The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/servers/inet/sr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.