debug buffer slightly usabler.
[minix.git] / servers / inet / sr.c
blob25e4282af222c836bc7710ee1f7bdb2aca24819b
1 /* this file contains the interface of the network software with the file
2 * system.
4 * Copyright 1995 Philip Homburg
6 * The valid messages and their parameters are:
7 *
8 * Requests:
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 * |-------------+-----------+-----------+-----------+----------+
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 * |-------------+-----------+-----------+-----------+-----------+-----------|
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 * |-------------+-----------+-----------+-----------+-----------+-----------|
29 * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_OPERATION
30 * -------------------------------------------------------------------|
31 * | DEV_CANCEL |minor dev | proc nr | fd | which operation|
32 * |-------------+-----------+-----------+-----------+----------------|
34 * Replies:
36 * m_type REP_PROC_NR REP_STATUS REP_REF REP_OPERATION
37 * ----------------------------------------------------------------------|
38 * | DEVICE_REPLY | proc nr | status | fd | which operation |
39 * |--------------+-------------+------------+---------+-----------------|
42 #include "inet.h"
44 #ifndef __minix_vmd /* Minix 3 */
45 #include <sys/select.h>
46 #endif
47 #include <sys/svrctl.h>
48 #include <minix/callnr.h>
50 #include "mq.h"
51 #include "qp.h"
52 #include "proto.h"
53 #include "generic/type.h"
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"
61 #ifndef __minix_vmd /* Minix 3 */
62 #define DEV_CANCEL NW_CANCEL
63 #define DEVICE_REPLY TASK_REPLY
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 IO_ENDPT
70 #endif
72 THIS_FILE
74 PUBLIC sr_fd_t sr_fd_table[FD_NR];
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 PRIVATE struct vscp_vec s_cp_req[CPVEC_NR];
82 #endif
84 FORWARD _PROTOTYPE ( int sr_open, (message *m) );
85 FORWARD _PROTOTYPE ( void sr_close, (message *m) );
86 FORWARD _PROTOTYPE ( int sr_rwio, (mq_t *m) );
87 FORWARD _PROTOTYPE ( int sr_rwio_s, (mq_t *m) );
88 FORWARD _PROTOTYPE ( int sr_restart_read, (sr_fd_t *fdp) );
89 FORWARD _PROTOTYPE ( int sr_restart_write, (sr_fd_t *fdp) );
90 FORWARD _PROTOTYPE ( int sr_restart_ioctl, (sr_fd_t *fdp) );
91 FORWARD _PROTOTYPE ( int sr_cancel, (message *m) );
92 #ifndef __minix_vmd /* Minix 3 */
93 FORWARD _PROTOTYPE ( int sr_select, (message *m) );
94 FORWARD _PROTOTYPE ( void sr_status, (message *m) );
95 #endif
96 FORWARD _PROTOTYPE ( void sr_reply_, (mq_t *m, int reply, int is_revive) );
97 FORWARD _PROTOTYPE ( sr_fd_t *sr_getchannel, (int minor));
98 FORWARD _PROTOTYPE ( acc_t *sr_get_userdata, (int fd, vir_bytes offset,
99 vir_bytes count, int for_ioctl) );
100 FORWARD _PROTOTYPE ( int sr_put_userdata, (int fd, vir_bytes offset,
101 acc_t *data, int for_ioctl) );
102 #ifdef __minix_vmd
103 #define sr_select_res 0
104 #else /* Minix 3 */
105 FORWARD _PROTOTYPE (void sr_select_res, (int fd, unsigned ops) );
106 #endif
107 FORWARD _PROTOTYPE ( int sr_repl_queue, (int proc, int ref, int operation) );
108 FORWARD _PROTOTYPE ( int walk_queue, (sr_fd_t *sr_fd, mq_t **q_head_ptr,
109 mq_t **q_tail_ptr, int type, int proc_nr, int ref, int first_flag) );
110 FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail,
111 mq_t **tail_ptr) );
112 FORWARD _PROTOTYPE ( void sr_event, (event_t *evp, ev_arg_t arg) );
113 FORWARD _PROTOTYPE ( int cp_u2b, (int proc, char *src, acc_t **var_acc_ptr,
114 int size) );
115 FORWARD _PROTOTYPE ( int cp_b2u, (acc_t *acc_ptr, int proc, char *dest) );
116 FORWARD _PROTOTYPE ( int cp_u2b_s, (int proc, int gid, vir_bytes offset,
117 acc_t **var_acc_ptr, int size) );
118 FORWARD _PROTOTYPE ( int cp_b2u_s, (acc_t *acc_ptr, int proc, int gid,
119 vir_bytes offset) );
121 PUBLIC void sr_init()
123 int i;
125 for (i=0; i<FD_NR; i++)
127 sr_fd_table[i].srf_flags= SFF_FREE;
128 ev_init(&sr_fd_table[i].srf_ioctl_ev);
129 ev_init(&sr_fd_table[i].srf_read_ev);
130 ev_init(&sr_fd_table[i].srf_write_ev);
132 repl_queue= NULL;
135 PUBLIC void sr_rec(m)
136 mq_t *m;
138 int result;
139 int send_reply, free_mess;
141 if (repl_queue)
143 if (m->mq_mess.m_type == DEV_CANCEL)
145 #ifdef __minix_vmd
146 result= sr_repl_queue(m->mq_mess.NDEV_PROC,
147 m->mq_mess.NDEV_REF,
148 m->mq_mess.NDEV_OPERATION);
149 #else /* Minix 3 */
150 result= sr_repl_queue(m->mq_mess.IO_ENDPT,
151 (int)m->mq_mess.IO_GRANT, 0);
152 #endif
153 if (result)
155 mq_free(m);
156 return; /* canceled request in queue */
159 #if 0
160 else
161 sr_repl_queue(ANY, 0, 0);
162 #endif
165 switch (m->mq_mess.m_type)
167 case DEV_OPEN:
168 result= sr_open(&m->mq_mess);
169 send_reply= 1;
170 free_mess= 1;
171 break;
172 case DEV_CLOSE:
173 sr_close(&m->mq_mess);
174 result= OK;
175 send_reply= 1;
176 free_mess= 1;
177 break;
178 #ifdef DEV_READ
179 case DEV_READ:
180 case DEV_WRITE:
181 case DEV_IOCTL3:
182 result= sr_rwio(m);
183 assert(result == OK || result == SUSPEND);
184 send_reply= (result == SUSPEND);
185 free_mess= 0;
186 break;
187 #endif
188 case DEV_READ_S:
189 case DEV_WRITE_S:
190 case DEV_IOCTL_S:
191 result= sr_rwio_s(m);
192 assert(result == OK || result == SUSPEND);
193 send_reply= (result == SUSPEND);
194 free_mess= 0;
195 break;
196 case DEV_CANCEL:
197 result= sr_cancel(&m->mq_mess);
198 assert(result == OK || result == EINTR);
199 send_reply= (result == EINTR);
200 free_mess= 1;
201 #ifdef __minix_vmd
202 m->mq_mess.m_type= m->mq_mess.NDEV_OPERATION;
203 #else /* Minix 3 */
204 m->mq_mess.m_type= 0;
205 #endif
206 break;
207 #ifndef __minix_vmd /* Minix 3 */
208 case DEV_SELECT:
209 result= sr_select(&m->mq_mess);
210 send_reply= 1;
211 free_mess= 1;
212 break;
213 case DEV_STATUS:
214 sr_status(&m->mq_mess);
215 send_reply= 0;
216 free_mess= 1;
217 break;
218 #endif
219 default:
220 ip_panic(("unknown message, from %d, type %d",
221 m->mq_mess.m_source, m->mq_mess.m_type));
223 if (send_reply)
225 sr_reply_(m, result, FALSE /* !is_revive */);
227 if (free_mess)
228 mq_free(m);
231 PUBLIC void sr_add_minor(minor, port, openf, closef, readf, writef,
232 ioctlf, cancelf, selectf)
233 int minor;
234 int port;
235 sr_open_t openf;
236 sr_close_t closef;
237 sr_read_t readf;
238 sr_write_t writef;
239 sr_ioctl_t ioctlf;
240 sr_cancel_t cancelf;
241 sr_select_t selectf;
243 sr_fd_t *sr_fd;
245 assert (minor>=0 && minor<FD_NR);
247 sr_fd= &sr_fd_table[minor];
249 assert(!(sr_fd->srf_flags & SFF_INUSE));
251 sr_fd->srf_flags= SFF_INUSE | SFF_MINOR;
252 sr_fd->srf_port= port;
253 sr_fd->srf_open= openf;
254 sr_fd->srf_close= closef;
255 sr_fd->srf_write= writef;
256 sr_fd->srf_read= readf;
257 sr_fd->srf_ioctl= ioctlf;
258 sr_fd->srf_cancel= cancelf;
259 sr_fd->srf_select= selectf;
262 PRIVATE int sr_open(m)
263 message *m;
265 sr_fd_t *sr_fd;
267 int minor= m->NDEV_MINOR;
268 int i, fd;
270 if (minor<0 || minor>FD_NR)
272 DBLOCK(1, printf("replying EINVAL\n"));
273 return EINVAL;
275 if (!(sr_fd_table[minor].srf_flags & SFF_MINOR))
277 DBLOCK(1, printf("replying ENXIO\n"));
278 return ENXIO;
280 for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++);
282 if (i>=FD_NR)
284 DBLOCK(1, printf("replying ENFILE\n"));
285 return ENFILE;
288 sr_fd= &sr_fd_table[i];
289 *sr_fd= sr_fd_table[minor];
290 sr_fd->srf_flags= SFF_INUSE;
291 fd= (*sr_fd->srf_open)(sr_fd->srf_port, i, sr_get_userdata,
292 sr_put_userdata, 0 /* no put_pkt */, sr_select_res);
293 if (fd<0)
295 sr_fd->srf_flags= SFF_FREE;
296 DBLOCK(1, printf("replying %d\n", fd));
297 return fd;
299 sr_fd->srf_fd= fd;
300 return i;
303 PRIVATE void sr_close(m)
304 message *m;
306 sr_fd_t *sr_fd;
308 sr_fd= sr_getchannel(m->NDEV_MINOR);
309 assert (sr_fd);
311 if (sr_fd->srf_flags & SFF_BUSY)
312 ip_panic(("close on busy channel"));
314 assert (!(sr_fd->srf_flags & SFF_MINOR));
315 (*sr_fd->srf_close)(sr_fd->srf_fd);
316 sr_fd->srf_flags= SFF_FREE;
319 PRIVATE int sr_rwio(m)
320 mq_t *m;
322 sr_fd_t *sr_fd;
323 mq_t **q_head_ptr, **q_tail_ptr;
324 int ip_flag, susp_flag, first_flag;
325 int r;
326 ioreq_t request;
327 size_t size;
329 sr_fd= sr_getchannel(m->mq_mess.NDEV_MINOR);
330 assert (sr_fd);
332 switch(m->mq_mess.m_type)
334 #ifdef DEV_READ
335 case DEV_READ:
336 q_head_ptr= &sr_fd->srf_read_q;
337 q_tail_ptr= &sr_fd->srf_read_q_tail;
338 ip_flag= SFF_READ_IP;
339 susp_flag= SFF_READ_SUSP;
340 first_flag= SFF_READ_FIRST;
341 break;
342 case DEV_WRITE:
343 q_head_ptr= &sr_fd->srf_write_q;
344 q_tail_ptr= &sr_fd->srf_write_q_tail;
345 ip_flag= SFF_WRITE_IP;
346 susp_flag= SFF_WRITE_SUSP;
347 first_flag= SFF_WRITE_FIRST;
348 break;
349 case DEV_IOCTL3:
350 q_head_ptr= &sr_fd->srf_ioctl_q;
351 q_tail_ptr= &sr_fd->srf_ioctl_q_tail;
352 ip_flag= SFF_IOCTL_IP;
353 susp_flag= SFF_IOCTL_SUSP;
354 first_flag= SFF_IOCTL_FIRST;
355 break;
356 #endif
357 default:
358 ip_panic(("illegal case entry"));
361 if (sr_fd->srf_flags & ip_flag)
363 assert(sr_fd->srf_flags & susp_flag);
364 assert(*q_head_ptr);
366 (*q_tail_ptr)->mq_next= m;
367 *q_tail_ptr= m;
368 return SUSPEND;
370 assert(!*q_head_ptr);
372 *q_tail_ptr= *q_head_ptr= m;
373 sr_fd->srf_flags |= ip_flag;
374 assert(!(sr_fd->srf_flags & first_flag));
375 sr_fd->srf_flags |= first_flag;
377 switch(m->mq_mess.m_type)
379 #ifdef DEV_READ
380 case DEV_READ:
381 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
382 m->mq_mess.NDEV_COUNT);
383 break;
384 case DEV_WRITE:
385 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
386 m->mq_mess.NDEV_COUNT);
387 break;
388 case DEV_IOCTL3:
389 request= m->mq_mess.NDEV_IOCTL;
390 size= (request >> 16) & _IOCPARM_MASK;
391 if (size>MAX_IOCTL_S)
393 DBLOCK(1, printf("replying EINVAL\n"));
394 r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL,
395 NULL, 1);
396 assert(r == OK);
397 assert(sr_fd->srf_flags & first_flag);
398 sr_fd->srf_flags &= ~first_flag;
399 return OK;
401 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
402 break;
403 #endif
404 default:
405 ip_panic(("illegal case entry"));
408 assert(sr_fd->srf_flags & first_flag);
409 sr_fd->srf_flags &= ~first_flag;
411 assert(r == OK || r == SUSPEND ||
412 (printf("r= %d\n", r), 0));
413 if (r == SUSPEND)
414 sr_fd->srf_flags |= susp_flag;
415 else
416 mq_free(m);
417 return r;
420 PRIVATE int sr_rwio_s(m)
421 mq_t *m;
423 sr_fd_t *sr_fd;
424 mq_t **q_head_ptr, **q_tail_ptr;
425 int ip_flag, susp_flag, first_flag;
426 int r;
427 ioreq_t request;
428 size_t size;
430 sr_fd= sr_getchannel(m->mq_mess.NDEV_MINOR);
431 assert (sr_fd);
433 switch(m->mq_mess.m_type)
435 case DEV_READ_S:
436 q_head_ptr= &sr_fd->srf_read_q;
437 q_tail_ptr= &sr_fd->srf_read_q_tail;
438 ip_flag= SFF_READ_IP;
439 susp_flag= SFF_READ_SUSP;
440 first_flag= SFF_READ_FIRST;
441 break;
442 case DEV_WRITE_S:
443 q_head_ptr= &sr_fd->srf_write_q;
444 q_tail_ptr= &sr_fd->srf_write_q_tail;
445 ip_flag= SFF_WRITE_IP;
446 susp_flag= SFF_WRITE_SUSP;
447 first_flag= SFF_WRITE_FIRST;
448 break;
449 case DEV_IOCTL_S:
450 q_head_ptr= &sr_fd->srf_ioctl_q;
451 q_tail_ptr= &sr_fd->srf_ioctl_q_tail;
452 ip_flag= SFF_IOCTL_IP;
453 susp_flag= SFF_IOCTL_SUSP;
454 first_flag= SFF_IOCTL_FIRST;
455 break;
456 default:
457 ip_panic(("illegal case entry"));
460 if (sr_fd->srf_flags & ip_flag)
462 assert(sr_fd->srf_flags & susp_flag);
463 assert(*q_head_ptr);
465 (*q_tail_ptr)->mq_next= m;
466 *q_tail_ptr= m;
467 return SUSPEND;
469 assert(!*q_head_ptr);
471 *q_tail_ptr= *q_head_ptr= m;
472 sr_fd->srf_flags |= ip_flag;
473 assert(!(sr_fd->srf_flags & first_flag));
474 sr_fd->srf_flags |= first_flag;
476 switch(m->mq_mess.m_type)
478 case DEV_READ_S:
479 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
480 m->mq_mess.NDEV_COUNT);
481 break;
482 case DEV_WRITE_S:
483 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
484 m->mq_mess.NDEV_COUNT);
485 break;
486 case DEV_IOCTL_S:
487 request= m->mq_mess.NDEV_IOCTL;
488 size= (request >> 16) & _IOCPARM_MASK;
489 if (size>MAX_IOCTL_S)
491 DBLOCK(1, printf("replying EINVAL\n"));
492 r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL,
493 NULL, 1);
494 assert(r == OK);
495 assert(sr_fd->srf_flags & first_flag);
496 sr_fd->srf_flags &= ~first_flag;
497 return OK;
499 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
500 break;
501 default:
502 ip_panic(("illegal case entry"));
505 assert(sr_fd->srf_flags & first_flag);
506 sr_fd->srf_flags &= ~first_flag;
508 assert(r == OK || r == SUSPEND ||
509 (printf("r= %d\n", r), 0));
510 if (r == SUSPEND)
511 sr_fd->srf_flags |= susp_flag;
512 else
513 mq_free(m);
514 return r;
517 PRIVATE int sr_restart_read(sr_fd)
518 sr_fd_t *sr_fd;
520 mq_t *mp;
521 int r;
523 mp= sr_fd->srf_read_q;
524 assert(mp);
526 if (sr_fd->srf_flags & SFF_READ_IP)
528 assert(sr_fd->srf_flags & SFF_READ_SUSP);
529 return SUSPEND;
531 sr_fd->srf_flags |= SFF_READ_IP;
533 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
534 mp->mq_mess.NDEV_COUNT);
536 assert(r == OK || r == SUSPEND ||
537 (printf("r= %d\n", r), 0));
538 if (r == SUSPEND)
539 sr_fd->srf_flags |= SFF_READ_SUSP;
540 return r;
543 PRIVATE int sr_restart_write(sr_fd)
544 sr_fd_t *sr_fd;
546 mq_t *mp;
547 int r;
549 mp= sr_fd->srf_write_q;
550 assert(mp);
552 if (sr_fd->srf_flags & SFF_WRITE_IP)
554 assert(sr_fd->srf_flags & SFF_WRITE_SUSP);
555 return SUSPEND;
557 sr_fd->srf_flags |= SFF_WRITE_IP;
559 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
560 mp->mq_mess.NDEV_COUNT);
562 assert(r == OK || r == SUSPEND ||
563 (printf("r= %d\n", r), 0));
564 if (r == SUSPEND)
565 sr_fd->srf_flags |= SFF_WRITE_SUSP;
566 return r;
569 PRIVATE int sr_restart_ioctl(sr_fd)
570 sr_fd_t *sr_fd;
572 mq_t *mp;
573 int r;
575 mp= sr_fd->srf_ioctl_q;
576 assert(mp);
578 if (sr_fd->srf_flags & SFF_IOCTL_IP)
580 assert(sr_fd->srf_flags & SFF_IOCTL_SUSP);
581 return SUSPEND;
583 sr_fd->srf_flags |= SFF_IOCTL_IP;
585 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd,
586 mp->mq_mess.NDEV_COUNT);
588 assert(r == OK || r == SUSPEND ||
589 (printf("r= %d\n", r), 0));
590 if (r == SUSPEND)
591 sr_fd->srf_flags |= SFF_IOCTL_SUSP;
592 return r;
595 PRIVATE int sr_cancel(m)
596 message *m;
598 sr_fd_t *sr_fd;
599 int result;
600 int proc_nr, ref, operation;
602 result=EINTR;
603 proc_nr= m->NDEV_PROC;
604 #ifdef __minix_vmd
605 ref= m->NDEV_REF;
606 operation= m->NDEV_OPERATION;
607 #else /* Minix 3 */
608 ref= (int)m->IO_GRANT;
609 operation= 0;
610 #endif
611 sr_fd= sr_getchannel(m->NDEV_MINOR);
612 assert (sr_fd);
614 #ifdef __minix_vmd
615 if (operation == CANCEL_ANY || operation == DEV_IOCTL3)
616 #endif
618 result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q,
619 &sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL,
620 proc_nr, ref, SFF_IOCTL_FIRST);
621 if (result != EAGAIN)
622 return result;
624 #ifdef __minix_vmd
625 if (operation == CANCEL_ANY || operation == DEV_READ)
626 #endif
628 result= walk_queue(sr_fd, &sr_fd->srf_read_q,
629 &sr_fd->srf_read_q_tail, SR_CANCEL_READ,
630 proc_nr, ref, SFF_READ_FIRST);
631 if (result != EAGAIN)
632 return result;
634 #ifdef __minix_vmd
635 if (operation == CANCEL_ANY || operation == DEV_WRITE)
636 #endif
638 result= walk_queue(sr_fd, &sr_fd->srf_write_q,
639 &sr_fd->srf_write_q_tail, SR_CANCEL_WRITE,
640 proc_nr, ref, SFF_WRITE_FIRST);
641 if (result != EAGAIN)
642 return result;
644 #ifdef __minix_vmd
645 ip_panic((
646 "request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d OPERATION= %ld",
647 m->m_source, m->m_type, m->NDEV_MINOR,
648 m->NDEV_PROC, m->NDEV_REF, m->NDEV_OPERATION));
649 #else /* Minix 3 */
650 ip_panic((
651 "request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d",
652 m->m_source, m->m_type, m->NDEV_MINOR,
653 m->NDEV_PROC, m->IO_GRANT));
654 #endif
657 #ifndef __minix_vmd /* Minix 3 */
658 PRIVATE int sr_select(m)
659 message *m;
661 sr_fd_t *sr_fd;
662 mq_t **q_head_ptr, **q_tail_ptr;
663 int ip_flag, susp_flag;
664 int r, ops;
665 unsigned m_ops, i_ops;
666 ioreq_t request;
667 size_t size;
669 sr_fd= sr_getchannel(m->NDEV_MINOR);
670 assert (sr_fd);
672 sr_fd->srf_select_proc= m->m_source;
674 m_ops= m->IO_ENDPT;
675 i_ops= 0;
676 if (m_ops & SEL_RD) i_ops |= SR_SELECT_READ;
677 if (m_ops & SEL_WR) i_ops |= SR_SELECT_WRITE;
678 if (m_ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION;
679 if (!(m_ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
681 r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
682 if (r < 0)
683 return r;
684 m_ops= 0;
685 if (r & SR_SELECT_READ) m_ops |= SEL_RD;
686 if (r & SR_SELECT_WRITE) m_ops |= SEL_WR;
687 if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
689 return m_ops;
692 PRIVATE void sr_status(m)
693 message *m;
695 int fd, result;
696 unsigned m_ops;
697 sr_fd_t *sr_fd;
698 mq_t *mq;
700 mq= repl_queue;
701 if (mq != NULL)
703 repl_queue= mq->mq_next;
705 mq->mq_mess.m_type= DEV_REVIVE;
706 result= send(mq->mq_mess.m_source, &mq->mq_mess);
707 if (result != OK)
708 ip_panic(("unable to send"));
709 mq_free(mq);
711 return;
714 for (fd=0, sr_fd= sr_fd_table; fd<FD_NR; fd++, sr_fd++)
716 if ((sr_fd->srf_flags &
717 (SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X)) == 0)
719 /* Nothing to report */
720 continue;
722 if (sr_fd->srf_select_proc != m->m_source)
724 /* Wrong process */
725 continue;
728 m_ops= 0;
729 if (sr_fd->srf_flags & SFF_SELECT_R) m_ops |= SEL_RD;
730 if (sr_fd->srf_flags & SFF_SELECT_W) m_ops |= SEL_WR;
731 if (sr_fd->srf_flags & SFF_SELECT_X) m_ops |= SEL_ERR;
733 sr_fd->srf_flags &= ~(SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X);
735 m->m_type= DEV_IO_READY;
736 m->DEV_MINOR= fd;
737 m->DEV_SEL_OPS= m_ops;
739 result= send(m->m_source, m);
740 if (result != OK)
741 ip_panic(("unable to send"));
742 return;
745 m->m_type= DEV_NO_STATUS;
746 result= send(m->m_source, m);
747 if (result != OK)
748 ip_panic(("unable to send"));
750 #endif
752 PRIVATE int walk_queue(sr_fd, q_head_ptr, q_tail_ptr, type, proc_nr, ref,
753 first_flag)
754 sr_fd_t *sr_fd;
755 mq_t **q_head_ptr;
756 mq_t **q_tail_ptr;
757 int type;
758 int proc_nr;
759 int ref;
760 int first_flag;
762 mq_t *q_ptr_prv, *q_ptr;
763 int result;
765 for(q_ptr_prv= NULL, q_ptr= *q_head_ptr; q_ptr;
766 q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
768 if (q_ptr->mq_mess.NDEV_PROC != proc_nr)
769 continue;
770 #ifdef __minix_vmd
771 if (q_ptr->mq_mess.NDEV_REF != ref)
772 continue;
773 #else
774 if ((int)q_ptr->mq_mess.IO_GRANT != ref)
775 continue;
776 #endif
777 if (!q_ptr_prv)
779 assert(!(sr_fd->srf_flags & first_flag));
780 sr_fd->srf_flags |= first_flag;
782 result= (*sr_fd->srf_cancel)(sr_fd->srf_fd, type);
783 assert(result == OK);
785 *q_head_ptr= q_ptr->mq_next;
786 mq_free(q_ptr);
788 assert(sr_fd->srf_flags & first_flag);
789 sr_fd->srf_flags &= ~first_flag;
791 return OK;
793 q_ptr_prv->mq_next= q_ptr->mq_next;
794 mq_free(q_ptr);
795 if (!q_ptr_prv->mq_next)
796 *q_tail_ptr= q_ptr_prv;
797 return EINTR;
799 return EAGAIN;
802 PRIVATE sr_fd_t *sr_getchannel(minor)
803 int minor;
805 sr_fd_t *loc_fd;
807 compare(minor, >=, 0);
808 compare(minor, <, FD_NR);
810 loc_fd= &sr_fd_table[minor];
812 assert (!(loc_fd->srf_flags & SFF_MINOR) &&
813 (loc_fd->srf_flags & SFF_INUSE));
815 return loc_fd;
818 PRIVATE void sr_reply_(mq, status, is_revive)
819 mq_t *mq;
820 int status;
821 int is_revive;
823 int result, proc, ref,operation;
824 message reply, *mp;
826 proc= mq->mq_mess.NDEV_PROC;
827 #ifdef __minix_vmd
828 ref= mq->mq_mess.NDEV_REF;
829 #else /* Minix 3 */
830 ref= (int)mq->mq_mess.IO_GRANT;
831 #endif
832 operation= mq->mq_mess.m_type;
833 #ifdef __minix_vmd
834 assert(operation != DEV_CANCEL);
835 #endif
837 if (is_revive)
838 mp= &mq->mq_mess;
839 else
840 mp= &reply;
842 mp->m_type= DEVICE_REPLY;
843 mp->REP_ENDPT= proc;
844 mp->REP_STATUS= status;
845 #ifdef __minix_vmd
846 mp->REP_REF= ref;
847 mp->REP_OPERATION= operation;
848 #else
849 mp->REP_IO_GRANT= ref;
850 #endif
851 if (is_revive)
853 notify(mq->mq_mess.m_source);
854 result= ELOCKED;
856 else
858 result= send(mq->mq_mess.m_source, mp);
861 if (result == ELOCKED && is_revive)
863 mq->mq_next= NULL;
864 if (repl_queue)
865 repl_queue_tail->mq_next= mq;
866 else
867 repl_queue= mq;
868 repl_queue_tail= mq;
869 return;
871 if (result != OK)
872 ip_panic(("unable to send"));
873 if (is_revive)
874 mq_free(mq);
877 PRIVATE acc_t *sr_get_userdata (fd, offset, count, for_ioctl)
878 int fd;
879 vir_bytes offset;
880 vir_bytes count;
881 int for_ioctl;
883 sr_fd_t *loc_fd;
884 mq_t **head_ptr, *m, *mq;
885 int ip_flag, susp_flag, first_flag, m_type, safe_copy;
886 int result, suspended, is_revive;
887 char *src;
888 acc_t *acc;
889 event_t *evp;
890 ev_arg_t arg;
892 loc_fd= &sr_fd_table[fd];
894 if (for_ioctl)
896 head_ptr= &loc_fd->srf_ioctl_q;
897 evp= &loc_fd->srf_ioctl_ev;
898 ip_flag= SFF_IOCTL_IP;
899 susp_flag= SFF_IOCTL_SUSP;
900 first_flag= SFF_IOCTL_FIRST;
902 else
904 head_ptr= &loc_fd->srf_write_q;
905 evp= &loc_fd->srf_write_ev;
906 ip_flag= SFF_WRITE_IP;
907 susp_flag= SFF_WRITE_SUSP;
908 first_flag= SFF_WRITE_FIRST;
911 assert (loc_fd->srf_flags & ip_flag);
913 if (!count)
915 m= *head_ptr;
916 mq= m->mq_next;
917 *head_ptr= mq;
918 result= (int)offset;
919 is_revive= !(loc_fd->srf_flags & first_flag);
920 sr_reply_(m, result, is_revive);
921 suspended= (loc_fd->srf_flags & susp_flag);
922 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
923 if (suspended)
925 if (mq)
927 arg.ev_ptr= loc_fd;
928 ev_enqueue(evp, sr_event, arg);
931 return NULL;
934 m_type= (*head_ptr)->mq_mess.m_type;
935 if (m_type == DEV_READ_S || m_type == DEV_WRITE_S ||
936 m_type == DEV_IOCTL_S)
938 safe_copy= 1;
940 else
942 #ifdef DEV_READ
943 assert(m_type == DEV_READ || m_type == DEV_WRITE ||
944 m_type == DEV_IOCTL);
945 #else
946 ip_panic(("sr_get_userdata: m_type not *_S\n"));
947 #endif
948 safe_copy= 0;
951 if (safe_copy)
953 result= cp_u2b_s ((*head_ptr)->mq_mess.NDEV_PROC,
954 (int)(*head_ptr)->mq_mess.NDEV_BUFFER, offset, &acc,
955 count);
957 else
959 src= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
960 result= cp_u2b ((*head_ptr)->mq_mess.NDEV_PROC, src, &acc,
961 count);
964 return result<0 ? NULL : acc;
967 PRIVATE int sr_put_userdata (fd, offset, data, for_ioctl)
968 int fd;
969 vir_bytes offset;
970 acc_t *data;
971 int for_ioctl;
973 sr_fd_t *loc_fd;
974 mq_t **head_ptr, *m, *mq;
975 int ip_flag, susp_flag, first_flag, m_type, safe_copy;
976 int result, suspended, is_revive;
977 char *dst;
978 event_t *evp;
979 ev_arg_t arg;
981 loc_fd= &sr_fd_table[fd];
983 if (for_ioctl)
985 head_ptr= &loc_fd->srf_ioctl_q;
986 evp= &loc_fd->srf_ioctl_ev;
987 ip_flag= SFF_IOCTL_IP;
988 susp_flag= SFF_IOCTL_SUSP;
989 first_flag= SFF_IOCTL_FIRST;
991 else
993 head_ptr= &loc_fd->srf_read_q;
994 evp= &loc_fd->srf_read_ev;
995 ip_flag= SFF_READ_IP;
996 susp_flag= SFF_READ_SUSP;
997 first_flag= SFF_READ_FIRST;
1000 assert (loc_fd->srf_flags & ip_flag);
1002 if (!data)
1004 m= *head_ptr;
1005 mq= m->mq_next;
1006 *head_ptr= mq;
1007 result= (int)offset;
1008 is_revive= !(loc_fd->srf_flags & first_flag);
1009 sr_reply_(m, result, is_revive);
1010 suspended= (loc_fd->srf_flags & susp_flag);
1011 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
1012 if (suspended)
1014 if (mq)
1016 arg.ev_ptr= loc_fd;
1017 ev_enqueue(evp, sr_event, arg);
1020 return OK;
1023 m_type= (*head_ptr)->mq_mess.m_type;
1024 if (m_type == DEV_READ_S || m_type == DEV_WRITE_S ||
1025 m_type == DEV_IOCTL_S)
1027 safe_copy= 1;
1029 else
1031 #ifdef DEV_READ
1032 assert(m_type == DEV_READ || m_type == DEV_WRITE ||
1033 m_type == DEV_IOCTL);
1034 #else
1035 ip_panic(("sr_put_userdata: m_type not *_S\n"));
1036 #endif
1037 safe_copy= 0;
1040 if (safe_copy)
1042 return cp_b2u_s (data, (*head_ptr)->mq_mess.NDEV_PROC,
1043 (int)(*head_ptr)->mq_mess.NDEV_BUFFER, offset);
1045 else
1047 dst= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
1048 return cp_b2u (data, (*head_ptr)->mq_mess.NDEV_PROC, dst);
1052 #ifndef __minix_vmd /* Minix 3 */
1053 PRIVATE void sr_select_res(fd, ops)
1054 int fd;
1055 unsigned ops;
1057 sr_fd_t *sr_fd;
1059 sr_fd= &sr_fd_table[fd];
1061 if (ops & SR_SELECT_READ) sr_fd->srf_flags |= SFF_SELECT_R;
1062 if (ops & SR_SELECT_WRITE) sr_fd->srf_flags |= SFF_SELECT_W;
1063 if (ops & SR_SELECT_EXCEPTION) sr_fd->srf_flags |= SFF_SELECT_X;
1065 notify(sr_fd->srf_select_proc);
1067 #endif
1069 PRIVATE void process_req_q(mq, tail, tail_ptr)
1070 mq_t *mq, *tail, **tail_ptr;
1072 mq_t *m;
1073 int result;
1075 for(;mq;)
1077 m= mq;
1078 mq= mq->mq_next;
1080 result= sr_rwio(m);
1081 if (result == SUSPEND)
1083 if (mq)
1085 (*tail_ptr)->mq_next= mq;
1086 *tail_ptr= tail;
1088 return;
1091 return;
1094 PRIVATE void sr_event(evp, arg)
1095 event_t *evp;
1096 ev_arg_t arg;
1098 sr_fd_t *sr_fd;
1099 int r;
1101 sr_fd= arg.ev_ptr;
1102 if (evp == &sr_fd->srf_write_ev)
1104 while(sr_fd->srf_write_q)
1106 r= sr_restart_write(sr_fd);
1107 if (r == SUSPEND)
1108 return;
1110 return;
1112 if (evp == &sr_fd->srf_read_ev)
1114 while(sr_fd->srf_read_q)
1116 r= sr_restart_read(sr_fd);
1117 if (r == SUSPEND)
1118 return;
1120 return;
1122 if (evp == &sr_fd->srf_ioctl_ev)
1124 while(sr_fd->srf_ioctl_q)
1126 r= sr_restart_ioctl(sr_fd);
1127 if (r == SUSPEND)
1128 return;
1130 return;
1132 ip_panic(("sr_event: unkown event\n"));
1135 PRIVATE int cp_u2b (proc, src, var_acc_ptr, size)
1136 int proc;
1137 char *src;
1138 acc_t **var_acc_ptr;
1139 int size;
1141 static message mess;
1142 acc_t *acc;
1143 int i;
1145 acc= bf_memreq(size);
1147 *var_acc_ptr= acc;
1148 i=0;
1150 while (acc)
1152 size= (vir_bytes)acc->acc_length;
1154 #ifdef __minix_vmd
1155 cpvec[i].cpv_src= (vir_bytes)src;
1156 cpvec[i].cpv_dst= (vir_bytes)ptr2acc_data(acc);
1157 cpvec[i].cpv_size= size;
1158 #else /* Minix 3 */
1159 vir_cp_req[i].count= size;
1160 vir_cp_req[i].src.proc_nr_e = proc;
1161 vir_cp_req[i].src.segment = D;
1162 vir_cp_req[i].src.offset = (vir_bytes) src;
1163 vir_cp_req[i].dst.proc_nr_e = this_proc;
1164 vir_cp_req[i].dst.segment = D;
1165 vir_cp_req[i].dst.offset = (vir_bytes) ptr2acc_data(acc);
1166 #endif
1168 src += size;
1169 acc= acc->acc_next;
1170 i++;
1172 if (i == CPVEC_NR || acc == NULL)
1174 #ifdef __minix_vmd
1175 mess.m_type= SYS_VCOPY;
1176 mess.m1_i1= proc;
1177 mess.m1_i2= this_proc;
1178 mess.m1_i3= i;
1179 mess.m1_p1= (char *)cpvec;
1180 #else /* Minix 3 */
1181 mess.m_type= SYS_VIRVCOPY;
1182 mess.VCP_VEC_SIZE= i;
1183 mess.VCP_VEC_ADDR= (char *)vir_cp_req;
1184 #endif
1185 if (sendrec(SYSTASK, &mess) <0)
1186 ip_panic(("unable to sendrec"));
1187 if (mess.m_type <0)
1189 bf_afree(*var_acc_ptr);
1190 *var_acc_ptr= 0;
1191 return mess.m_type;
1193 i= 0;
1196 return OK;
1199 PRIVATE int cp_b2u (acc_ptr, proc, dest)
1200 acc_t *acc_ptr;
1201 int proc;
1202 char *dest;
1204 static message mess;
1205 acc_t *acc;
1206 int i, size;
1208 acc= acc_ptr;
1209 i=0;
1211 while (acc)
1213 size= (vir_bytes)acc->acc_length;
1215 if (size)
1217 #ifdef __minix_vmd
1218 cpvec[i].cpv_src= (vir_bytes)ptr2acc_data(acc);
1219 cpvec[i].cpv_dst= (vir_bytes)dest;
1220 cpvec[i].cpv_size= size;
1221 #else /* Minix 3 */
1222 vir_cp_req[i].src.proc_nr_e = this_proc;
1223 vir_cp_req[i].src.segment = D;
1224 vir_cp_req[i].src.offset= (vir_bytes)ptr2acc_data(acc);
1225 vir_cp_req[i].dst.proc_nr_e = proc;
1226 vir_cp_req[i].dst.segment = D;
1227 vir_cp_req[i].dst.offset= (vir_bytes)dest;
1228 vir_cp_req[i].count= size;
1229 #endif
1230 i++;
1233 dest += size;
1234 acc= acc->acc_next;
1236 if (i == CPVEC_NR || acc == NULL)
1238 #ifdef __minix_vmd
1239 mess.m_type= SYS_VCOPY;
1240 mess.m1_i1= this_proc;
1241 mess.m1_i2= proc;
1242 mess.m1_i3= i;
1243 mess.m1_p1= (char *)cpvec;
1244 #else /* Minix 3 */
1245 mess.m_type= SYS_VIRVCOPY;
1246 mess.VCP_VEC_SIZE= i;
1247 mess.VCP_VEC_ADDR= (char *) vir_cp_req;
1248 #endif
1249 if (sendrec(SYSTASK, &mess) <0)
1250 ip_panic(("unable to sendrec"));
1251 if (mess.m_type <0)
1253 bf_afree(acc_ptr);
1254 return mess.m_type;
1256 i= 0;
1259 bf_afree(acc_ptr);
1260 return OK;
1263 PRIVATE int cp_u2b_s(proc, gid, offset, var_acc_ptr, size)
1264 int proc;
1265 int gid;
1266 vir_bytes offset;
1267 acc_t **var_acc_ptr;
1268 int size;
1270 acc_t *acc;
1271 int i, r;
1273 acc= bf_memreq(size);
1275 *var_acc_ptr= acc;
1276 i=0;
1278 while (acc)
1280 size= (vir_bytes)acc->acc_length;
1282 s_cp_req[i].v_from= proc;
1283 s_cp_req[i].v_to= SELF;
1284 s_cp_req[i].v_gid= gid;
1285 s_cp_req[i].v_offset= offset;
1286 s_cp_req[i].v_addr= (vir_bytes) ptr2acc_data(acc);
1287 s_cp_req[i].v_bytes= size;
1289 offset += size;
1290 acc= acc->acc_next;
1291 i++;
1293 if (acc == NULL && i == 1)
1295 r= sys_safecopyfrom(s_cp_req[0].v_from,
1296 s_cp_req[0].v_gid, s_cp_req[0].v_offset,
1297 s_cp_req[0].v_addr, s_cp_req[0].v_bytes, D);
1298 if (r <0)
1300 printf("sys_safecopyfrom failed: %d\n", r);
1301 bf_afree(*var_acc_ptr);
1302 *var_acc_ptr= 0;
1303 return r;
1305 i= 0;
1306 continue;
1308 if (i == CPVEC_NR || acc == NULL)
1310 r= sys_vsafecopy(s_cp_req, i);
1312 if (r <0)
1314 printf("cp_u2b_s: sys_vsafecopy failed: %d\n",
1316 bf_afree(*var_acc_ptr);
1317 *var_acc_ptr= 0;
1318 return r;
1320 i= 0;
1323 return OK;
1326 PRIVATE int cp_b2u_s(acc_ptr, proc, gid, offset)
1327 acc_t *acc_ptr;
1328 int proc;
1329 int gid;
1330 vir_bytes offset;
1332 acc_t *acc;
1333 int i, r, size;
1335 acc= acc_ptr;
1336 i=0;
1338 while (acc)
1340 size= (vir_bytes)acc->acc_length;
1342 if (size)
1344 s_cp_req[i].v_from= SELF;
1345 s_cp_req[i].v_to= proc;
1346 s_cp_req[i].v_gid= gid;
1347 s_cp_req[i].v_offset= offset;
1348 s_cp_req[i].v_addr= (vir_bytes) ptr2acc_data(acc);
1349 s_cp_req[i].v_bytes= size;
1351 i++;
1354 offset += size;
1355 acc= acc->acc_next;
1357 if (acc == NULL && i == 1)
1359 r= sys_safecopyto(s_cp_req[0].v_to,
1360 s_cp_req[0].v_gid, s_cp_req[0].v_offset,
1361 s_cp_req[0].v_addr, s_cp_req[0].v_bytes, D);
1362 if (r <0)
1364 printf("sys_safecopyto failed: %d\n", r);
1365 bf_afree(acc_ptr);
1366 return r;
1368 i= 0;
1369 continue;
1371 if (i == CPVEC_NR || acc == NULL)
1373 r= sys_vsafecopy(s_cp_req, i);
1375 if (r <0)
1377 printf("cp_b2u_s: sys_vsafecopy failed: %d\n",
1379 bf_afree(acc_ptr);
1380 return r;
1382 i= 0;
1385 bf_afree(acc_ptr);
1386 return OK;
1389 PRIVATE int sr_repl_queue(proc, ref, operation)
1390 int proc;
1391 int ref;
1392 int operation;
1394 mq_t *m, *m_cancel, *m_tmp;
1395 #ifndef __minix_vmd
1396 mq_t *new_queue;
1397 #endif
1398 int result;
1400 m_cancel= NULL;
1401 new_queue= NULL;
1403 for (m= repl_queue; m;)
1405 #ifdef __minix_vmd
1406 if (m->mq_mess.REP_ENDPT == proc &&
1407 m->mq_mess.REP_REF == ref &&
1408 (m->mq_mess.REP_OPERATION == operation ||
1409 operation == CANCEL_ANY))
1410 #else /* Minix 3 */
1411 if (m->mq_mess.REP_ENDPT == proc &&
1412 m->mq_mess.REP_IO_GRANT == ref)
1413 #endif
1415 assert(!m_cancel);
1416 m_cancel= m;
1417 m= m->mq_next;
1418 continue;
1420 #ifdef __minix_vmd
1421 result= send(m->mq_mess.m_source, &m->mq_mess);
1422 if (result != OK)
1423 ip_panic(("unable to send: %d", result));
1424 m_tmp= m;
1425 m= m->mq_next;
1426 mq_free(m_tmp);
1427 #else /* Minix 3 */
1428 m_tmp= m;
1429 m= m->mq_next;
1430 m_tmp->mq_next= new_queue;
1431 new_queue= m_tmp;
1432 #endif
1434 repl_queue= NULL;
1435 #ifndef __minix_vmd /* Minix 3 */
1436 repl_queue= new_queue;
1437 #endif
1438 if (m_cancel)
1440 result= send(m_cancel->mq_mess.m_source, &m_cancel->mq_mess);
1441 if (result != OK)
1442 ip_panic(("unable to send: %d", result));
1443 mq_free(m_cancel);
1444 return 1;
1446 return 0;
1450 * $PchId: sr.c,v 1.17 2005/06/28 14:26:16 philip Exp $