📄 sr.c
字号:
/* this file contains the interface of the network software with the file
system.
The valid messages and their parameters are:
__________________________________________________________________
| | | | | | |
| m_type | DEVICE | PROC_NR | COUNT | REQUEST | ADDRESS |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_OPEN | minor dev | proc nr | mode | | |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_CLOSE | minor dev | proc nr | | | |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_IOCTL | minor dev | proc nr | | NWIO.. | address |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_READ | minor dev | proc nr | count | | address |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_WRITE | minor dev | proc nr | count | | address |
|_______________|___________|_________|_______|__________|_________|
| | | | | | |
| NW_CANCEL | minor dev | proc nr | | | |
|_______________|___________|_________|_______|__________|_________|
*/
#include "inet.h"
#include <minix/callnr.h>
#include "mq.h"
#include "proto.h"
#include "generic/assert.h"
#include "generic/buf.h"
#include "generic/sr.h"
#include "generic/type.h"
INIT_PANIC();
#define FD_NR 32
typedef struct sr_fd
{
int srf_flags;
int srf_fd;
int srf_port;
sr_open_t srf_open;
sr_close_t srf_close;
sr_write_t srf_write;
sr_read_t srf_read;
sr_ioctl_t srf_ioctl;
sr_cancel_t srf_cancel;
mq_t *srf_ioctl_q, *srf_ioctl_q_tail;
mq_t *srf_read_q, *srf_read_q_tail;
mq_t *srf_write_q, *srf_write_q_tail;
} sr_fd_t;
#define SFF_FLAGS 0x0F
# define SFF_FREE 0x00
# define SFF_MINOR 0x01
# define SFF_INUSE 0x02
# define SFF_BUSY 0x3C
# define SFF_IOCTL_IP 0x04
# define SFF_READ_IP 0x08
# define SFF_WRITE_IP 0x10
# define SFF_PENDING_REQ 0x30
# define SFF_SUSPENDED 0x1C0
# define SFF_IOCTL_SUSP 0x40
# define SFF_READ_SUSP 0x80
# define SFF_WRITE_SUSP 0x100
FORWARD _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_cancel, (message *m) );
FORWARD _PROTOTYPE ( void sr_reply, (message *mes_ptr, int reply) );
FORWARD _PROTOTYPE ( void sr_revive, (mq_t *mes_ptr, int reply) );
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) );
FORWARD _PROTOTYPE ( int sr_repl_queue, (int proc) );
FORWARD _PROTOTYPE ( int walk_queue, (sr_fd_t *sr_fd, mq_t *q_head,
mq_t **q_tail_ptr, int type, int proc_n) );
FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail,
mq_t **tail_ptr) );
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) );
PRIVATE sr_fd_t sr_fd_table[FD_NR];
PRIVATE mq_t *repl_queue, *repl_queue_tail;
PRIVATE cpvec_t cpvec[CPVEC_NR];
PUBLIC void sr_init()
{
int i;
for (i=0; i<FD_NR; i++)
sr_fd_table[i].srf_flags= SFF_FREE;
repl_queue= NULL;
}
PUBLIC void sr_rec(m)
mq_t *m;
{
message mess, *mp;
int result;
int send_reply, free_mess;
if (repl_queue)
{
if (m->mq_mess.m_type == NW_CANCEL)
{
result= sr_repl_queue(m->mq_mess.PROC_NR);
if (result)
return; /* canceled request in queue */
}
else
sr_repl_queue(ANY);
}
#if DEBUG & 256
{ where(); printf("sr_rec: message from %d for %d type %d, minor %d\n",
m->mq_mess.m_source, m->mq_mess.PROC_NR, m->mq_mess.m_type,
m->mq_mess.DEVICE); }
#endif
switch (m->mq_mess.m_type)
{
case NW_OPEN:
result= sr_open(&m->mq_mess);
send_reply= 1;
free_mess= 1;
break;
case NW_CLOSE:
sr_close(&m->mq_mess);
result= OK;
send_reply= 1;
free_mess= 1;
break;
case NW_READ:
case NW_WRITE:
case NW_IOCTL:
#if DEBUG & 256
{ where(); printf("calling rwio\n"); }
#endif
result= sr_rwio(m);
#if DEBUG & 256
{ where(); printf("rwio()= %d\n", result); }
#endif
assert(result == OK || result == SUSPEND);
send_reply= (result == SUSPEND);
free_mess= 0;
break;
case NW_CANCEL:
result= sr_cancel(&m->mq_mess);
assert(result == OK || result == EINTR);
send_reply= (result == EINTR);
free_mess= 1;
break;
default:
ip_panic(("unknown message, type= %d", m->mq_mess.m_type));
}
if (send_reply)
{
if (free_mess)
mp= &m->mq_mess;
else
{
mess= m->mq_mess;
mp= &mess;
}
sr_reply(mp, result);
}
if (free_mess)
mq_free(m);
}
PUBLIC int sr_add_minor(minor, port, openf, closef, readf, writef,
ioctlf, cancelf)
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_fd_t *sr_fd;
assert (minor>=0 && minor<FD_NR);
sr_fd= &sr_fd_table[minor];
if (sr_fd->srf_flags & SFF_INUSE)
return EGENERIC;
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;
return OK;
}
PRIVATE int sr_open(m)
message *m;
{
sr_fd_t *sr_fd;
int minor= m->DEVICE;
int i, fd;
if (minor<0 || minor>FD_NR)
{
#if DEBUG
{ where(); printf("replying EINVAL\n"); }
#endif
return EINVAL;
}
if (!(sr_fd_table[minor].srf_flags & SFF_MINOR))
{
#if DEBUG
{ where(); printf("replying ENXIO\n"); }
#endif
return ENXIO;
}
for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++);
if (i>=FD_NR)
{
#if DEBUG
{ where(); printf("replying ENFILE\n"); }
#endif
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);
#if DEBUG & 256
{ where(); printf("srf_open: 0x%x(%d, %d, .., ..)= %d\n", sr_fd->srf_open,
sr_fd->srf_port, i, fd); }
#endif
if (fd<0)
{
sr_fd->srf_flags= SFF_FREE;
#if DEBUG
{ where(); printf("replying %d\n", fd); }
#endif
return fd;
}
sr_fd->srf_fd= fd;
#if DEBUG & 256
{ where(); printf("replying %d\n", i); }
#endif
return i;
}
PRIVATE void sr_close(m)
message *m;
{
sr_fd_t *sr_fd;
sr_fd= sr_getchannel(m->DEVICE);
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);
#if DEBUG & 256
{ where(); printf("srf_close: 0x%x(%d)\n", sr_fd->srf_close, sr_fd->srf_fd); }
#endif
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;
int result;
unsigned long request;
size_t size;
sr_fd= sr_getchannel(m->mq_mess.DEVICE);
assert (sr_fd);
switch(m->mq_mess.m_type)
{
case NW_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;
break;
case NW_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;
break;
case NW_IOCTL:
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;
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;
switch(m->mq_mess.m_type)
{
case NW_READ:
#if DEBUG&256
{ where(); printf("calling 0x%x(%d, %d)\n", sr_fd->srf_read, sr_fd->srf_fd,
m->mq_mess.COUNT); }
#endif
result= (*sr_fd->srf_read)(sr_fd->srf_fd, m->mq_mess.COUNT);
break;
case NW_WRITE:
#if DEBUG&256
{ where(); printf("calling 0x%x(%d, %d)\n", sr_fd->srf_write, sr_fd->srf_fd,
m->mq_mess.COUNT); }
#endif
result= (*sr_fd->srf_write)(sr_fd->srf_fd, m->mq_mess.COUNT);
break;
case NW_IOCTL:
request= m->mq_mess.REQUEST;
#ifdef IOCPARM_MASK
size= (request >> 16) & IOCPARM_MASK;
if (size>MAX_IOCTL_S)
{
#if DEBUG
{ where(); printf("replying EINVAL\n"); }
#endif
result= sr_put_userdata(sr_fd-sr_fd_table, EINVAL,
NULL, 1);
assert(result == OK);
return OK;
}
#endif /* IOCPARM_MASK */
#if DEBUG
{ where(); printf("calling 0x%x(%d, 0x%lx)\n", sr_fd->srf_ioctl, sr_fd->srf_fd,
request); }
#endif
result=(*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
break;
default:
ip_panic(("illegal case entry"));
}
#if DEBUG
if (result != OK && result != SUSPEND)
{ where(); printf("result= %d\n", result); }
#endif
assert(result == OK || result == SUSPEND);
if (result == SUSPEND)
sr_fd->srf_flags |= susp_flag;
return result;
}
PRIVATE int sr_cancel(m)
message *m;
{
sr_fd_t *sr_fd;
int i, result;
mq_t *q_ptr, *q_ptr_prv;
int proc_nr;
result=EINTR;
proc_nr= m->PROC_NR;
sr_fd= sr_getchannel(m->DEVICE);
assert (sr_fd);
result= walk_queue(sr_fd, sr_fd->srf_ioctl_q, &sr_fd->srf_ioctl_q_tail,
SR_CANCEL_IOCTL, proc_nr);
if (result != EAGAIN)
return result;
result= walk_queue(sr_fd, sr_fd->srf_read_q, &sr_fd->srf_read_q_tail,
SR_CANCEL_READ, proc_nr);
if (result != EAGAIN)
return result;
result= walk_queue(sr_fd, sr_fd->srf_write_q, &sr_fd->srf_write_q_tail,
SR_CANCEL_WRITE, proc_nr);
if (result != EAGAIN)
return result;
ip_panic(("request not found"));
}
PRIVATE int walk_queue(sr_fd, q_head, q_tail_ptr, type, proc_nr)
sr_fd_t *sr_fd;
mq_t *q_head, **q_tail_ptr;
int type;
int proc_nr;
{
mq_t *q_ptr_prv, *q_ptr;
int result;
for(q_ptr_prv= NULL, q_ptr= q_head; q_ptr;
q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -