source: trunk/minix/servers/inet/sr.c@ 11

Last change on this file since 11 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 23.8 KB
Line 
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 IO_ENDPT
70#endif
71
72THIS_FILE
73
74PUBLIC sr_fd_t sr_fd_table[FD_NR];
75
76PRIVATE mq_t *repl_queue, *repl_queue_tail;
77#ifdef __minix_vmd
78PRIVATE cpvec_t cpvec[CPVEC_NR];
79#else /* Minix 3 */
80PRIVATE struct vir_cp_req vir_cp_req[CPVEC_NR];
81#endif
82
83FORWARD _PROTOTYPE ( int sr_open, (message *m) );
84FORWARD _PROTOTYPE ( void sr_close, (message *m) );
85FORWARD _PROTOTYPE ( int sr_rwio, (mq_t *m) );
86FORWARD _PROTOTYPE ( int sr_restart_read, (sr_fd_t *fdp) );
87FORWARD _PROTOTYPE ( int sr_restart_write, (sr_fd_t *fdp) );
88FORWARD _PROTOTYPE ( int sr_restart_ioctl, (sr_fd_t *fdp) );
89FORWARD _PROTOTYPE ( int sr_cancel, (message *m) );
90#ifndef __minix_vmd /* Minix 3 */
91FORWARD _PROTOTYPE ( int sr_select, (message *m) );
92FORWARD _PROTOTYPE ( void sr_status, (message *m) );
93#endif
94FORWARD _PROTOTYPE ( void sr_reply_, (mq_t *m, int reply, int is_revive) );
95FORWARD _PROTOTYPE ( sr_fd_t *sr_getchannel, (int minor));
96FORWARD _PROTOTYPE ( acc_t *sr_get_userdata, (int fd, vir_bytes offset,
97 vir_bytes count, int for_ioctl) );
98FORWARD _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 */
103FORWARD _PROTOTYPE (void sr_select_res, (int fd, unsigned ops) );
104#endif
105FORWARD _PROTOTYPE ( int sr_repl_queue, (int proc, int ref, int operation) );
106FORWARD _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) );
108FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail,
109 mq_t **tail_ptr) );
110FORWARD _PROTOTYPE ( void sr_event, (event_t *evp, ev_arg_t arg) );
111FORWARD _PROTOTYPE ( int cp_u2b, (int proc, char *src, acc_t **var_acc_ptr,
112 int size) );
113FORWARD _PROTOTYPE ( int cp_b2u, (acc_t *acc_ptr, int proc, char *dest) );
114
115PUBLIC 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
129PUBLIC void sr_rec(m)
130mq_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.IO_ENDPT, 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
214PUBLIC void sr_add_minor(minor, port, openf, closef, readf, writef,
215 ioctlf, cancelf, selectf)
216int minor;
217int port;
218sr_open_t openf;
219sr_close_t closef;
220sr_read_t readf;
221sr_write_t writef;
222sr_ioctl_t ioctlf;
223sr_cancel_t cancelf;
224sr_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
245PRIVATE int sr_open(m)
246message *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
286PRIVATE void sr_close(m)
287message *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
302PRIVATE int sr_rwio(m)
303mq_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 break;
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 assert(sr_fd->srf_flags & first_flag);
390 sr_fd->srf_flags &= ~first_flag;
391 return OK;
392 }
393 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
394 break;
395 default:
396 ip_panic(("illegal case entry"));
397 }
398
399 assert(sr_fd->srf_flags & first_flag);
400 sr_fd->srf_flags &= ~first_flag;
401
402 assert(r == OK || r == SUSPEND ||
403 (printf("r= %d\n", r), 0));
404 if (r == SUSPEND)
405 sr_fd->srf_flags |= susp_flag;
406 else
407 mq_free(m);
408 return r;
409}
410
411PRIVATE int sr_restart_read(sr_fd)
412sr_fd_t *sr_fd;
413{
414 mq_t *mp;
415 int r;
416
417 mp= sr_fd->srf_read_q;
418 assert(mp);
419
420 if (sr_fd->srf_flags & SFF_READ_IP)
421 {
422 assert(sr_fd->srf_flags & SFF_READ_SUSP);
423 return SUSPEND;
424 }
425 sr_fd->srf_flags |= SFF_READ_IP;
426
427 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
428 mp->mq_mess.NDEV_COUNT);
429
430 assert(r == OK || r == SUSPEND ||
431 (printf("r= %d\n", r), 0));
432 if (r == SUSPEND)
433 sr_fd->srf_flags |= SFF_READ_SUSP;
434 return r;
435}
436
437PRIVATE int sr_restart_write(sr_fd)
438sr_fd_t *sr_fd;
439{
440 mq_t *mp;
441 int r;
442
443 mp= sr_fd->srf_write_q;
444 assert(mp);
445
446 if (sr_fd->srf_flags & SFF_WRITE_IP)
447 {
448 assert(sr_fd->srf_flags & SFF_WRITE_SUSP);
449 return SUSPEND;
450 }
451 sr_fd->srf_flags |= SFF_WRITE_IP;
452
453 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
454 mp->mq_mess.NDEV_COUNT);
455
456 assert(r == OK || r == SUSPEND ||
457 (printf("r= %d\n", r), 0));
458 if (r == SUSPEND)
459 sr_fd->srf_flags |= SFF_WRITE_SUSP;
460 return r;
461}
462
463PRIVATE int sr_restart_ioctl(sr_fd)
464sr_fd_t *sr_fd;
465{
466 mq_t *mp;
467 int r;
468
469 mp= sr_fd->srf_ioctl_q;
470 assert(mp);
471
472 if (sr_fd->srf_flags & SFF_IOCTL_IP)
473 {
474 assert(sr_fd->srf_flags & SFF_IOCTL_SUSP);
475 return SUSPEND;
476 }
477 sr_fd->srf_flags |= SFF_IOCTL_IP;
478
479 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd,
480 mp->mq_mess.NDEV_COUNT);
481
482 assert(r == OK || r == SUSPEND ||
483 (printf("r= %d\n", r), 0));
484 if (r == SUSPEND)
485 sr_fd->srf_flags |= SFF_IOCTL_SUSP;
486 return r;
487}
488
489PRIVATE int sr_cancel(m)
490message *m;
491{
492 sr_fd_t *sr_fd;
493 int result;
494 int proc_nr, ref, operation;
495
496 result=EINTR;
497 proc_nr= m->NDEV_PROC;
498#ifdef __minix_vmd
499 ref= m->NDEV_REF;
500 operation= m->NDEV_OPERATION;
501#else /* Minix 3 */
502 ref= 0;
503 operation= 0;
504#endif
505 sr_fd= sr_getchannel(m->NDEV_MINOR);
506 assert (sr_fd);
507
508#ifdef __minix_vmd
509 if (operation == CANCEL_ANY || operation == DEV_IOCTL3)
510#endif
511 {
512 result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q,
513 &sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL,
514 proc_nr, ref, SFF_IOCTL_FIRST);
515 if (result != EAGAIN)
516 return result;
517 }
518#ifdef __minix_vmd
519 if (operation == CANCEL_ANY || operation == DEV_READ)
520#endif
521 {
522 result= walk_queue(sr_fd, &sr_fd->srf_read_q,
523 &sr_fd->srf_read_q_tail, SR_CANCEL_READ,
524 proc_nr, ref, SFF_READ_FIRST);
525 if (result != EAGAIN)
526 return result;
527 }
528#ifdef __minix_vmd
529 if (operation == CANCEL_ANY || operation == DEV_WRITE)
530#endif
531 {
532 result= walk_queue(sr_fd, &sr_fd->srf_write_q,
533 &sr_fd->srf_write_q_tail, SR_CANCEL_WRITE,
534 proc_nr, ref, SFF_WRITE_FIRST);
535 if (result != EAGAIN)
536 return result;
537 }
538#ifdef __minix_vmd
539 ip_panic((
540"request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d OPERATION= %ld",
541 m->m_source, m->m_type, m->NDEV_MINOR,
542 m->NDEV_PROC, m->NDEV_REF, m->NDEV_OPERATION));
543#else /* Minix 3 */
544 ip_panic((
545"request not found: from %d, type %d, MINOR= %d, PROC= %d",
546 m->m_source, m->m_type, m->NDEV_MINOR,
547 m->NDEV_PROC));
548#endif
549}
550
551#ifndef __minix_vmd /* Minix 3 */
552PRIVATE int sr_select(m)
553message *m;
554{
555 sr_fd_t *sr_fd;
556 mq_t **q_head_ptr, **q_tail_ptr;
557 int ip_flag, susp_flag;
558 int r, ops;
559 unsigned m_ops, i_ops;
560 ioreq_t request;
561 size_t size;
562
563 sr_fd= sr_getchannel(m->NDEV_MINOR);
564 assert (sr_fd);
565
566 sr_fd->srf_select_proc= m->m_source;
567
568 m_ops= m->IO_ENDPT;
569 i_ops= 0;
570 if (m_ops & SEL_RD) i_ops |= SR_SELECT_READ;
571 if (m_ops & SEL_WR) i_ops |= SR_SELECT_WRITE;
572 if (m_ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION;
573 if (!(m_ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
574
575 r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
576 if (r < 0)
577 return r;
578 m_ops= 0;
579 if (r & SR_SELECT_READ) m_ops |= SEL_RD;
580 if (r & SR_SELECT_WRITE) m_ops |= SEL_WR;
581 if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
582
583 return m_ops;
584}
585
586PRIVATE void sr_status(m)
587message *m;
588{
589 int fd, result;
590 unsigned m_ops;
591 sr_fd_t *sr_fd;
592 mq_t *mq;
593
594 mq= repl_queue;
595 if (mq != NULL)
596 {
597 repl_queue= mq->mq_next;
598
599 mq->mq_mess.m_type= DEV_REVIVE;
600 result= send(mq->mq_mess.m_source, &mq->mq_mess);
601 if (result != OK)
602 ip_panic(("unable to send"));
603 mq_free(mq);
604
605 return;
606 }
607
608 for (fd=0, sr_fd= sr_fd_table; fd<FD_NR; fd++, sr_fd++)
609 {
610 if ((sr_fd->srf_flags &
611 (SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X)) == 0)
612 {
613 /* Nothing to report */
614 continue;
615 }
616 if (sr_fd->srf_select_proc != m->m_source)
617 {
618 /* Wrong process */
619 continue;
620 }
621
622 m_ops= 0;
623 if (sr_fd->srf_flags & SFF_SELECT_R) m_ops |= SEL_RD;
624 if (sr_fd->srf_flags & SFF_SELECT_W) m_ops |= SEL_WR;
625 if (sr_fd->srf_flags & SFF_SELECT_X) m_ops |= SEL_ERR;
626
627 sr_fd->srf_flags &= ~(SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X);
628
629 m->m_type= DEV_IO_READY;
630 m->DEV_MINOR= fd;
631 m->DEV_SEL_OPS= m_ops;
632
633 result= send(m->m_source, m);
634 if (result != OK)
635 ip_panic(("unable to send"));
636 return;
637 }
638
639 m->m_type= DEV_NO_STATUS;
640 result= send(m->m_source, m);
641 if (result != OK)
642 ip_panic(("unable to send"));
643}
644#endif
645
646PRIVATE int walk_queue(sr_fd, q_head_ptr, q_tail_ptr, type, proc_nr, ref,
647 first_flag)
648sr_fd_t *sr_fd;
649mq_t **q_head_ptr;
650mq_t **q_tail_ptr;
651int type;
652int proc_nr;
653int ref;
654int first_flag;
655{
656 mq_t *q_ptr_prv, *q_ptr;
657 int result;
658
659 for(q_ptr_prv= NULL, q_ptr= *q_head_ptr; q_ptr;
660 q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
661 {
662 if (q_ptr->mq_mess.NDEV_PROC != proc_nr)
663 continue;
664#ifdef __minix_vmd
665 if (q_ptr->mq_mess.NDEV_REF != ref)
666 continue;
667#endif
668 if (!q_ptr_prv)
669 {
670 assert(!(sr_fd->srf_flags & first_flag));
671 sr_fd->srf_flags |= first_flag;
672
673 result= (*sr_fd->srf_cancel)(sr_fd->srf_fd, type);
674 assert(result == OK);
675
676 *q_head_ptr= q_ptr->mq_next;
677 mq_free(q_ptr);
678
679 assert(sr_fd->srf_flags & first_flag);
680 sr_fd->srf_flags &= ~first_flag;
681
682 return OK;
683 }
684 q_ptr_prv->mq_next= q_ptr->mq_next;
685 mq_free(q_ptr);
686 if (!q_ptr_prv->mq_next)
687 *q_tail_ptr= q_ptr_prv;
688 return EINTR;
689 }
690 return EAGAIN;
691}
692
693PRIVATE sr_fd_t *sr_getchannel(minor)
694int minor;
695{
696 sr_fd_t *loc_fd;
697
698 compare(minor, >=, 0);
699 compare(minor, <, FD_NR);
700
701 loc_fd= &sr_fd_table[minor];
702
703 assert (!(loc_fd->srf_flags & SFF_MINOR) &&
704 (loc_fd->srf_flags & SFF_INUSE));
705
706 return loc_fd;
707}
708
709PRIVATE void sr_reply_(mq, status, is_revive)
710mq_t *mq;
711int status;
712int is_revive;
713{
714 int result, proc, ref,operation;
715 message reply, *mp;
716
717 proc= mq->mq_mess.NDEV_PROC;
718#ifdef __minix_vmd
719 ref= mq->mq_mess.NDEV_REF;
720#else /* Minix 3 */
721 ref= 0;
722#endif
723 operation= mq->mq_mess.m_type;
724#ifdef __minix_vmd
725 assert(operation != DEV_CANCEL);
726#endif
727
728 if (is_revive)
729 mp= &mq->mq_mess;
730 else
731 mp= &reply;
732
733 mp->m_type= DEVICE_REPLY;
734 mp->REP_ENDPT= proc;
735 mp->REP_STATUS= status;
736#ifdef __minix_vmd
737 mp->REP_REF= ref;
738 mp->REP_OPERATION= operation;
739#endif
740 if (is_revive)
741 {
742 notify(mq->mq_mess.m_source);
743 result= ELOCKED;
744 }
745 else
746 result= send(mq->mq_mess.m_source, mp);
747
748 if (result == ELOCKED && is_revive)
749 {
750 mq->mq_next= NULL;
751 if (repl_queue)
752 repl_queue_tail->mq_next= mq;
753 else
754 repl_queue= mq;
755 repl_queue_tail= mq;
756 return;
757 }
758 if (result != OK)
759 ip_panic(("unable to send"));
760 if (is_revive)
761 mq_free(mq);
762}
763
764PRIVATE acc_t *sr_get_userdata (fd, offset, count, for_ioctl)
765int fd;
766vir_bytes offset;
767vir_bytes count;
768int for_ioctl;
769{
770 sr_fd_t *loc_fd;
771 mq_t **head_ptr, *m, *mq;
772 int ip_flag, susp_flag, first_flag;
773 int result, suspended, is_revive;
774 char *src;
775 acc_t *acc;
776 event_t *evp;
777 ev_arg_t arg;
778
779 loc_fd= &sr_fd_table[fd];
780
781 if (for_ioctl)
782 {
783 head_ptr= &loc_fd->srf_ioctl_q;
784 evp= &loc_fd->srf_ioctl_ev;
785 ip_flag= SFF_IOCTL_IP;
786 susp_flag= SFF_IOCTL_SUSP;
787 first_flag= SFF_IOCTL_FIRST;
788 }
789 else
790 {
791 head_ptr= &loc_fd->srf_write_q;
792 evp= &loc_fd->srf_write_ev;
793 ip_flag= SFF_WRITE_IP;
794 susp_flag= SFF_WRITE_SUSP;
795 first_flag= SFF_WRITE_FIRST;
796 }
797
798assert (loc_fd->srf_flags & ip_flag);
799
800 if (!count)
801 {
802 m= *head_ptr;
803 mq= m->mq_next;
804 *head_ptr= mq;
805 result= (int)offset;
806 is_revive= !(loc_fd->srf_flags & first_flag);
807 sr_reply_(m, result, is_revive);
808 suspended= (loc_fd->srf_flags & susp_flag);
809 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
810 if (suspended)
811 {
812 if (mq)
813 {
814 arg.ev_ptr= loc_fd;
815 ev_enqueue(evp, sr_event, arg);
816 }
817 }
818 return NULL;
819 }
820
821 src= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
822 result= cp_u2b ((*head_ptr)->mq_mess.NDEV_PROC, src, &acc, count);
823
824 return result<0 ? NULL : acc;
825}
826
827PRIVATE int sr_put_userdata (fd, offset, data, for_ioctl)
828int fd;
829vir_bytes offset;
830acc_t *data;
831int for_ioctl;
832{
833 sr_fd_t *loc_fd;
834 mq_t **head_ptr, *m, *mq;
835 int ip_flag, susp_flag, first_flag;
836 int result, suspended, is_revive;
837 char *dst;
838 event_t *evp;
839 ev_arg_t arg;
840
841 loc_fd= &sr_fd_table[fd];
842
843 if (for_ioctl)
844 {
845 head_ptr= &loc_fd->srf_ioctl_q;
846 evp= &loc_fd->srf_ioctl_ev;
847 ip_flag= SFF_IOCTL_IP;
848 susp_flag= SFF_IOCTL_SUSP;
849 first_flag= SFF_IOCTL_FIRST;
850 }
851 else
852 {
853 head_ptr= &loc_fd->srf_read_q;
854 evp= &loc_fd->srf_read_ev;
855 ip_flag= SFF_READ_IP;
856 susp_flag= SFF_READ_SUSP;
857 first_flag= SFF_READ_FIRST;
858 }
859
860 assert (loc_fd->srf_flags & ip_flag);
861
862 if (!data)
863 {
864 m= *head_ptr;
865 mq= m->mq_next;
866 *head_ptr= mq;
867 result= (int)offset;
868 is_revive= !(loc_fd->srf_flags & first_flag);
869 sr_reply_(m, result, is_revive);
870 suspended= (loc_fd->srf_flags & susp_flag);
871 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
872 if (suspended)
873 {
874 if (mq)
875 {
876 arg.ev_ptr= loc_fd;
877 ev_enqueue(evp, sr_event, arg);
878 }
879 }
880 return OK;
881 }
882
883 dst= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
884 return cp_b2u (data, (*head_ptr)->mq_mess.NDEV_PROC, dst);
885}
886
887#ifndef __minix_vmd /* Minix 3 */
888PRIVATE void sr_select_res(fd, ops)
889int fd;
890unsigned ops;
891{
892 sr_fd_t *sr_fd;
893
894 sr_fd= &sr_fd_table[fd];
895
896 if (ops & SR_SELECT_READ) sr_fd->srf_flags |= SFF_SELECT_R;
897 if (ops & SR_SELECT_WRITE) sr_fd->srf_flags |= SFF_SELECT_W;
898 if (ops & SR_SELECT_EXCEPTION) sr_fd->srf_flags |= SFF_SELECT_X;
899
900 notify(sr_fd->srf_select_proc);
901}
902#endif
903
904PRIVATE void process_req_q(mq, tail, tail_ptr)
905mq_t *mq, *tail, **tail_ptr;
906{
907 mq_t *m;
908 int result;
909
910 for(;mq;)
911 {
912 m= mq;
913 mq= mq->mq_next;
914
915 result= sr_rwio(m);
916 if (result == SUSPEND)
917 {
918 if (mq)
919 {
920 (*tail_ptr)->mq_next= mq;
921 *tail_ptr= tail;
922 }
923 return;
924 }
925 }
926 return;
927}
928
929PRIVATE void sr_event(evp, arg)
930event_t *evp;
931ev_arg_t arg;
932{
933 sr_fd_t *sr_fd;
934 int r;
935
936 sr_fd= arg.ev_ptr;
937 if (evp == &sr_fd->srf_write_ev)
938 {
939 while(sr_fd->srf_write_q)
940 {
941 r= sr_restart_write(sr_fd);
942 if (r == SUSPEND)
943 return;
944 }
945 return;
946 }
947 if (evp == &sr_fd->srf_read_ev)
948 {
949 while(sr_fd->srf_read_q)
950 {
951 r= sr_restart_read(sr_fd);
952 if (r == SUSPEND)
953 return;
954 }
955 return;
956 }
957 if (evp == &sr_fd->srf_ioctl_ev)
958 {
959 while(sr_fd->srf_ioctl_q)
960 {
961 r= sr_restart_ioctl(sr_fd);
962 if (r == SUSPEND)
963 return;
964 }
965 return;
966 }
967 ip_panic(("sr_event: unkown event\n"));
968}
969
970PRIVATE int cp_u2b (proc, src, var_acc_ptr, size)
971int proc;
972char *src;
973acc_t **var_acc_ptr;
974int size;
975{
976 static message mess;
977 acc_t *acc;
978 int i;
979
980 acc= bf_memreq(size);
981
982 *var_acc_ptr= acc;
983 i=0;
984
985 while (acc)
986 {
987 size= (vir_bytes)acc->acc_length;
988
989#ifdef __minix_vmd
990 cpvec[i].cpv_src= (vir_bytes)src;
991 cpvec[i].cpv_dst= (vir_bytes)ptr2acc_data(acc);
992 cpvec[i].cpv_size= size;
993#else /* Minix 3 */
994 vir_cp_req[i].count= size;
995 vir_cp_req[i].src.proc_nr_e = proc;
996 vir_cp_req[i].src.segment = D;
997 vir_cp_req[i].src.offset = (vir_bytes) src;
998 vir_cp_req[i].dst.proc_nr_e = this_proc;
999 vir_cp_req[i].dst.segment = D;
1000 vir_cp_req[i].dst.offset = (vir_bytes) ptr2acc_data(acc);
1001#endif
1002
1003 src += size;
1004 acc= acc->acc_next;
1005 i++;
1006
1007 if (i == CPVEC_NR || acc == NULL)
1008 {
1009#ifdef __minix_vmd
1010 mess.m_type= SYS_VCOPY;
1011 mess.m1_i1= proc;
1012 mess.m1_i2= this_proc;
1013 mess.m1_i3= i;
1014 mess.m1_p1= (char *)cpvec;
1015#else /* Minix 3 */
1016 mess.m_type= SYS_VIRVCOPY;
1017 mess.VCP_VEC_SIZE= i;
1018 mess.VCP_VEC_ADDR= (char *)vir_cp_req;
1019#endif
1020 if (sendrec(SYSTASK, &mess) <0)
1021 ip_panic(("unable to sendrec"));
1022 if (mess.m_type <0)
1023 {
1024 bf_afree(*var_acc_ptr);
1025 *var_acc_ptr= 0;
1026 return mess.m_type;
1027 }
1028 i= 0;
1029 }
1030 }
1031 return OK;
1032}
1033
1034PRIVATE int cp_b2u (acc_ptr, proc, dest)
1035acc_t *acc_ptr;
1036int proc;
1037char *dest;
1038{
1039 static message mess;
1040 acc_t *acc;
1041 int i, size;
1042
1043 acc= acc_ptr;
1044 i=0;
1045
1046 while (acc)
1047 {
1048 size= (vir_bytes)acc->acc_length;
1049
1050 if (size)
1051 {
1052#ifdef __minix_vmd
1053 cpvec[i].cpv_src= (vir_bytes)ptr2acc_data(acc);
1054 cpvec[i].cpv_dst= (vir_bytes)dest;
1055 cpvec[i].cpv_size= size;
1056#else /* Minix 3 */
1057 vir_cp_req[i].src.proc_nr_e = this_proc;
1058 vir_cp_req[i].src.segment = D;
1059 vir_cp_req[i].src.offset= (vir_bytes)ptr2acc_data(acc);
1060 vir_cp_req[i].dst.proc_nr_e = proc;
1061 vir_cp_req[i].dst.segment = D;
1062 vir_cp_req[i].dst.offset= (vir_bytes)dest;
1063 vir_cp_req[i].count= size;
1064#endif
1065 i++;
1066 }
1067
1068 dest += size;
1069 acc= acc->acc_next;
1070
1071 if (i == CPVEC_NR || acc == NULL)
1072 {
1073#ifdef __minix_vmd
1074 mess.m_type= SYS_VCOPY;
1075 mess.m1_i1= this_proc;
1076 mess.m1_i2= proc;
1077 mess.m1_i3= i;
1078 mess.m1_p1= (char *)cpvec;
1079#else /* Minix 3 */
1080 mess.m_type= SYS_VIRVCOPY;
1081 mess.VCP_VEC_SIZE= i;
1082 mess.VCP_VEC_ADDR= (char *) vir_cp_req;
1083#endif
1084 if (sendrec(SYSTASK, &mess) <0)
1085 ip_panic(("unable to sendrec"));
1086 if (mess.m_type <0)
1087 {
1088 bf_afree(acc_ptr);
1089 return mess.m_type;
1090 }
1091 i= 0;
1092 }
1093 }
1094 bf_afree(acc_ptr);
1095 return OK;
1096}
1097
1098PRIVATE int sr_repl_queue(proc, ref, operation)
1099int proc;
1100int ref;
1101int operation;
1102{
1103 mq_t *m, *m_cancel, *m_tmp;
1104 int result;
1105
1106 m_cancel= NULL;
1107
1108 for (m= repl_queue; m;)
1109 {
1110#ifdef __minix_vmd
1111 if (m->mq_mess.REP_ENDPT == proc &&
1112 m->mq_mess.REP_REF ==ref &&
1113 (m->mq_mess.REP_OPERATION == operation ||
1114 operation == CANCEL_ANY))
1115#else /* Minix 3 */
1116 if (m->mq_mess.REP_ENDPT == proc)
1117#endif
1118 {
1119assert(!m_cancel);
1120 m_cancel= m;
1121 m= m->mq_next;
1122 continue;
1123 }
1124 result= send(m->mq_mess.m_source, &m->mq_mess);
1125 if (result != OK)
1126 ip_panic(("unable to send: %d", result));
1127 m_tmp= m;
1128 m= m->mq_next;
1129 mq_free(m_tmp);
1130 }
1131 repl_queue= NULL;
1132 if (m_cancel)
1133 {
1134 result= send(m_cancel->mq_mess.m_source, &m_cancel->mq_mess);
1135 if (result != OK)
1136 ip_panic(("unable to send: %d", result));
1137 mq_free(m_cancel);
1138 return 1;
1139 }
1140 return 0;
1141}
1142
1143/*
1144 * $PchId: sr.c,v 1.17 2005/06/28 14:26:16 philip Exp $
1145 */
Note: See TracBrowser for help on using the repository browser.