📄 sr.c
字号:
/* this file contains the interface of the network software with the file * system. * * Copyright 1995 Philip Homburg * * The valid messages and their parameters are: * * Requests: * * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_MODE * ------------------------------------------------------------- * | DEV_OPEN |minor dev | proc nr | fd | mode | * |-------------+-----------+-----------+-----------+----------+ * | DEV_CLOSE |minor dev | proc nr | fd | | * |-------------+-----------+-----------+-----------+----------+ * * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_COUNT NDEV_BUFFER * --------------------------------------------------------------------------- * | DEV_READ |minor dev | proc nr | fd | count | buf ptr | * |-------------+-----------+-----------+-----------+-----------+-----------| * | DEV_WRITE |minor dev | proc nr | fd | count | buf ptr | * |-------------+-----------+-----------+-----------+-----------+-----------| * * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_IOCTL NDEV_BUFFER * --------------------------------------------------------------------------- * | DEV_IOCTL3 |minor dev | proc nr | fd | command | buf ptr | * |-------------+-----------+-----------+-----------+-----------+-----------| * * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_OPERATION * -------------------------------------------------------------------| * | DEV_CANCEL |minor dev | proc nr | fd | which operation| * |-------------+-----------+-----------+-----------+----------------| * * Replies: * * m_type REP_PROC_NR REP_STATUS REP_REF REP_OPERATION * ----------------------------------------------------------------------| * | DEVICE_REPLY | proc nr | status | fd | which operation | * |--------------+-------------+------------+---------+-----------------| */#include "inet.h"#ifndef __minix_vmd /* Minix 3 */#include <sys/select.h>#endif#include <sys/svrctl.h>#include <minix/callnr.h>#include "mq.h"#include "qp.h"#include "proto.h"#include "generic/type.h"#include "generic/assert.h"#include "generic/buf.h"#include "generic/event.h"#include "generic/sr.h"#include "sr_int.h"#ifndef __minix_vmd /* Minix 3 */#define DEV_CANCEL NW_CANCEL#define DEVICE_REPLY REVIVE#define DEV_IOCTL3 DEV_IOCTL#define NDEV_BUFFER ADDRESS#define NDEV_COUNT COUNT#define NDEV_IOCTL REQUEST#define NDEV_MINOR DEVICE#define NDEV_PROC PROC_NR#endifTHIS_FILEPUBLIC sr_fd_t sr_fd_table[FD_NR];PRIVATE mq_t *repl_queue, *repl_queue_tail;#ifdef __minix_vmdPRIVATE cpvec_t cpvec[CPVEC_NR];#else /* Minix 3 */PRIVATE struct vir_cp_req vir_cp_req[CPVEC_NR];#endifFORWARD _PROTOTYPE ( int sr_open, (message *m) );FORWARD _PROTOTYPE ( void sr_close, (message *m) );FORWARD _PROTOTYPE ( int sr_rwio, (mq_t *m) );FORWARD _PROTOTYPE ( int sr_restart_read, (sr_fd_t *fdp) );FORWARD _PROTOTYPE ( int sr_restart_write, (sr_fd_t *fdp) );FORWARD _PROTOTYPE ( int sr_restart_ioctl, (sr_fd_t *fdp) );FORWARD _PROTOTYPE ( int sr_cancel, (message *m) );#ifndef __minix_vmd /* Minix 3 */FORWARD _PROTOTYPE ( int sr_select, (message *m) );FORWARD _PROTOTYPE ( void sr_status, (message *m) );#endifFORWARD _PROTOTYPE ( void sr_reply_, (mq_t *m, int reply, int is_revive) );FORWARD _PROTOTYPE ( sr_fd_t *sr_getchannel, (int minor));FORWARD _PROTOTYPE ( acc_t *sr_get_userdata, (int fd, vir_bytes offset, vir_bytes count, int for_ioctl) );FORWARD _PROTOTYPE ( int sr_put_userdata, (int fd, vir_bytes offset, acc_t *data, int for_ioctl) );#ifdef __minix_vmd #define sr_select_res 0#else /* Minix 3 */FORWARD _PROTOTYPE (void sr_select_res, (int fd, unsigned ops) );#endifFORWARD _PROTOTYPE ( int sr_repl_queue, (int proc, int ref, int operation) );FORWARD _PROTOTYPE ( int walk_queue, (sr_fd_t *sr_fd, mq_t **q_head_ptr, mq_t **q_tail_ptr, int type, int proc_nr, int ref, int first_flag) );FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail, mq_t **tail_ptr) );FORWARD _PROTOTYPE ( void sr_event, (event_t *evp, ev_arg_t arg) );FORWARD _PROTOTYPE ( int cp_u2b, (int proc, char *src, acc_t **var_acc_ptr, int size) );FORWARD _PROTOTYPE ( int cp_b2u, (acc_t *acc_ptr, int proc, char *dest) );PUBLIC void sr_init(){ int i; for (i=0; i<FD_NR; i++) { sr_fd_table[i].srf_flags= SFF_FREE; ev_init(&sr_fd_table[i].srf_ioctl_ev); ev_init(&sr_fd_table[i].srf_read_ev); ev_init(&sr_fd_table[i].srf_write_ev); } repl_queue= NULL;}PUBLIC void sr_rec(m)mq_t *m;{ int result; int send_reply, free_mess; if (repl_queue) { if (m->mq_mess.m_type == DEV_CANCEL) {#ifdef __minix_vmd result= sr_repl_queue(m->mq_mess.NDEV_PROC, m->mq_mess.NDEV_REF, m->mq_mess.NDEV_OPERATION);#else /* Minix 3 */ result= sr_repl_queue(m->mq_mess.PROC_NR, 0, 0);#endif if (result) { mq_free(m); return; /* canceled request in queue */ } }#if 0 else sr_repl_queue(ANY, 0, 0);#endif } switch (m->mq_mess.m_type) { case DEV_OPEN: result= sr_open(&m->mq_mess); send_reply= 1; free_mess= 1; break; case DEV_CLOSE: sr_close(&m->mq_mess); result= OK; send_reply= 1; free_mess= 1; break; case DEV_READ: case DEV_WRITE: case DEV_IOCTL3: result= sr_rwio(m); assert(result == OK || result == SUSPEND); send_reply= (result == SUSPEND); free_mess= 0; break; case DEV_CANCEL: result= sr_cancel(&m->mq_mess); assert(result == OK || result == EINTR); send_reply= (result == EINTR); free_mess= 1;#ifdef __minix_vmd m->mq_mess.m_type= m->mq_mess.NDEV_OPERATION;#else /* Minix 3 */ m->mq_mess.m_type= 0;#endif break;#ifndef __minix_vmd /* Minix 3 */ case DEV_SELECT: result= sr_select(&m->mq_mess); send_reply= 1; free_mess= 1; break; case DEV_STATUS: sr_status(&m->mq_mess); send_reply= 0; free_mess= 1; break;#endif default: ip_panic(("unknown message, from %d, type %d", m->mq_mess.m_source, m->mq_mess.m_type)); } if (send_reply) { sr_reply_(m, result, FALSE /* !is_revive */); } if (free_mess) mq_free(m);}PUBLIC void sr_add_minor(minor, port, openf, closef, readf, writef, ioctlf, cancelf, selectf)int minor;int port;sr_open_t openf;sr_close_t closef;sr_read_t readf;sr_write_t writef;sr_ioctl_t ioctlf;sr_cancel_t cancelf;sr_select_t selectf;{ sr_fd_t *sr_fd; assert (minor>=0 && minor<FD_NR); sr_fd= &sr_fd_table[minor]; assert(!(sr_fd->srf_flags & SFF_INUSE)); sr_fd->srf_flags= SFF_INUSE | SFF_MINOR; sr_fd->srf_port= port; sr_fd->srf_open= openf; sr_fd->srf_close= closef; sr_fd->srf_write= writef; sr_fd->srf_read= readf; sr_fd->srf_ioctl= ioctlf; sr_fd->srf_cancel= cancelf; sr_fd->srf_select= selectf;}PRIVATE int sr_open(m)message *m;{ sr_fd_t *sr_fd; int minor= m->NDEV_MINOR; int i, fd; if (minor<0 || minor>FD_NR) { DBLOCK(1, printf("replying EINVAL\n")); return EINVAL; } if (!(sr_fd_table[minor].srf_flags & SFF_MINOR)) { DBLOCK(1, printf("replying ENXIO\n")); return ENXIO; } for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++); if (i>=FD_NR) { DBLOCK(1, printf("replying ENFILE\n")); return ENFILE; } sr_fd= &sr_fd_table[i]; *sr_fd= sr_fd_table[minor]; sr_fd->srf_flags= SFF_INUSE; fd= (*sr_fd->srf_open)(sr_fd->srf_port, i, sr_get_userdata, sr_put_userdata, 0 /* no put_pkt */, sr_select_res); if (fd<0) { sr_fd->srf_flags= SFF_FREE; DBLOCK(1, printf("replying %d\n", fd)); return fd; } sr_fd->srf_fd= fd; return i;}PRIVATE void sr_close(m)message *m;{ sr_fd_t *sr_fd; sr_fd= sr_getchannel(m->NDEV_MINOR); assert (sr_fd); if (sr_fd->srf_flags & SFF_BUSY) ip_panic(("close on busy channel")); assert (!(sr_fd->srf_flags & SFF_MINOR)); (*sr_fd->srf_close)(sr_fd->srf_fd); sr_fd->srf_flags= SFF_FREE;}PRIVATE int sr_rwio(m)mq_t *m;{ sr_fd_t *sr_fd; mq_t **q_head_ptr, **q_tail_ptr; int ip_flag, susp_flag, first_flag; int r; ioreq_t request; size_t size; sr_fd= sr_getchannel(m->mq_mess.NDEV_MINOR); assert (sr_fd); switch(m->mq_mess.m_type) { case DEV_READ: q_head_ptr= &sr_fd->srf_read_q; q_tail_ptr= &sr_fd->srf_read_q_tail; ip_flag= SFF_READ_IP; susp_flag= SFF_READ_SUSP; first_flag= SFF_READ_FIRST; break; case DEV_WRITE: q_head_ptr= &sr_fd->srf_write_q; q_tail_ptr= &sr_fd->srf_write_q_tail; ip_flag= SFF_WRITE_IP; susp_flag= SFF_WRITE_SUSP; first_flag= SFF_WRITE_FIRST; break; case DEV_IOCTL3: q_head_ptr= &sr_fd->srf_ioctl_q; q_tail_ptr= &sr_fd->srf_ioctl_q_tail; ip_flag= SFF_IOCTL_IP; susp_flag= SFF_IOCTL_SUSP; first_flag= SFF_IOCTL_FIRST; break; default: ip_panic(("illegal case entry")); } if (sr_fd->srf_flags & ip_flag) { assert(sr_fd->srf_flags & susp_flag); assert(*q_head_ptr); (*q_tail_ptr)->mq_next= m; *q_tail_ptr= m; return SUSPEND; } assert(!*q_head_ptr); *q_tail_ptr= *q_head_ptr= m; sr_fd->srf_flags |= ip_flag; assert(!(sr_fd->srf_flags & first_flag)); sr_fd->srf_flags |= first_flag; switch(m->mq_mess.m_type) { case DEV_READ: r= (*sr_fd->srf_read)(sr_fd->srf_fd, m->mq_mess.NDEV_COUNT); break; case DEV_WRITE: r= (*sr_fd->srf_write)(sr_fd->srf_fd, m->mq_mess.NDEV_COUNT); break; case DEV_IOCTL3: request= m->mq_mess.NDEV_IOCTL; /* There should be a better way to do this... */ if (request == NWIOQUERYPARAM) { r= qp_query(m->mq_mess.NDEV_PROC, (vir_bytes)m->mq_mess.NDEV_BUFFER); r= sr_put_userdata(sr_fd-sr_fd_table, r, NULL, 1); assert(r == OK); return OK; } /* And now, we continue with our regular program. */ size= (request >> 16) & _IOCPARM_MASK; if (size>MAX_IOCTL_S) { DBLOCK(1, printf("replying EINVAL\n")); r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL, NULL, 1); assert(r == OK); return OK; } r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request); break; default: ip_panic(("illegal case entry")); } assert(sr_fd->srf_flags & first_flag); sr_fd->srf_flags &= ~first_flag; assert(r == OK || r == SUSPEND || (printf("r= %d\n", r), 0)); if (r == SUSPEND) sr_fd->srf_flags |= susp_flag; else mq_free(m); return r;}PRIVATE int sr_restart_read(sr_fd)sr_fd_t *sr_fd;{ mq_t *mp; int r; mp= sr_fd->srf_read_q; assert(mp); if (sr_fd->srf_flags & SFF_READ_IP) { assert(sr_fd->srf_flags & SFF_READ_SUSP); return SUSPEND; } sr_fd->srf_flags |= SFF_READ_IP; r= (*sr_fd->srf_read)(sr_fd->srf_fd, mp->mq_mess.NDEV_COUNT); assert(r == OK || r == SUSPEND || (printf("r= %d\n", r), 0)); if (r == SUSPEND) sr_fd->srf_flags |= SFF_READ_SUSP; return r;}PRIVATE int sr_restart_write(sr_fd)sr_fd_t *sr_fd;{ mq_t *mp; int r; mp= sr_fd->srf_write_q; assert(mp); if (sr_fd->srf_flags & SFF_WRITE_IP) { assert(sr_fd->srf_flags & SFF_WRITE_SUSP); return SUSPEND; } sr_fd->srf_flags |= SFF_WRITE_IP; r= (*sr_fd->srf_write)(sr_fd->srf_fd, mp->mq_mess.NDEV_COUNT); assert(r == OK || r == SUSPEND || (printf("r= %d\n", r), 0)); if (r == SUSPEND) sr_fd->srf_flags |= SFF_WRITE_SUSP; return r;}PRIVATE int sr_restart_ioctl(sr_fd)sr_fd_t *sr_fd;{ mq_t *mp; int r; mp= sr_fd->srf_ioctl_q; assert(mp); if (sr_fd->srf_flags & SFF_IOCTL_IP) { assert(sr_fd->srf_flags & SFF_IOCTL_SUSP); return SUSPEND; } sr_fd->srf_flags |= SFF_IOCTL_IP; r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, mp->mq_mess.NDEV_COUNT); assert(r == OK || r == SUSPEND || (printf("r= %d\n", r), 0)); if (r == SUSPEND) sr_fd->srf_flags |= SFF_IOCTL_SUSP; return r;}PRIVATE int sr_cancel(m)message *m;{ sr_fd_t *sr_fd; int result; int proc_nr, ref, operation; result=EINTR; proc_nr= m->NDEV_PROC;#ifdef __minix_vmd ref= m->NDEV_REF; operation= m->NDEV_OPERATION;#else /* Minix 3 */ ref= 0; operation= 0;#endif sr_fd= sr_getchannel(m->NDEV_MINOR); assert (sr_fd);#ifdef __minix_vmd if (operation == CANCEL_ANY || operation == DEV_IOCTL3)#endif { result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q, &sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL, proc_nr, ref, SFF_IOCTL_FIRST); if (result != EAGAIN) return result; }#ifdef __minix_vmd if (operation == CANCEL_ANY || operation == DEV_READ)#endif { result= walk_queue(sr_fd, &sr_fd->srf_read_q, &sr_fd->srf_read_q_tail, SR_CANCEL_READ, proc_nr, ref, SFF_READ_FIRST); if (result != EAGAIN) return result; }#ifdef __minix_vmd if (operation == CANCEL_ANY || operation == DEV_WRITE)#endif { result= walk_queue(sr_fd, &sr_fd->srf_write_q, &sr_fd->srf_write_q_tail, SR_CANCEL_WRITE, proc_nr, ref, SFF_WRITE_FIRST); if (result != EAGAIN) return result; }#ifdef __minix_vmd ip_panic(("request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d OPERATION= %ld", m->m_source, m->m_type, m->NDEV_MINOR, m->NDEV_PROC, m->NDEV_REF, m->NDEV_OPERATION));#else /* Minix 3 */ ip_panic(("request not found: from %d, type %d, MINOR= %d, PROC= %d", m->m_source, m->m_type, m->NDEV_MINOR, m->NDEV_PROC));#endif}#ifndef __minix_vmd /* Minix 3 */PRIVATE int sr_select(m)message *m;{ sr_fd_t *sr_fd; mq_t **q_head_ptr, **q_tail_ptr; int ip_flag, susp_flag; int r, ops; unsigned m_ops, i_ops; ioreq_t request; size_t size; sr_fd= sr_getchannel(m->NDEV_MINOR); assert (sr_fd); sr_fd->srf_select_proc= m->m_source; m_ops= m->PROC_NR; i_ops= 0; if (m_ops & SEL_RD) i_ops |= SR_SELECT_READ; if (m_ops & SEL_WR) i_ops |= SR_SELECT_WRITE; if (m_ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION; if (!(m_ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -