Rewrite character driver protocol
As a side effect, remove the clone style, as the normal device style supports device cloning now. Change-Id: Ie82d1ef0385514a04a8faa139129a617895780b5
This commit is contained in:
parent
87337273e4
commit
665198b4c2
38 changed files with 515 additions and 661 deletions
|
@ -335,9 +335,9 @@ static int parse_arguments(int argc, char **argv, u32_t *rss_flags)
|
|||
}
|
||||
else if (strcmp(argv[i], ARG_DEVSTYLE)==0) {
|
||||
char* dev_style_keys[] = { "STYLE_DEV", "STYLE_TTY",
|
||||
"STYLE_CTTY", "STYLE_CLONE", NULL };
|
||||
"STYLE_CTTY", NULL };
|
||||
int dev_style_values[] = { STYLE_DEV, STYLE_TTY,
|
||||
STYLE_CTTY, STYLE_CLONE };
|
||||
STYLE_CTTY };
|
||||
for(j=0;dev_style_keys[j]!=NULL;j++) {
|
||||
if(!strcmp(dev_style_keys[j], argv[i+1])) {
|
||||
break;
|
||||
|
|
|
@ -167,17 +167,17 @@ subwrite(struct logdevice *log, size_t size, endpoint_t endpt,
|
|||
log->log_source = NONE;
|
||||
}
|
||||
|
||||
if (log->log_size > 0 && (log->log_selected & SEL_RD)) {
|
||||
if (log->log_size > 0 && (log->log_selected & CDEV_OP_RD)) {
|
||||
/* Someone(s) who was/were select()ing can now be awoken. If there was
|
||||
* a blocking read (above), this can only happen if the blocking read
|
||||
* didn't swallow all the data (log_size > 0).
|
||||
*/
|
||||
minor = log-logdevices;
|
||||
#if LOG_DEBUG
|
||||
printf("select sending DEV_SEL_REPL2\n");
|
||||
printf("select sending CDEV_SEL2_REPLY\n");
|
||||
#endif
|
||||
chardriver_reply_select(log->log_select_proc, minor, SEL_RD);
|
||||
log->log_selected &= ~SEL_RD;
|
||||
chardriver_reply_select(log->log_select_proc, minor, CDEV_OP_RD);
|
||||
log->log_selected &= ~CDEV_OP_RD;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -248,7 +248,7 @@ static ssize_t log_read(devminor_t minor, u64_t UNUSED(position),
|
|||
if (log->log_source != NONE) return OK;
|
||||
|
||||
if (!log->log_size && size > 0) {
|
||||
if (flags & FLG_OP_NONBLOCK) return EAGAIN;
|
||||
if (flags & CDEV_NONBLOCK) return EAGAIN;
|
||||
|
||||
/* No data available; let caller block. */
|
||||
log->log_source = endpt;
|
||||
|
@ -319,24 +319,24 @@ static int log_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
|||
if (minor < 0 || minor >= NR_DEVS)
|
||||
return ENXIO;
|
||||
|
||||
want_ops = ops & (SEL_RD|SEL_WR|SEL_ERR);
|
||||
want_ops = ops & (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
/* Read blocks when there is no log. */
|
||||
if ((want_ops & SEL_RD) && logdevices[minor].log_size > 0) {
|
||||
if ((want_ops & CDEV_OP_RD) && logdevices[minor].log_size > 0) {
|
||||
#if LOG_DEBUG
|
||||
printf("log can read; size %d\n", logdevices[minor].log_size);
|
||||
#endif
|
||||
ready_ops |= SEL_RD;
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
}
|
||||
|
||||
/* Write never blocks. */
|
||||
if (want_ops & SEL_WR) ready_ops |= SEL_WR;
|
||||
if (want_ops & CDEV_OP_WR) ready_ops |= CDEV_OP_WR;
|
||||
|
||||
/* Enable select calback if not all requested operations were ready to go,
|
||||
* and notify was enabled.
|
||||
*/
|
||||
want_ops &= ~ready_ops;
|
||||
if ((ops & SEL_NOTIFY) && want_ops) {
|
||||
if ((ops & CDEV_NOTIFY) && want_ops) {
|
||||
logdevices[minor].log_selected |= want_ops;
|
||||
logdevices[minor].log_select_proc = endpt;
|
||||
#if LOG_DEBUG
|
||||
|
|
|
@ -6,27 +6,6 @@
|
|||
* May 07, 2004 fix: wait until printer is ready (Jorrit N. Herder)
|
||||
* May 06, 2004 printer driver moved to user-space (Jorrit N. Herder)
|
||||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* DEV_OPEN: initializes the printer
|
||||
* DEV_CLOSE: does nothing
|
||||
* HARD_INT: interrupt handler has finished current chunk of output
|
||||
* DEV_WRITE: a process wants to write on a terminal
|
||||
* CANCEL: terminate a previous incomplete system call immediately
|
||||
*
|
||||
* m_type DEVICE USER_ENDPT COUNT ADDRESS
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_OPEN | | | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE | | proc nr | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | HARD_INT | | | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE |minor dev| proc nr | count | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | CANCEL |minor dev| proc nr | | |
|
||||
* -------------------------------------------------------
|
||||
*
|
||||
* Note: since only 1 printer is supported, minor dev is not used at present.
|
||||
*/
|
||||
|
||||
|
@ -192,7 +171,7 @@ static ssize_t printer_write(devminor_t UNUSED(minor), u64_t UNUSED(position),
|
|||
*/
|
||||
if (writing) return EIO;
|
||||
if (size <= 0) return EINVAL;
|
||||
if (flags & FLG_OP_NONBLOCK) return EAGAIN; /* not supported */
|
||||
if (flags & CDEV_NONBLOCK) return EAGAIN; /* not supported */
|
||||
|
||||
/* If no errors occurred, continue printing with the caller.
|
||||
* First wait until the printer is online to prevent stupid errors.
|
||||
|
|
|
@ -261,7 +261,7 @@ kbd_read(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt,
|
|||
|
||||
/* If no data is available, suspend the caller. */
|
||||
if (kbdp->avail == 0) {
|
||||
if (flags & FLG_OP_NONBLOCK)
|
||||
if (flags & CDEV_NONBLOCK)
|
||||
return EAGAIN;
|
||||
kbdp->req_size = size;
|
||||
kbdp->req_id = id;
|
||||
|
@ -420,14 +420,14 @@ kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
|||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
watch = (ops & SEL_NOTIFY);
|
||||
ops &= (SEL_RD | SEL_WR | SEL_ERR);
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = 0;
|
||||
if (kbdp->avail && (ops & SEL_RD))
|
||||
ready_ops |= SEL_RD;
|
||||
if (ops & SEL_WR)
|
||||
ready_ops |= SEL_WR; /* writes never block */
|
||||
if (kbdp->avail && (ops & CDEV_OP_RD))
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
if (ops & CDEV_OP_WR)
|
||||
ready_ops |= CDEV_OP_WR; /* writes never block */
|
||||
|
||||
ops &= ~ready_ops;
|
||||
if (ops && watch) {
|
||||
|
@ -543,10 +543,10 @@ void kbd_interrupt(message *UNUSED(m_ptr))
|
|||
kbdp->req_caller = NONE;
|
||||
}
|
||||
/* Only satisfy pending select if characters weren't just read. */
|
||||
if (kbdp->avail && (kbdp->select_ops & SEL_RD)) {
|
||||
if (kbdp->avail && (kbdp->select_ops & CDEV_OP_RD)) {
|
||||
chardriver_reply_select(kbdp->select_proc, kbdp->minor,
|
||||
SEL_RD);
|
||||
kbdp->select_ops &= ~SEL_RD;
|
||||
CDEV_OP_RD);
|
||||
kbdp->select_ops &= ~CDEV_OP_RD;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ void kbd_interrupt(message *UNUSED(m_ptr))
|
|||
if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
|
||||
icount++;
|
||||
tty_table[ccurrent].tty_events = 1;
|
||||
if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
|
||||
if (tty_table[ccurrent].tty_select_ops & CDEV_OP_RD) {
|
||||
select_retry(&tty_table[ccurrent]);
|
||||
}
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ void do_kb_inject(message *msg)
|
|||
if (injhead == injbuf + KB_IN_BYTES) injhead = injbuf;
|
||||
injcount++;
|
||||
tty_table[ccurrent].tty_events = 1;
|
||||
if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
|
||||
if (tty_table[ccurrent].tty_select_ops & CDEV_OP_RD) {
|
||||
select_retry(&tty_table[ccurrent]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ static ssize_t pty_master_read(devminor_t minor, u64_t UNUSED(position),
|
|||
return EDONTREPLY; /* already done */
|
||||
}
|
||||
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdcaller = NONE;
|
||||
|
@ -214,7 +214,7 @@ static ssize_t pty_master_write(devminor_t minor, u64_t UNUSED(position),
|
|||
return EDONTREPLY; /* already done */
|
||||
}
|
||||
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrcaller = NONE;
|
||||
|
@ -265,18 +265,18 @@ static int select_try_pty(tty_t *tp, int ops)
|
|||
pty_t *pp = tp->tty_priv;
|
||||
int r = 0;
|
||||
|
||||
if (ops & SEL_WR) {
|
||||
if (ops & CDEV_OP_WR) {
|
||||
/* Write won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= SEL_WR;
|
||||
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
|
||||
else if (tp->tty_inleft > 0) r |= SEL_WR; /* There's a reader. */
|
||||
if (pp->state & TTY_CLOSED) r |= CDEV_OP_WR;
|
||||
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= CDEV_OP_WR;
|
||||
else if (tp->tty_inleft > 0) r |= CDEV_OP_WR; /* There's a reader. */
|
||||
}
|
||||
|
||||
if (ops & SEL_RD) {
|
||||
if (ops & CDEV_OP_RD) {
|
||||
/* Read won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= SEL_RD;
|
||||
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
|
||||
else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */
|
||||
if (pp->state & TTY_CLOSED) r |= CDEV_OP_RD;
|
||||
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= CDEV_OP_RD;
|
||||
else if (pp->ocount > 0) r |= CDEV_OP_RD; /* Actual data. */
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -313,8 +313,8 @@ static int pty_master_select(devminor_t minor, unsigned int ops,
|
|||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
watch = (ops & SEL_NOTIFY);
|
||||
ops &= (SEL_RD | SEL_WR | SEL_ERR);
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = select_try_pty(tp, ops);
|
||||
|
||||
|
|
|
@ -16,38 +16,6 @@
|
|||
* to, you guessed it, wake up the TTY to check if input or output can
|
||||
* continue.
|
||||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* notify from HARDWARE: output has been completed or input has arrived
|
||||
* notify from SYSTEM : e.g., MINIX wants to shutdown; run code to
|
||||
* cleanly stop
|
||||
* DEV_READ: a process wants to read from a terminal
|
||||
* DEV_WRITE: a process wants to write on a terminal
|
||||
* DEV_IOCTL: a process wants to change a terminal's parameters
|
||||
* DEV_OPEN: a tty line has been opened
|
||||
* DEV_CLOSE: a tty line has been closed
|
||||
* DEV_SELECT: start select notification request
|
||||
* CANCEL: terminate a previous incomplete system call immediately
|
||||
*
|
||||
* m_type DEVICE USER_ENDPT COUNT POSITION IO_GRANT
|
||||
* -----------------------------------------------------------------
|
||||
* | HARD_INT | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_READ |minor dev| proc nr | count | | grant |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE |minor dev| proc nr | count | | grant |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_IOCTL |minor dev| proc nr |func code|user proc| |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_OPEN |minor dev| proc nr | O_NOCTTY| | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE |minor dev| proc nr | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | CANCEL |minor dev| proc nr | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_SELECT |minor dev| sel ops | | | |
|
||||
* -----------------------------------------------------------------
|
||||
*
|
||||
* Changes:
|
||||
* Jan 20, 2004 moved TTY driver to user-space (Jorrit N. Herder)
|
||||
* Sep 20, 2004 local timer management/ sync alarms (Jorrit N. Herder)
|
||||
|
@ -235,7 +203,7 @@ int main(void)
|
|||
; /* do nothing; end switch */
|
||||
}
|
||||
|
||||
if (!IS_DEV_RQ(tty_mess.m_type)) {
|
||||
if (!IS_CDEV_RQ(tty_mess.m_type)) {
|
||||
chardriver_process(&tty_tab, &tty_mess, ipc_status);
|
||||
continue;
|
||||
}
|
||||
|
@ -243,7 +211,7 @@ int main(void)
|
|||
/* Only device requests should get to this point.
|
||||
* All requests have a minor device number.
|
||||
*/
|
||||
line = tty_mess.DEVICE;
|
||||
line = tty_mess.CDEV_MINOR;
|
||||
if (line == KBD_MINOR || line == KBDAUX_MINOR) {
|
||||
do_kbd(&tty_mess, ipc_status);
|
||||
continue;
|
||||
|
@ -251,7 +219,7 @@ int main(void)
|
|||
do_video(&tty_mess, ipc_status);
|
||||
continue;
|
||||
} else if (line - PTYPX_MINOR < NR_PTYS &&
|
||||
tty_mess.m_type != DEV_IOCTL_S) {
|
||||
tty_mess.m_type != CDEV_IOCTL) {
|
||||
/* Terminals and pseudo terminals belong together. We can only
|
||||
* make a distinction between the two based on position in the
|
||||
* tty_table and not on minor number (i.e., use ispty macro).
|
||||
|
@ -276,7 +244,7 @@ set_color(tty_t *tp, int color)
|
|||
buf[0] = '\033';
|
||||
snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color);
|
||||
do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
|
||||
FLG_OP_NONBLOCK, 0);
|
||||
CDEV_NONBLOCK, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -288,7 +256,7 @@ reset_color(tty_t *tp)
|
|||
buf[0] = '\033';
|
||||
snprintf(&buf[1], sizeof(buf) - 1, "[0;%dm", SGR_COLOR_RESET);
|
||||
do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
|
||||
FLG_OP_NONBLOCK, 0);
|
||||
CDEV_NONBLOCK, 0);
|
||||
}
|
||||
|
||||
tty_t *
|
||||
|
@ -466,7 +434,7 @@ do_new_kmess(void)
|
|||
set_color(tp, kernel_msg_color);
|
||||
do_write(tp->tty_minor, 0, KERNEL,
|
||||
(cp_grant_id_t) kernel_buf_copy, bytes,
|
||||
FLG_OP_NONBLOCK, 0);
|
||||
CDEV_NONBLOCK, 0);
|
||||
if (kernel_msg_color != 0)
|
||||
reset_color(tp);
|
||||
if (restore) {
|
||||
|
@ -553,7 +521,7 @@ static ssize_t do_read(devminor_t minor, u64_t UNUSED(position),
|
|||
return EDONTREPLY; /* already done */
|
||||
|
||||
/* There were no bytes in the input queue available. */
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
tty_icancel(tp);
|
||||
r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
|
@ -602,7 +570,7 @@ static ssize_t do_write(devminor_t minor, u64_t UNUSED(position),
|
|||
return EDONTREPLY; /* already done */
|
||||
|
||||
/* None or not all the bytes could be written. */
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
|
@ -677,7 +645,7 @@ static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
|||
case TCSETSF:
|
||||
case TCDRAIN:
|
||||
if (tp->tty_outleft > 0) {
|
||||
if (flags & FLG_OP_NONBLOCK)
|
||||
if (flags & CDEV_NONBLOCK)
|
||||
return EAGAIN;
|
||||
/* Wait for all ongoing output processing to finish. */
|
||||
tp->tty_iocaller = endpt;
|
||||
|
@ -771,8 +739,8 @@ static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
|||
static int do_open(devminor_t minor, int access, endpoint_t user_endpt)
|
||||
{
|
||||
/* A tty line has been opened. Make it the callers controlling tty if
|
||||
* O_NOCTTY is *not* set and it is not the log device. 1 is returned if
|
||||
* the tty is made the controlling tty, otherwise OK or an error code.
|
||||
* CDEV_NOCTTY is *not* set and it is not the log device. CDEV_CTTY is returned
|
||||
* if the tty is made the controlling tty, otherwise OK or an error code.
|
||||
*/
|
||||
tty_t *tp;
|
||||
int r = OK;
|
||||
|
@ -782,11 +750,11 @@ static int do_open(devminor_t minor, int access, endpoint_t user_endpt)
|
|||
|
||||
if (minor == LOG_MINOR && isconsole(tp)) {
|
||||
/* The log device is a write-only diagnostics device. */
|
||||
if (access & R_BIT) return EACCES;
|
||||
if (access & CDEV_R_BIT) return EACCES;
|
||||
} else {
|
||||
if (!(access & O_NOCTTY)) {
|
||||
if (!(access & CDEV_NOCTTY)) {
|
||||
tp->tty_pgrp = user_endpt;
|
||||
r = 1;
|
||||
r = CDEV_CTTY;
|
||||
}
|
||||
tp->tty_openct++;
|
||||
if (tp->tty_openct == 1) {
|
||||
|
@ -874,10 +842,10 @@ int select_try(struct tty *tp, int ops)
|
|||
ready_ops |= ops;
|
||||
}
|
||||
|
||||
if (ops & SEL_RD) {
|
||||
if (ops & CDEV_OP_RD) {
|
||||
/* will i/o not block on read? */
|
||||
if (tp->tty_inleft > 0) {
|
||||
ready_ops |= SEL_RD; /* EIO - no blocking */
|
||||
ready_ops |= CDEV_OP_RD; /* EIO - no blocking */
|
||||
} else if (tp->tty_incount > 0) {
|
||||
/* Is a regular read possible? tty_incount
|
||||
* says there is data. But a read will only succeed
|
||||
|
@ -885,14 +853,14 @@ int select_try(struct tty *tp, int ops)
|
|||
*/
|
||||
if (!(tp->tty_termios.c_lflag & ICANON) ||
|
||||
tp->tty_eotct > 0) {
|
||||
ready_ops |= SEL_RD;
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ops & SEL_WR) {
|
||||
if (tp->tty_outleft > 0) ready_ops |= SEL_WR;
|
||||
else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= SEL_WR;
|
||||
if (ops & CDEV_OP_WR) {
|
||||
if (tp->tty_outleft > 0) ready_ops |= CDEV_OP_WR;
|
||||
else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= CDEV_OP_WR;
|
||||
}
|
||||
return ready_ops;
|
||||
}
|
||||
|
@ -924,8 +892,8 @@ static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
|||
if (tp->tty_minor != minor)
|
||||
return EBADF;
|
||||
|
||||
watch = (ops & SEL_NOTIFY);
|
||||
ops &= (SEL_RD | SEL_WR | SEL_ERR);
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = select_try(tp, ops);
|
||||
|
||||
|
|
|
@ -25,9 +25,6 @@
|
|||
|
||||
#define ESC '\33' /* escape */
|
||||
|
||||
#define O_NOCTTY 00400 /* from <fcntl.h>, or cc will choke */
|
||||
#define O_NONBLOCK 04000
|
||||
|
||||
struct tty;
|
||||
typedef int(*devfun_t) (struct tty *tp, int try_only);
|
||||
typedef void(*devfunarg_t) (struct tty *tp, int c);
|
||||
|
|
|
@ -65,10 +65,10 @@ kill_by_name syslogd
|
|||
sleep 3
|
||||
if [ X`/bin/sysenv lwip` = Xyes ]
|
||||
then
|
||||
service up /usr/sbin/lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
service up /usr/sbin/lwip -script /etc/rs.inet -dev /dev/ip
|
||||
dhcpd --lwip &
|
||||
else
|
||||
service up /usr/sbin/inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
service up /usr/sbin/inet -script /etc/rs.inet -dev /dev/ip
|
||||
daemonize dhcpd
|
||||
fi
|
||||
daemonize nonamed -L
|
||||
|
|
|
@ -188,9 +188,9 @@ start)
|
|||
done
|
||||
if [ X`/bin/sysenv lwip` = Xyes ]
|
||||
then
|
||||
up lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
up lwip -script /etc/rs.inet -dev /dev/ip
|
||||
else
|
||||
up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
up inet -script /etc/rs.inet -dev /dev/ip
|
||||
fi
|
||||
|
||||
up -n ipc
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
* 1 - 0xFF POSIX requests (see callnr.h)
|
||||
* 0x200 - 0x2FF Data link layer requests and responses
|
||||
* 0x300 - 0x3FF Bus controller requests and responses
|
||||
* 0x400 - 0x4FF Character device requests
|
||||
* 0x500 - 0x5FF Character device responses
|
||||
* 0x400 - 0x4FF Character device requests and responses
|
||||
* 0x500 - 0x5FF Block device requests and responses
|
||||
* 0x600 - 0x6FF Kernel calls to SYSTEM task
|
||||
* 0x700 - 0x7FF Reincarnation Server (RS) requests
|
||||
* 0x800 - 0x8FF Data Store (DS) requests
|
||||
|
@ -25,7 +25,7 @@
|
|||
* 0x1200 - 0x12FF Devman
|
||||
* 0x1300 - 0x13FF TTY Requests
|
||||
* 0x1400 - 0x14FF VFS-FS transaction IDs
|
||||
* 0x1500 - 0x15FF Block device requests and responses
|
||||
* 0x1500 - 0x15FF (unused)
|
||||
* 0x1600 - 0x16FF VirtualBox (VBOX) requests (see vboxif.h)
|
||||
* 0x1700 - 0x17FF Real Time Clock requests and responses
|
||||
*
|
||||
|
@ -186,58 +186,6 @@
|
|||
#define BUSC_I2C_EXEC (BUSC_RQ_BASE + 65) /* perform i2c action */
|
||||
#define BUSC_I2C_GRANT m2_i1 /* grant for request */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for CHARACTER device drivers *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Message types for character device drivers. */
|
||||
#define DEV_RQ_BASE 0x400 /* base for character device request types */
|
||||
#define DEV_RS_BASE 0x500 /* base for character device response types */
|
||||
|
||||
#define CANCEL (DEV_RQ_BASE + 0) /* force a task to cancel */
|
||||
#define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */
|
||||
#define DEV_CLOSE (DEV_RQ_BASE + 7) /* close a minor device */
|
||||
#define DEV_SELECT (DEV_RQ_BASE + 12) /* request select() attention */
|
||||
|
||||
#define DEV_READ_S (DEV_RQ_BASE + 20) /* (safecopy) read from minor */
|
||||
#define DEV_WRITE_S (DEV_RQ_BASE + 21) /* (safecopy) write to minor */
|
||||
#define DEV_SCATTER_S (DEV_RQ_BASE + 22) /* (safecopy) write from a vector */
|
||||
#define DEV_GATHER_S (DEV_RQ_BASE + 23) /* (safecopy) read into a vector */
|
||||
#define DEV_IOCTL_S (DEV_RQ_BASE + 24) /* (safecopy) I/O control code */
|
||||
|
||||
#define IS_DEV_RQ(type) (((type) & ~0xff) == DEV_RQ_BASE)
|
||||
|
||||
#define DEV_REVIVE (DEV_RS_BASE + 2) /* driver revives process */
|
||||
#define DEV_CLOSE_REPL (DEV_RS_BASE + 6) /* reply to DEV_CLOSE */
|
||||
#define DEV_SEL_REPL1 (DEV_RS_BASE + 7) /* first reply to DEV_SELECT */
|
||||
#define DEV_SEL_REPL2 (DEV_RS_BASE + 8) /* (opt) second reply to DEV_SELECT */
|
||||
#define DEV_OPEN_REPL (DEV_RS_BASE + 9) /* reply to DEV_OPEN */
|
||||
|
||||
#define IS_DEV_RS(type) (((type) & ~0xff) == DEV_RS_BASE)
|
||||
|
||||
/* Field names for messages to character device drivers. */
|
||||
#define DEVICE m2_i1 /* major-minor device */
|
||||
#define USER_ENDPT m2_i2 /* which endpoint initiated this call? */
|
||||
#define COUNT m2_i3 /* how many bytes to transfer */
|
||||
#define REQUEST m2_i3 /* ioctl request code */
|
||||
#define POSITION m2_l1 /* file offset (low 4 bytes) */
|
||||
#define HIGHPOS m2_l2 /* file offset (high 4 bytes) */
|
||||
#define ADDRESS m2_p1 /* core buffer address */
|
||||
#define IO_GRANT m2_p1 /* grant id (for DEV_*_S variants) */
|
||||
#define FLAGS m2_s1 /* operation flags */
|
||||
|
||||
#define FLG_OP_NONBLOCK 0x1 /* operation is non blocking */
|
||||
|
||||
/* Field names for DEV_SELECT messages to character device drivers. */
|
||||
#define DEV_MINOR m2_i1 /* minor device */
|
||||
#define DEV_SEL_OPS m2_i2 /* which select operations are requested */
|
||||
|
||||
/* Field names used in reply messages from tasks. */
|
||||
#define REP_ENDPT m2_i1 /* # of proc on whose behalf I/O was done */
|
||||
#define REP_STATUS m2_i2 /* bytes transferred or error number */
|
||||
#define REP_IO_GRANT m2_i3 /* DEV_REVIVE: grant by which I/O was done */
|
||||
# define SUSPEND -998 /* status to suspend caller, reply later */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for networking layer *
|
||||
*===========================================================================*/
|
||||
|
@ -939,6 +887,11 @@
|
|||
#define VFS_PFS_FD m2_i3
|
||||
#define VFS_PFS_FILP m2_p1
|
||||
|
||||
/* Field names for GETRUSAGE related calls */
|
||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||
#define RU_RUSAGE_ADDR m1_p1 /* pointer to struct rusage */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for VM server *
|
||||
*===========================================================================*/
|
||||
|
@ -1298,13 +1251,71 @@
|
|||
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
|
||||
#define IS_VFS_FS_TRANSID(type) (((type) & ~0xff) == VFS_TRANSACTION_BASE)
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for character devices *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Base type for character device requests and responses. */
|
||||
#define CDEV_RQ_BASE 0x400
|
||||
#define CDEV_RS_BASE 0x480
|
||||
|
||||
#define IS_CDEV_RQ(type) (((type) & ~0x7f) == CDEV_RQ_BASE)
|
||||
#define IS_CDEV_RS(type) (((type) & ~0x7f) == CDEV_RS_BASE)
|
||||
|
||||
/* Message types for character device requests. */
|
||||
#define CDEV_OPEN (CDEV_RQ_BASE + 0) /* open a minor device */
|
||||
#define CDEV_CLOSE (CDEV_RQ_BASE + 1) /* close a minor device */
|
||||
#define CDEV_READ (CDEV_RQ_BASE + 2) /* read into a buffer */
|
||||
#define CDEV_WRITE (CDEV_RQ_BASE + 3) /* write from a buffer */
|
||||
#define CDEV_IOCTL (CDEV_RQ_BASE + 4) /* I/O control operation */
|
||||
#define CDEV_CANCEL (CDEV_RQ_BASE + 5) /* cancel suspended request */
|
||||
#define CDEV_SELECT (CDEV_RQ_BASE + 6) /* test for ready operations */
|
||||
|
||||
/* Message types for character device responses. */
|
||||
#define CDEV_REPLY (CDEV_RS_BASE + 0) /* general reply code */
|
||||
#define CDEV_SEL1_REPLY (CDEV_RS_BASE + 1) /* immediate select reply */
|
||||
#define CDEV_SEL2_REPLY (CDEV_RS_BASE + 2) /* select notification reply */
|
||||
|
||||
/* Field names for block device messages. */
|
||||
#define CDEV_MINOR m10_i1 /* minor device number */
|
||||
#define CDEV_STATUS m10_i2 /* OK, error code, minor device, operations */
|
||||
#define CDEV_ACCESS m10_i2 /* access bits for open requests */
|
||||
#define CDEV_GRANT m10_i2 /* grant ID of buffer */
|
||||
#define CDEV_OPS m10_i2 /* requested select operations */
|
||||
#define CDEV_COUNT m10_i3 /* number of bytes to transfer */
|
||||
#define CDEV_USER m10_i3 /* endpoint of user process */
|
||||
#define CDEV_FLAGS m10_i4 /* transfer flags */
|
||||
#define CDEV_ID m10_l1 /* opaque request ID */
|
||||
#define CDEV_REQUEST m10_l2 /* I/O control request */
|
||||
#define CDEV_POS_LO m10_l2 /* transfer position (low bits) */
|
||||
#define CDEV_POS_HI m10_l3 /* transfer position (high bits) */
|
||||
|
||||
/* Bits in 'CDEV_ACCESS' field of block device open requests. */
|
||||
# define CDEV_R_BIT 0x01 /* open with read access */
|
||||
# define CDEV_W_BIT 0x02 /* open with write access */
|
||||
# define CDEV_NOCTTY 0x04 /* not to become the controlling TTY */
|
||||
|
||||
/* Bits in 'CDEV_FLAGS' field of block device transfer requests. */
|
||||
# define CDEV_NOFLAGS 0x00 /* no flags are set */
|
||||
# define CDEV_NONBLOCK 0x01 /* do not suspend I/O request */
|
||||
|
||||
/* Bits in 'CDEV_OPS', 'CDEV_STATUS' fields of block device select messages. */
|
||||
# define CDEV_OP_RD 0x01 /* selected for read operation */
|
||||
# define CDEV_OP_WR 0x02 /* selected for write operation */
|
||||
# define CDEV_OP_ERR 0x04 /* selected for error operation */
|
||||
# define CDEV_NOTIFY 0x08 /* notification requested */
|
||||
|
||||
/* Bits in 'CDEV_STATUS' field of block device open responses. */
|
||||
# define CDEV_CLONED 0x20000000 /* device is cloned */
|
||||
# define CDEV_CTTY 0x40000000 /* device is controlling TTY */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for block devices *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Base type for block device requests and responses. */
|
||||
#define BDEV_RQ_BASE 0x1500
|
||||
#define BDEV_RS_BASE 0x1580
|
||||
#define BDEV_RQ_BASE 0x500
|
||||
#define BDEV_RS_BASE 0x580
|
||||
|
||||
#define IS_BDEV_RQ(type) (((type) & ~0x7f) == BDEV_RQ_BASE)
|
||||
#define IS_BDEV_RS(type) (((type) & ~0x7f) == BDEV_RS_BASE)
|
||||
|
@ -1343,11 +1354,6 @@
|
|||
# define BDEV_FORCEWRITE 0x01 /* force write to disk immediately */
|
||||
# define BDEV_NOPAGE 0x02 /* eeprom: don't send page address */
|
||||
|
||||
/* Field names for GETRUSAGE related calls */
|
||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||
#define RU_RUSAGE_ADDR m1_p1 /* pointer to struct rusage */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for Real Time Clocks *
|
||||
*===========================================================================*/
|
||||
|
@ -1382,4 +1388,10 @@
|
|||
#define RTCDEV_Y2KBUG 0x01 /* Interpret 1980 as 2000 for RTC w/Y2K bug */
|
||||
#define RTCDEV_CMOSREG 0x02 /* Also set the CMOS clock register bits. */
|
||||
|
||||
/*===========================================================================*
|
||||
* Internal codes used by several services *
|
||||
*===========================================================================*/
|
||||
|
||||
#define SUSPEND -998 /* status to suspend caller, reply later */
|
||||
|
||||
/* _MINIX_COM_H */
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include <minix/sys_config.h>
|
||||
#include <minix/ipc.h>
|
||||
|
||||
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY, STYLE_CLONE };
|
||||
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CLONE)
|
||||
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY };
|
||||
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CTTY)
|
||||
|
||||
/*===========================================================================*
|
||||
* Major and minor device numbers *
|
||||
|
|
|
@ -6,23 +6,6 @@
|
|||
* This driver also support sub devices, which can be independently
|
||||
* opened and closed.
|
||||
*
|
||||
* The driver supports the following operations:
|
||||
*
|
||||
* m_type DEVICE USER_ENDPT COUNT POSITION ADRRESS
|
||||
* -----------------------------------------------------------------
|
||||
* | DEV_OPEN | device | proc nr | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE | device | proc nr | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_READ_S | device | proc nr | bytes | | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE_S | device | proc nr | bytes | | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_IOCTL_S | device | proc nr |func code| | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | HARD_INT | | | | | |
|
||||
* -----------------------------------------------------------------
|
||||
*
|
||||
* The file contains one entry point:
|
||||
*
|
||||
* main: main entry when driver is brought up
|
||||
|
|
|
@ -369,9 +369,9 @@ static void do_char_open(message *m_ptr, int ipc_status)
|
|||
|
||||
memset(&m_reply, 0, sizeof(m_reply));
|
||||
|
||||
m_reply.m_type = DEV_OPEN_REPL;
|
||||
m_reply.REP_ENDPT = m_ptr->USER_ENDPT;
|
||||
m_reply.REP_STATUS = ENXIO;
|
||||
m_reply.m_type = CDEV_REPLY;
|
||||
m_reply.CDEV_STATUS = ENXIO;
|
||||
m_reply.CDEV_ID = m_ptr->CDEV_ID;
|
||||
|
||||
send_reply(m_ptr->m_source, &m_reply, ipc_status);
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ void blockdriver_process_on_thread(struct blockdriver *bdp, message *m_ptr,
|
|||
* someone creates a character device node for a block driver, opening that
|
||||
* device node will cause the corresponding VFS thread to block forever.
|
||||
*/
|
||||
if (m_ptr->m_type == DEV_OPEN) {
|
||||
if (m_ptr->m_type == CDEV_OPEN) {
|
||||
do_char_open(m_ptr, ipc_status);
|
||||
|
||||
return;
|
||||
|
|
|
@ -1,27 +1,36 @@
|
|||
/* This file contains the device independent character driver interface.
|
||||
*
|
||||
* The drivers support the following operations (using message format m2):
|
||||
* Charaxter drivers support the following requests. Message format m10 is
|
||||
* used. Field names are prefixed with CDEV_. Separate field names are used for
|
||||
* the "access", "ops", "user", and "request" fields.
|
||||
*
|
||||
* m_type DEVICE USER_ENDPT COUNT POSITION HIGHPOS IO_GRANT
|
||||
* ----------------------------------------------------------------------------
|
||||
* | DEV_OPEN | device | proc nr | mode | | | |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_CLOSE | device | proc nr | | | | |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_READ_S | device | proc nr | bytes | off lo | off hi i buf grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_WRITE_S | device | proc nr | bytes | off lo | off hi | buf grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_GATHER_S | device | proc nr | iov len | off lo | off hi | iov grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_SCATTER_S | device | proc nr | iov len | off lo | off hi | iov grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_IOCTL_S | device | proc nr | request | | | buf grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | CANCEL | device | proc nr | r/w | | | grant |
|
||||
* |---------------+--------+---------+---------+--------+--------+-----------|
|
||||
* | DEV_SELECT | device | ops | | | | |
|
||||
* ----------------------------------------------------------------------------
|
||||
* m_type MINOR GRANT COUNT FLAGS ID POS_LO POS_HI
|
||||
* +-------------+-------+--------+-------+-------+------+---------+--------+
|
||||
* | CDEV_OPEN | minor | access | user | | id | | |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_CLOSE | minor | | | | id | | |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_READ | minor | grant | bytes | flags | id | position |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_WRITE | minor | grant | bytes | flags | id | position |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_IOCTL | minor | grant | user | flags | id | request | |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_CANCEL | minor | | | | id | | |
|
||||
* |-------------+-------+--------+-------+-------+------+---------+--------|
|
||||
* | CDEV_SELECT | minor | ops | | | | | |
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The following reply messages are used.
|
||||
*
|
||||
* m_type MINOR STATUS ID
|
||||
* +-----------------+-------+--------+-----+-----+------+---------+--------+
|
||||
* | CDEV_REPLY | | status | | | id | | |
|
||||
* |-----------------+-------+--------+-----+-----+------+---------+--------|
|
||||
* | CDEV_SEL1_REPLY | minor | status | | | | | |
|
||||
* |-----------------+-------+--------+-----+-----+------+---------+--------|
|
||||
* | CDEV_SEL2_REPLY | minor | status | | | | | |
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Changes:
|
||||
* Sep 01, 2013 complete rewrite of the API (D.C. van Moolenboek)
|
||||
|
@ -110,7 +119,7 @@ void chardriver_announce(void)
|
|||
if ((r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)) != OK)
|
||||
panic("chardriver_init: unable to publish driver up event: %d", r);
|
||||
|
||||
/* Expect a DEV_OPEN for any device before serving regular driver requests. */
|
||||
/* Expect an open for any device before serving regular driver requests. */
|
||||
clear_open_devs();
|
||||
}
|
||||
|
||||
|
@ -130,10 +139,9 @@ void chardriver_reply_task(endpoint_t endpt, cdev_id_t id, int r)
|
|||
|
||||
memset(&m_reply, 0, sizeof(m_reply));
|
||||
|
||||
m_reply.m_type = DEV_REVIVE;
|
||||
m_reply.REP_STATUS = r;
|
||||
m_reply.REP_ENDPT = endpt; /* XXX FIXME: hack */
|
||||
m_reply.REP_IO_GRANT = (cp_grant_id_t) id;
|
||||
m_reply.m_type = CDEV_REPLY;
|
||||
m_reply.CDEV_STATUS = r;
|
||||
m_reply.CDEV_ID = id;
|
||||
|
||||
if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK)
|
||||
printf("chardriver_reply_task: send to %d failed: %d\n", endpt, r);
|
||||
|
@ -155,9 +163,9 @@ void chardriver_reply_select(endpoint_t endpt, devminor_t minor, int r)
|
|||
|
||||
memset(&m_reply, 0, sizeof(m_reply));
|
||||
|
||||
m_reply.m_type = DEV_SEL_REPL2;
|
||||
m_reply.DEV_MINOR = minor;
|
||||
m_reply.DEV_SEL_OPS = r;
|
||||
m_reply.m_type = CDEV_SEL2_REPLY;
|
||||
m_reply.CDEV_MINOR = minor;
|
||||
m_reply.CDEV_STATUS = r;
|
||||
|
||||
if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK)
|
||||
printf("chardriver_reply_select: send to %d failed: %d\n", endpt, r);
|
||||
|
@ -194,15 +202,20 @@ static void chardriver_reply(message *mess, int ipc_status, int r)
|
|||
*/
|
||||
if (r == EDONTREPLY) {
|
||||
switch (mess->m_type) {
|
||||
case DEV_READ_S:
|
||||
case DEV_WRITE_S:
|
||||
case DEV_IOCTL_S:
|
||||
#if 0 /* XXX doesn't match lwip's model, disabled for now */
|
||||
if (mess->FLAGS & FLG_OP_NONBLOCK)
|
||||
case CDEV_READ:
|
||||
case CDEV_WRITE:
|
||||
case CDEV_IOCTL:
|
||||
/* FIXME: we should be able to check CDEV_FLAGS against
|
||||
* CDEV_NONBLOCK here, but in practice, several drivers do not
|
||||
* send a reply through this path (eg TTY) or simply do not
|
||||
* implement nonblocking calls properly (eg audio, LWIP).
|
||||
*/
|
||||
#if 0
|
||||
if (mess->CDEV_FLAGS & CDEV_NONBLOCK)
|
||||
panic("chardriver: cannot suspend nonblocking I/O");
|
||||
#endif
|
||||
/*fall-through*/
|
||||
case CANCEL:
|
||||
case CDEV_CANCEL:
|
||||
return; /* alright */
|
||||
default:
|
||||
panic("chardriver: cannot suspend request %d", mess->m_type);
|
||||
|
@ -222,32 +235,21 @@ static void chardriver_reply(message *mess, int ipc_status, int r)
|
|||
memset(&reply_mess, 0, sizeof(reply_mess));
|
||||
|
||||
switch (mess->m_type) {
|
||||
case DEV_OPEN:
|
||||
reply_mess.m_type = DEV_OPEN_REPL;
|
||||
reply_mess.REP_ENDPT = mess->USER_ENDPT;
|
||||
reply_mess.REP_STATUS = r;
|
||||
case CDEV_OPEN:
|
||||
case CDEV_CLOSE:
|
||||
case CDEV_READ:
|
||||
case CDEV_WRITE:
|
||||
case CDEV_IOCTL:
|
||||
case CDEV_CANCEL: /* For cancel, this is a reply to the original request! */
|
||||
reply_mess.m_type = CDEV_REPLY;
|
||||
reply_mess.CDEV_STATUS = r;
|
||||
reply_mess.CDEV_ID = mess->CDEV_ID;
|
||||
break;
|
||||
|
||||
case DEV_CLOSE:
|
||||
reply_mess.m_type = DEV_CLOSE_REPL;
|
||||
reply_mess.REP_ENDPT = mess->USER_ENDPT;
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
|
||||
case DEV_READ_S:
|
||||
case DEV_WRITE_S:
|
||||
case DEV_IOCTL_S:
|
||||
case CANCEL: /* For CANCEL, this is a reply to the original request! */
|
||||
reply_mess.m_type = DEV_REVIVE;
|
||||
reply_mess.REP_ENDPT = mess->USER_ENDPT;
|
||||
reply_mess.REP_IO_GRANT = (cp_grant_id_t) mess->IO_GRANT;
|
||||
reply_mess.REP_STATUS = r;
|
||||
break;
|
||||
|
||||
case DEV_SELECT:
|
||||
reply_mess.m_type = DEV_SEL_REPL1;
|
||||
reply_mess.DEV_MINOR = mess->DEVICE;
|
||||
reply_mess.DEV_SEL_OPS = r;
|
||||
case CDEV_SELECT:
|
||||
reply_mess.m_type = CDEV_SEL1_REPLY;
|
||||
reply_mess.CDEV_MINOR = mess->CDEV_MINOR;
|
||||
reply_mess.CDEV_STATUS = r;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -272,15 +274,18 @@ static int do_open(struct chardriver *cdp, message *m_ptr)
|
|||
return OK;
|
||||
|
||||
/* Call the open hook. */
|
||||
minor = m_ptr->DEVICE;
|
||||
access = m_ptr->COUNT;
|
||||
user_endpt = m_ptr->USER_ENDPT;
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
access = m_ptr->CDEV_ACCESS;
|
||||
user_endpt = m_ptr->CDEV_USER;
|
||||
|
||||
r = cdp->cdr_open(minor, access, user_endpt);
|
||||
|
||||
/* If the device has been cloned, mark the new minor as open too. */
|
||||
if (r >= 0 && !is_open_dev(r)) /* XXX FIXME */
|
||||
set_open_dev(r);
|
||||
if (r >= 0 && (r & CDEV_CLONED)) {
|
||||
minor = r & ~(CDEV_CLONED | CDEV_CTTY);
|
||||
if (!is_open_dev(minor))
|
||||
set_open_dev(minor);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -298,7 +303,7 @@ static int do_close(struct chardriver *cdp, message *m_ptr)
|
|||
return OK;
|
||||
|
||||
/* Call the close hook. */
|
||||
minor = m_ptr->DEVICE;
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
|
||||
return cdp->cdr_close(minor);
|
||||
}
|
||||
|
@ -318,13 +323,13 @@ static int do_transfer(struct chardriver *cdp, message *m_ptr, int do_write)
|
|||
cdev_id_t id;
|
||||
ssize_t r;
|
||||
|
||||
minor = m_ptr->DEVICE;
|
||||
position = make64(m_ptr->POSITION, m_ptr->HIGHPOS);
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
position = make64(m_ptr->CDEV_POS_LO, m_ptr->CDEV_POS_HI);
|
||||
endpt = m_ptr->m_source;
|
||||
grant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
||||
size = m_ptr->COUNT;
|
||||
flags = m_ptr->FLAGS;
|
||||
id = (cdev_id_t) m_ptr->IO_GRANT;
|
||||
grant = (cp_grant_id_t) m_ptr->CDEV_GRANT;
|
||||
size = m_ptr->CDEV_COUNT;
|
||||
flags = m_ptr->CDEV_FLAGS;
|
||||
id = m_ptr->CDEV_ID;
|
||||
|
||||
/* Call the read/write hook, if the appropriate one is in place. */
|
||||
if (!do_write && cdp->cdr_read != NULL)
|
||||
|
@ -355,13 +360,13 @@ static int do_ioctl(struct chardriver *cdp, message *m_ptr)
|
|||
return ENOTTY;
|
||||
|
||||
/* Call the ioctl hook. */
|
||||
minor = m_ptr->DEVICE;
|
||||
request = m_ptr->REQUEST;
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
request = m_ptr->CDEV_REQUEST;
|
||||
endpt = m_ptr->m_source;
|
||||
grant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
||||
flags = m_ptr->FLAGS;
|
||||
user_endpt = (endpoint_t) m_ptr->POSITION;
|
||||
id = (cdev_id_t) m_ptr->IO_GRANT;
|
||||
grant = m_ptr->CDEV_GRANT;
|
||||
flags = m_ptr->CDEV_FLAGS;
|
||||
user_endpt = m_ptr->CDEV_USER;
|
||||
id = m_ptr->CDEV_ID;
|
||||
|
||||
return cdp->cdr_ioctl(minor, request, endpt, grant, flags, user_endpt, id);
|
||||
}
|
||||
|
@ -383,9 +388,9 @@ static int do_cancel(struct chardriver *cdp, message *m_ptr)
|
|||
return EDONTREPLY;
|
||||
|
||||
/* Call the cancel hook. */
|
||||
minor = m_ptr->DEVICE;
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
endpt = m_ptr->m_source;
|
||||
id = (cdev_id_t) m_ptr->IO_GRANT;
|
||||
id = m_ptr->CDEV_ID;
|
||||
|
||||
return cdp->cdr_cancel(minor, endpt, id);
|
||||
}
|
||||
|
@ -405,8 +410,8 @@ static int do_select(struct chardriver *cdp, message *m_ptr)
|
|||
return EBADF;
|
||||
|
||||
/* Call the select hook. */
|
||||
minor = m_ptr->DEV_MINOR;
|
||||
ops = m_ptr->DEV_SEL_OPS;
|
||||
minor = m_ptr->CDEV_MINOR;
|
||||
ops = m_ptr->CDEV_OPS;
|
||||
endpt = m_ptr->m_source;
|
||||
|
||||
return cdp->cdr_select(minor, ops, endpt);
|
||||
|
@ -473,24 +478,24 @@ void chardriver_process(struct chardriver *cdp, message *m_ptr, int ipc_status)
|
|||
/* We might get spurious requests if the driver has been restarted. Deny any
|
||||
* requests on devices that have not previously been opened.
|
||||
*/
|
||||
if (IS_DEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->DEVICE)) {
|
||||
if (IS_CDEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->CDEV_MINOR)) {
|
||||
/* Ignore spurious requests for unopened devices. */
|
||||
if (m_ptr->m_type != DEV_OPEN)
|
||||
if (m_ptr->m_type != CDEV_OPEN)
|
||||
return; /* do not send a reply */
|
||||
|
||||
/* Mark the device as opened otherwise. */
|
||||
set_open_dev(m_ptr->DEVICE);
|
||||
set_open_dev(m_ptr->CDEV_MINOR);
|
||||
}
|
||||
|
||||
/* Call the appropriate function(s) for this request. */
|
||||
switch (m_ptr->m_type) {
|
||||
case DEV_OPEN: r = do_open(cdp, m_ptr); break;
|
||||
case DEV_CLOSE: r = do_close(cdp, m_ptr); break;
|
||||
case DEV_READ_S: r = do_transfer(cdp, m_ptr, FALSE); break;
|
||||
case DEV_WRITE_S: r = do_transfer(cdp, m_ptr, TRUE); break;
|
||||
case DEV_IOCTL_S: r = do_ioctl(cdp, m_ptr); break;
|
||||
case CANCEL: r = do_cancel(cdp, m_ptr); break;
|
||||
case DEV_SELECT: r = do_select(cdp, m_ptr); break;
|
||||
case CDEV_OPEN: r = do_open(cdp, m_ptr); break;
|
||||
case CDEV_CLOSE: r = do_close(cdp, m_ptr); break;
|
||||
case CDEV_READ: r = do_transfer(cdp, m_ptr, FALSE); break;
|
||||
case CDEV_WRITE: r = do_transfer(cdp, m_ptr, TRUE); break;
|
||||
case CDEV_IOCTL: r = do_ioctl(cdp, m_ptr); break;
|
||||
case CDEV_CANCEL: r = do_cancel(cdp, m_ptr); break;
|
||||
case CDEV_SELECT: r = do_select(cdp, m_ptr); break;
|
||||
default:
|
||||
if (cdp->cdr_other)
|
||||
cdp->cdr_other(m_ptr, ipc_status);
|
||||
|
|
|
@ -261,7 +261,7 @@ struct socket * get_unused_sock(void)
|
|||
|
||||
static int socket_request_socket(struct socket * sock, struct sock_req * req)
|
||||
{
|
||||
int r, blocking = req->flags & FLG_OP_NONBLOCK ? 0 : 1;
|
||||
int r, blocking = (req->flags & CDEV_NONBLOCK) ? 0 : 1;
|
||||
|
||||
switch (req->type) {
|
||||
case SOCK_REQ_READ:
|
||||
|
@ -292,7 +292,12 @@ static int socket_request_socket(struct socket * sock, struct sock_req * req)
|
|||
static int netsock_open(devminor_t minor, int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
return socket_open(minor);
|
||||
int r;
|
||||
|
||||
if ((r = socket_open(minor)) < 0)
|
||||
return r;
|
||||
|
||||
return CDEV_CLONED | r;
|
||||
}
|
||||
|
||||
static int netsock_close(devminor_t minor)
|
||||
|
@ -505,26 +510,26 @@ int generic_op_select(struct socket * sock, unsigned int sel)
|
|||
|
||||
/* in this case any operation would block, no error */
|
||||
if (sock->flags & SOCK_FLG_OP_PENDING) {
|
||||
if (sel & SEL_NOTIFY) {
|
||||
if (sel & SEL_RD)
|
||||
if (sel & CDEV_NOTIFY) {
|
||||
if (sel & CDEV_OP_RD)
|
||||
sock->flags |= SOCK_FLG_SEL_READ;
|
||||
if (sel & SEL_WR)
|
||||
if (sel & CDEV_OP_WR)
|
||||
sock->flags |= SOCK_FLG_SEL_WRITE;
|
||||
/* FIXME we do not monitor error */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel & SEL_RD) {
|
||||
if (sel & CDEV_OP_RD) {
|
||||
if (sock->recv_head)
|
||||
retsel |= SEL_RD;
|
||||
else if (sel & SEL_NOTIFY)
|
||||
retsel |= CDEV_OP_RD;
|
||||
else if (sel & CDEV_NOTIFY)
|
||||
sock->flags |= SOCK_FLG_SEL_READ;
|
||||
}
|
||||
/* FIXME generic packet socket never blocks on write */
|
||||
if (sel & SEL_WR)
|
||||
retsel |= SEL_WR;
|
||||
/* FIXME SEL_ERR is ignored, we do not generate exceptions */
|
||||
if (sel & CDEV_OP_WR)
|
||||
retsel |= CDEV_OP_WR;
|
||||
/* FIXME CDEV_OP_ERR is ignored, we do not generate exceptions */
|
||||
|
||||
return retsel;
|
||||
}
|
||||
|
@ -545,7 +550,7 @@ int generic_op_select_reply(struct socket * sock)
|
|||
}
|
||||
|
||||
if (sock->flags & SOCK_FLG_SEL_READ && sock->recv_head)
|
||||
sel |= SEL_RD;
|
||||
sel |= CDEV_OP_RD;
|
||||
|
||||
if (sel)
|
||||
sock->flags &= ~(SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_READ |
|
||||
|
|
|
@ -146,7 +146,7 @@ static int sr_open(devminor_t minor, int UNUSED(access),
|
|||
return fd;
|
||||
}
|
||||
sr_fd->srf_fd= fd;
|
||||
return i; /* cloned! */
|
||||
return CDEV_CLONED | i;
|
||||
}
|
||||
|
||||
static int sr_close(devminor_t minor)
|
||||
|
@ -214,7 +214,7 @@ static int sr_rwio(sr_req_t *req)
|
|||
assert(sr_fd->srf_flags & susp_flag);
|
||||
assert(*q_head_ptr);
|
||||
|
||||
if (m->mq_req.srr_flags & FLG_OP_NONBLOCK) {
|
||||
if (m->mq_req.srr_flags & CDEV_NONBLOCK) {
|
||||
mq_free(m);
|
||||
return EAGAIN;
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ static int sr_rwio(sr_req_t *req)
|
|||
(printf("r= %d\n", r), 0));
|
||||
if (r == SUSPEND) {
|
||||
sr_fd->srf_flags |= susp_flag;
|
||||
if (m->mq_req.srr_flags & FLG_OP_NONBLOCK) {
|
||||
if (m->mq_req.srr_flags & CDEV_NONBLOCK) {
|
||||
r= sr_cancel(m->mq_req.srr_minor, m->mq_req.srr_endpt,
|
||||
m->mq_req.srr_id);
|
||||
assert(r == EDONTREPLY); /* head of the queue */
|
||||
|
@ -442,19 +442,19 @@ static int sr_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
|||
sr_fd->srf_select_proc= endpt;
|
||||
|
||||
i_ops= 0;
|
||||
if (ops & SEL_RD) i_ops |= SR_SELECT_READ;
|
||||
if (ops & SEL_WR) i_ops |= SR_SELECT_WRITE;
|
||||
if (ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION;
|
||||
if (!(ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
|
||||
if (ops & CDEV_OP_RD) i_ops |= SR_SELECT_READ;
|
||||
if (ops & CDEV_OP_WR) i_ops |= SR_SELECT_WRITE;
|
||||
if (ops & CDEV_OP_ERR) i_ops |= SR_SELECT_EXCEPTION;
|
||||
if (!(ops & CDEV_NOTIFY)) i_ops |= SR_SELECT_POLL;
|
||||
|
||||
r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
|
||||
if (r < 0) {
|
||||
m_ops= r;
|
||||
} else {
|
||||
m_ops= 0;
|
||||
if (r & SR_SELECT_READ) m_ops |= SEL_RD;
|
||||
if (r & SR_SELECT_WRITE) m_ops |= SEL_WR;
|
||||
if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
|
||||
if (r & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
|
||||
if (r & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
|
||||
if (r & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
|
||||
}
|
||||
|
||||
return m_ops;
|
||||
|
@ -657,9 +657,9 @@ static void sr_select_res(int fd, unsigned ops)
|
|||
sr_fd= &sr_fd_table[fd];
|
||||
|
||||
m_ops= 0;
|
||||
if (ops & SR_SELECT_READ) m_ops |= SEL_RD;
|
||||
if (ops & SR_SELECT_WRITE) m_ops |= SEL_WR;
|
||||
if (ops & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
|
||||
if (ops & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
|
||||
if (ops & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
|
||||
if (ops & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
|
||||
|
||||
chardriver_reply_select(sr_fd->srf_select_proc, fd, m_ops);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@ static char * dmap_style(int dev_style)
|
|||
case STYLE_DEV: return "STYLE_DEV";
|
||||
case STYLE_TTY: return "STYLE_TTY";
|
||||
case STYLE_CTTY: return "STYLE_CTTY";
|
||||
case STYLE_CLONE: return "STYLE_CLONE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1082,22 +1082,22 @@ static int tcp_op_select(struct socket * sock, unsigned int sel)
|
|||
/* in this case any operation would block, no error */
|
||||
if (sock->flags & SOCK_FLG_OP_PENDING) {
|
||||
debug_tcp_print("SOCK_FLG_OP_PENDING");
|
||||
if (sel & SEL_NOTIFY) {
|
||||
if (sel & SEL_RD) {
|
||||
if (sel & CDEV_NOTIFY) {
|
||||
if (sel & CDEV_OP_RD) {
|
||||
sock->flags |= SOCK_FLG_SEL_READ;
|
||||
debug_tcp_print("monitor read");
|
||||
}
|
||||
if (sel & SEL_WR) {
|
||||
if (sel & CDEV_OP_WR) {
|
||||
sock->flags |= SOCK_FLG_SEL_WRITE;
|
||||
debug_tcp_print("monitor write");
|
||||
}
|
||||
if (sel & SEL_ERR)
|
||||
if (sel & CDEV_OP_ERR)
|
||||
sock->flags |= SOCK_FLG_SEL_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel & SEL_RD) {
|
||||
if (sel & CDEV_OP_RD) {
|
||||
/*
|
||||
* If recv_head is not NULL we can either read or accept a
|
||||
* connection which is the same for select()
|
||||
|
@ -1105,38 +1105,38 @@ static int tcp_op_select(struct socket * sock, unsigned int sel)
|
|||
if (sock->pcb) {
|
||||
if (sock->recv_head &&
|
||||
!(sock->flags & SOCK_FLG_OP_WRITING))
|
||||
retsel |= SEL_RD;
|
||||
retsel |= CDEV_OP_RD;
|
||||
else if (!(sock->flags & SOCK_FLG_OP_LISTENING) &&
|
||||
((struct tcp_pcb *) sock->pcb)->state != ESTABLISHED)
|
||||
retsel |= SEL_RD;
|
||||
else if (sel & SEL_NOTIFY) {
|
||||
retsel |= CDEV_OP_RD;
|
||||
else if (sel & CDEV_NOTIFY) {
|
||||
sock->flags |= SOCK_FLG_SEL_READ;
|
||||
debug_tcp_print("monitor read");
|
||||
}
|
||||
} else
|
||||
retsel |= SEL_RD; /* not connected read does not block */
|
||||
} else /* not connected read does not block */
|
||||
retsel |= CDEV_OP_RD;
|
||||
}
|
||||
if (sel & SEL_WR) {
|
||||
if (sel & CDEV_OP_WR) {
|
||||
if (sock->pcb) {
|
||||
if (((struct tcp_pcb *) sock->pcb)->state == ESTABLISHED)
|
||||
retsel |= SEL_WR;
|
||||
else if (sel & SEL_NOTIFY) {
|
||||
retsel |= CDEV_OP_WR;
|
||||
else if (sel & CDEV_NOTIFY) {
|
||||
sock->flags |= SOCK_FLG_SEL_WRITE;
|
||||
debug_tcp_print("monitor write");
|
||||
}
|
||||
} else
|
||||
retsel |= SEL_WR; /* not connected write does not block */
|
||||
} else /* not connected write does not block */
|
||||
retsel |= CDEV_OP_WR;
|
||||
}
|
||||
|
||||
if (retsel & SEL_RD) {
|
||||
if (retsel & CDEV_OP_RD) {
|
||||
debug_tcp_print("read won't block");
|
||||
}
|
||||
if (retsel & SEL_WR) {
|
||||
if (retsel & CDEV_OP_WR) {
|
||||
debug_tcp_print("write won't block");
|
||||
}
|
||||
|
||||
/* we only monitor if errors will happen in the future */
|
||||
if (sel & SEL_ERR && sel & SEL_NOTIFY)
|
||||
if (sel & CDEV_OP_ERR && sel & CDEV_NOTIFY)
|
||||
sock->flags |= SOCK_FLG_SEL_ERROR;
|
||||
|
||||
return retsel;
|
||||
|
@ -1160,7 +1160,7 @@ static int tcp_op_select_reply(struct socket * sock)
|
|||
(!(sock->flags & SOCK_FLG_OP_LISTENING) &&
|
||||
((struct tcp_pcb *) sock->pcb)->state !=
|
||||
ESTABLISHED)) {
|
||||
sel |= SEL_RD;
|
||||
sel |= CDEV_OP_RD;
|
||||
debug_tcp_print("read won't block");
|
||||
}
|
||||
}
|
||||
|
@ -1169,7 +1169,7 @@ static int tcp_op_select_reply(struct socket * sock)
|
|||
(sock->pcb == NULL ||
|
||||
((struct tcp_pcb *) sock->pcb)->state ==
|
||||
ESTABLISHED)) {
|
||||
sel |= SEL_WR;
|
||||
sel |= CDEV_OP_WR;
|
||||
debug_tcp_print("write won't block");
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,9 @@
|
|||
*
|
||||
* Overview
|
||||
*
|
||||
* The interface to unix domain sockets is similar to the
|
||||
* the interface to network sockets. There is a character
|
||||
* device (/dev/uds) that uses STYLE_CLONE and this server
|
||||
* is a 'driver' for that device.
|
||||
* The interface to unix domain sockets is similar to the interface to network
|
||||
* sockets. There is a character device (/dev/uds) and this server is a
|
||||
* 'driver' for that device.
|
||||
*/
|
||||
|
||||
#define DEBUG 0
|
||||
|
@ -190,7 +189,7 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
|
|||
/* Process the response */
|
||||
uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR;
|
||||
|
||||
return minor; /* cloned! */
|
||||
return CDEV_CLONED | minor;
|
||||
}
|
||||
|
||||
static int uds_close(devminor_t minor)
|
||||
|
@ -271,40 +270,40 @@ static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
watch = (ops & SEL_NOTIFY);
|
||||
ops &= (SEL_RD | SEL_WR | SEL_ERR);
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = 0;
|
||||
|
||||
/* check if there is data available to read */
|
||||
if (ops & SEL_RD) {
|
||||
if (ops & CDEV_OP_RD) {
|
||||
bytes = uds_perform_read(minor, NONE, GRANT_INVALID, 1, 1);
|
||||
if (bytes > 0) {
|
||||
/* there is data in the pipe for us to read */
|
||||
ready_ops |= SEL_RD;
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
} else if (uds_fd_table[minor].listening == 1) {
|
||||
/* check for pending connections */
|
||||
for (i = 0; i < uds_fd_table[minor].backlog_size; i++)
|
||||
{
|
||||
if (uds_fd_table[minor].backlog[i] != -1) {
|
||||
ready_ops |= SEL_RD;
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (bytes != SUSPEND) {
|
||||
ready_ops |= SEL_RD;
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we can write without blocking */
|
||||
if (ops & SEL_WR) {
|
||||
if (ops & CDEV_OP_WR) {
|
||||
bytes = uds_perform_write(minor, NONE, GRANT_INVALID, PIPE_BUF,
|
||||
1);
|
||||
if (bytes != 0 && bytes != SUSPEND) {
|
||||
/* There is room to write or there is an error
|
||||
* condition.
|
||||
*/
|
||||
ready_ops |= SEL_WR;
|
||||
ready_ops |= CDEV_OP_WR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,12 +438,12 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
|
|||
* peer to minor); if the peer wants to know about write being possible
|
||||
* and it doesn't know about it already, then let the peer know.
|
||||
*/
|
||||
if (peer != -1 && (uds_fd_table[peer].sel_ops & SEL_WR) &&
|
||||
if (peer != -1 && (uds_fd_table[peer].sel_ops & CDEV_OP_WR) &&
|
||||
(uds_fd_table[minor].size+uds_fd_table[minor].pos + 1 < PIPE_BUF)){
|
||||
/* a write on peer is possible now */
|
||||
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
|
||||
SEL_WR);
|
||||
uds_fd_table[peer].sel_ops &= ~SEL_WR;
|
||||
CDEV_OP_WR);
|
||||
uds_fd_table[peer].sel_ops &= ~CDEV_OP_WR;
|
||||
}
|
||||
|
||||
return fs_m_out.RES_NBYTES; /* return number of bytes read */
|
||||
|
@ -604,11 +603,12 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
|
|||
* data ready to read and it doesn't know about it already, then let
|
||||
* the peer know we have data for it.
|
||||
*/
|
||||
if ((uds_fd_table[peer].sel_ops & SEL_RD) && fs_m_out.RES_NBYTES > 0) {
|
||||
if ((uds_fd_table[peer].sel_ops & CDEV_OP_RD) &&
|
||||
fs_m_out.RES_NBYTES > 0) {
|
||||
/* a read on peer is possible now */
|
||||
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
|
||||
SEL_RD);
|
||||
uds_fd_table[peer].sel_ops &= ~SEL_RD;
|
||||
CDEV_OP_RD);
|
||||
uds_fd_table[peer].sel_ops &= ~CDEV_OP_RD;
|
||||
}
|
||||
|
||||
return fs_m_out.RES_NBYTES; /* return number of bytes written */
|
||||
|
@ -644,7 +644,7 @@ static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
|||
uds_fd_table[minor].susp_id = id;
|
||||
|
||||
/* If the call wasn't supposed to block, cancel immediately. */
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
uds_cancel(minor, endpt, id);
|
||||
|
||||
rc = EAGAIN;
|
||||
|
@ -684,7 +684,7 @@ static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
|||
uds_fd_table[minor].susp_id = id;
|
||||
|
||||
/* If the call wasn't supposed to block, cancel immediately. */
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
uds_cancel(minor, endpt, id);
|
||||
|
||||
rc = EAGAIN;
|
||||
|
@ -730,7 +730,7 @@ static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
|||
uds_fd_table[minor].susp_id = id;
|
||||
|
||||
/* If the call wasn't supposed to block, cancel immediately. */
|
||||
if (flags & FLG_OP_NONBLOCK) {
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
uds_cancel(minor, endpt, id);
|
||||
|
||||
rc = EAGAIN;
|
||||
|
|
|
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
|||
get_work(&pfs_m_in, &ipc_status);
|
||||
|
||||
/* If this is a UDS device request, process it and continue. */
|
||||
if (IS_DEV_RQ(pfs_m_in.m_type)) {
|
||||
if (IS_CDEV_RQ(pfs_m_in.m_type)) {
|
||||
uds_request(&pfs_m_in, ipc_status);
|
||||
|
||||
continue;
|
||||
|
|
|
@ -464,7 +464,7 @@ static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
|
|||
}
|
||||
|
||||
/* see if the server is blocked on select() */
|
||||
if (uds_fd_table[i].sel_ops & SEL_RD) {
|
||||
if (uds_fd_table[i].sel_ops & CDEV_OP_RD) {
|
||||
/* if the server wants to know about
|
||||
* data ready to read and it doesn't
|
||||
* doesn't know about it already, then
|
||||
|
@ -473,9 +473,9 @@ static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
|
|||
*/
|
||||
chardriver_reply_select(
|
||||
uds_fd_table[i].sel_endpt, i,
|
||||
SEL_RD);
|
||||
CDEV_OP_RD);
|
||||
|
||||
uds_fd_table[i].sel_ops &= ~SEL_RD;
|
||||
uds_fd_table[i].sel_ops &= ~CDEV_OP_RD;
|
||||
}
|
||||
|
||||
/* we found our server */
|
||||
|
|
|
@ -179,7 +179,7 @@ struct uds_fd {
|
|||
*/
|
||||
endpoint_t sel_endpt;
|
||||
|
||||
/* Options (SEL_RD, SEL_WR, SEL_ERR) that are requested. */
|
||||
/* Options (CDEV_OP_RD,WR,ERR) that are requested. */
|
||||
unsigned int sel_ops;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ struct boot_image_dev boot_image_dev_table[] = {
|
|||
{ TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY },
|
||||
{ MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV },
|
||||
{ LOG_PROC_NR, SRV_DF, LOG_MAJOR, STYLE_DEV, STYLE_NDEV },
|
||||
{ PFS_PROC_NR, SRV_DF, UDS_MAJOR, STYLE_CLONE,STYLE_NDEV },
|
||||
{ PFS_PROC_NR, SRV_DF, UDS_MAJOR, STYLE_DEV, STYLE_NDEV },
|
||||
{ DEFAULT_BOOT_NR, SRV_DF, 0, STYLE_NDEV, STYLE_NDEV } /* default
|
||||
* entry
|
||||
*/
|
||||
|
|
|
@ -93,7 +93,7 @@ int drv_sendrec(endpoint_t drv_e, message *reqmp)
|
|||
panic("driver endpoint %d invalid", drv_e);
|
||||
|
||||
lock_dmap(dp);
|
||||
if (dp->dmap_servicing != NONE)
|
||||
if (dp->dmap_servicing != INVALID_THREAD)
|
||||
panic("driver locking inconsistency");
|
||||
dp->dmap_servicing = self->w_tid;
|
||||
self->w_task = drv_e;
|
||||
|
@ -108,7 +108,7 @@ int drv_sendrec(endpoint_t drv_e, message *reqmp)
|
|||
util_stacktrace();
|
||||
}
|
||||
|
||||
dp->dmap_servicing = NONE;
|
||||
dp->dmap_servicing = INVALID_THREAD;
|
||||
self->w_task = NONE;
|
||||
self->w_drv_sendrec = NULL;
|
||||
unlock_dmap(dp);
|
||||
|
|
|
@ -26,14 +26,7 @@
|
|||
/* test if the process is blocked on something */
|
||||
#define fp_is_blocked(fp) ((fp)->fp_blocked_on != FP_BLOCKED_ON_NONE)
|
||||
|
||||
/* test if reply is a driver reply */
|
||||
#define IS_DRV_REPLY(x) (IS_DEV_RS(x) || IS_BDEV_RS(x))
|
||||
#define DUP_MASK 0100 /* mask to distinguish dup2 from dup */
|
||||
|
||||
#define LOOK_UP 0 /* tells search_dir to lookup string */
|
||||
#define ENTER 1 /* tells search_dir to make dir entry */
|
||||
#define DELETE 2 /* tells search_dir to delete entry */
|
||||
#define IS_EMPTY 3 /* tells search_dir to ret. OK or ENOTEMPTY */
|
||||
#define INVALID_THREAD ((thread_t) -1) /* known-invalid thread ID */
|
||||
|
||||
#define SYMLOOP 16
|
||||
|
||||
|
@ -43,4 +36,10 @@
|
|||
*/
|
||||
#define FSTYPE_MAX VFS_NAMELEN /* maximum file system type size */
|
||||
|
||||
/* possible select() operation types; read, write, errors */
|
||||
#define SEL_RD CDEV_OP_RD
|
||||
#define SEL_WR CDEV_OP_WR
|
||||
#define SEL_ERR CDEV_OP_ERR
|
||||
#define SEL_NOTIFY CDEV_NOTIFY /* not a real select operation */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,24 +2,25 @@
|
|||
* Special character files also require I/O. The routines for these are here.
|
||||
*
|
||||
* The entry points in this file are:
|
||||
* dev_open: open a character device
|
||||
* dev_close: close a character device
|
||||
* cdev_reply: process the result of a character driver request
|
||||
* bdev_open: open a block device
|
||||
* bdev_close: close a block device
|
||||
* bdev_reply: process the result of a block driver request
|
||||
* dev_io: FS does a read or write on a device
|
||||
* gen_opcl: generic call to a character driver to perform an open/close
|
||||
* gen_io: generic call to a character driver to initiate I/O
|
||||
* no_dev: open/close processing for devices that don't exist
|
||||
* no_dev_io: i/o processing for devices that don't exist
|
||||
* tty_opcl: perform tty-specific processing for open/close
|
||||
* ctty_opcl: perform controlling-tty-specific processing for open/close
|
||||
* ctty_io: perform controlling-tty-specific processing for I/O
|
||||
* pm_setsid: perform VFS's side of setsid system call
|
||||
* do_ioctl: perform the IOCTL system call
|
||||
* dev_select: initiate a select call on a device
|
||||
* dev_cancel: cancel an I/O request, blocking until it has been cancelled
|
||||
* cdev_open: open a character device
|
||||
* cdev_close: close a character device
|
||||
* cdev_io: initiate a read, write, or ioctl to a character device
|
||||
* cdev_select: initiate a select call on a device
|
||||
* cdev_cancel: cancel an I/O request, blocking until it has been cancelled
|
||||
* cdev_reply: process the result of a character driver request
|
||||
* bdev_open: open a block device
|
||||
* bdev_close: close a block device
|
||||
* bdev_reply: process the result of a block driver request
|
||||
* bdev_up: a block driver has been mapped in
|
||||
* gen_opcl: generic call to a character driver to perform an open/close
|
||||
* gen_io: generic call to a character driver to initiate I/O
|
||||
* no_dev: open/close processing for devices that don't exist
|
||||
* no_dev_io: i/o processing for devices that don't exist
|
||||
* tty_opcl: perform tty-specific processing for open/close
|
||||
* ctty_opcl: perform controlling-tty-specific processing for open/close
|
||||
* ctty_io: perform controlling-tty-specific processing for I/O
|
||||
* pm_setsid: perform VFS's side of setsid system call
|
||||
* do_ioctl: perform the IOCTL system call
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
|
@ -44,15 +45,10 @@ static int block_io(endpoint_t driver_e, message *mess_ptr);
|
|||
static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
||||
void *buf, unsigned long size);
|
||||
|
||||
static int dummyproc;
|
||||
|
||||
/*===========================================================================*
|
||||
* dev_open *
|
||||
* cdev_open *
|
||||
*===========================================================================*/
|
||||
int dev_open(
|
||||
dev_t dev, /* device to open */
|
||||
int flags /* mode bits and flags */
|
||||
)
|
||||
int cdev_open(dev_t dev, int flags)
|
||||
{
|
||||
/* Open a character device. */
|
||||
devmajor_t major_dev;
|
||||
|
@ -65,17 +61,15 @@ int dev_open(
|
|||
major_dev = major(dev);
|
||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
||||
if (dmap[major_dev].dmap_driver == NONE) return(ENXIO);
|
||||
r = (*dmap[major_dev].dmap_opcl)(DEV_OPEN, dev, fp->fp_endpoint, flags);
|
||||
r = (*dmap[major_dev].dmap_opcl)(CDEV_OPEN, dev, fp->fp_endpoint, flags);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* dev_close *
|
||||
* cdev_close *
|
||||
*===========================================================================*/
|
||||
int dev_close(
|
||||
dev_t dev /* device to close */
|
||||
)
|
||||
int cdev_close(dev_t dev)
|
||||
{
|
||||
/* Close a character device. */
|
||||
devmajor_t major_dev;
|
||||
|
@ -85,7 +79,7 @@ int dev_close(
|
|||
major_dev = major(dev);
|
||||
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
|
||||
if (dmap[major_dev].dmap_driver == NONE) return(ENXIO);
|
||||
r = (*dmap[major_dev].dmap_opcl)(DEV_CLOSE, dev, fp->fp_endpoint, 0);
|
||||
r = (*dmap[major_dev].dmap_opcl)(CDEV_CLOSE, dev, fp->fp_endpoint, 0);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
@ -204,30 +198,6 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, unsigned long req,
|
|||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* find_suspended_ep *
|
||||
*===========================================================================*/
|
||||
static endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
|
||||
{
|
||||
/* A process is suspended on a driver for which VFS issued a grant. Find out
|
||||
* which process it was.
|
||||
*/
|
||||
struct fproc *rfp;
|
||||
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
||||
if(rfp->fp_pid == PID_FREE)
|
||||
continue;
|
||||
|
||||
if (rfp->fp_task == driver && rfp->fp_grant == g) {
|
||||
assert(!fp_is_blocked(rfp) ||
|
||||
rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER);
|
||||
return(rfp->fp_endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
return(NONE);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* make_grant *
|
||||
*===========================================================================*/
|
||||
|
@ -240,13 +210,13 @@ static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
|||
size_t size;
|
||||
|
||||
switch (op) {
|
||||
case DEV_READ_S:
|
||||
case DEV_WRITE_S:
|
||||
case CDEV_READ:
|
||||
case CDEV_WRITE:
|
||||
gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf,
|
||||
(size_t) bytes, op == DEV_READ_S ? CPF_WRITE : CPF_READ);
|
||||
(size_t) bytes, op == CDEV_READ ? CPF_WRITE : CPF_READ);
|
||||
break;
|
||||
|
||||
case DEV_IOCTL_S:
|
||||
case CDEV_IOCTL:
|
||||
case BDEV_IOCTL:
|
||||
/* For IOCTLs, the bytes parameter contains the IOCTL request.
|
||||
* This request encodes the requested access method and buffer size.
|
||||
|
@ -259,8 +229,9 @@ static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
|||
else
|
||||
size = _MINIX_IOCTL_SIZE(bytes);
|
||||
|
||||
/* Grant access to the buffer even if no I/O happens with the ioctl, in
|
||||
* order to disambiguate requests with DEV_IOCTL_S.
|
||||
/* Grant access to the buffer even if no I/O happens with the ioctl,
|
||||
* although now that we no longer identify responses based on grants,
|
||||
* this is not strictly necessary.
|
||||
*/
|
||||
gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, size, access);
|
||||
break;
|
||||
|
@ -277,27 +248,27 @@ static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* dev_io *
|
||||
* cdev_io *
|
||||
*===========================================================================*/
|
||||
int dev_io(
|
||||
int op, /* DEV_READ_S, DEV_WRITE_S, or DEV_IOCTL_S */
|
||||
int cdev_io(
|
||||
int op, /* CDEV_READ, CDEV_WRITE, or CDEV_IOCTL */
|
||||
dev_t dev, /* major-minor device number */
|
||||
endpoint_t proc_e, /* in whose address space is buf? */
|
||||
void *buf, /* virtual address of the buffer */
|
||||
off_t pos, /* byte position */
|
||||
size_t bytes, /* how many bytes to transfer */
|
||||
unsigned long bytes, /* how many bytes to transfer, or request */
|
||||
int flags /* special flags, like O_NONBLOCK */
|
||||
)
|
||||
{
|
||||
/* Initiate a read, write, or ioctl to a device. */
|
||||
/* Initiate a read, write, or ioctl to a character device. */
|
||||
struct dmap *dp;
|
||||
message dev_mess;
|
||||
cp_grant_id_t gid;
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
int r;
|
||||
int r, slot;
|
||||
|
||||
assert(op == DEV_READ_S || op == DEV_WRITE_S || op == DEV_IOCTL_S);
|
||||
assert(op == CDEV_READ || op == CDEV_WRITE || op == CDEV_IOCTL);
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
|
@ -307,7 +278,7 @@ int dev_io(
|
|||
/* See if driver is roughly valid. */
|
||||
if (dp->dmap_driver == NONE) return(ENXIO);
|
||||
|
||||
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
|
||||
if(isokendpt(dp->dmap_driver, &slot) != OK) {
|
||||
printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
|
||||
dp->dmap_driver);
|
||||
return(ENXIO);
|
||||
|
@ -318,21 +289,21 @@ int dev_io(
|
|||
|
||||
/* Set up the rest of the message that will be sent to the driver. */
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.DEVICE = minor_dev;
|
||||
if (op == DEV_IOCTL_S) {
|
||||
dev_mess.REQUEST = bytes;
|
||||
dev_mess.POSITION = proc_e;
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
if (op == CDEV_IOCTL) {
|
||||
dev_mess.CDEV_REQUEST = bytes;
|
||||
dev_mess.CDEV_USER = proc_e;
|
||||
} else {
|
||||
dev_mess.POSITION = ex64lo(pos);
|
||||
dev_mess.COUNT = bytes;
|
||||
dev_mess.CDEV_POS_LO = ex64lo(pos);
|
||||
dev_mess.CDEV_POS_HI = ex64hi(pos);
|
||||
dev_mess.CDEV_COUNT = (size_t) bytes;
|
||||
}
|
||||
dev_mess.HIGHPOS = ex64hi(pos);
|
||||
dev_mess.USER_ENDPT = VFS_PROC_NR;
|
||||
dev_mess.IO_GRANT = (void *) gid;
|
||||
dev_mess.FLAGS = 0;
|
||||
dev_mess.CDEV_ID = proc_e;
|
||||
dev_mess.CDEV_GRANT = gid;
|
||||
dev_mess.CDEV_FLAGS = 0;
|
||||
if (flags & O_NONBLOCK)
|
||||
dev_mess.FLAGS |= FLG_OP_NONBLOCK;
|
||||
dev_mess.CDEV_FLAGS |= CDEV_NONBLOCK;
|
||||
|
||||
/* Send the request to the driver. */
|
||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
@ -347,7 +318,6 @@ int dev_io(
|
|||
wait_for(dp->dmap_driver);
|
||||
assert(!GRANT_VALID(fp->fp_grant));
|
||||
fp->fp_grant = gid; /* revoke this when unsuspended. */
|
||||
fp->fp_ioproc = VFS_PROC_NR;
|
||||
|
||||
return SUSPEND;
|
||||
}
|
||||
|
@ -374,14 +344,14 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
|||
r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
|
||||
ALL_MODES | I_CHAR_SPECIAL, dev, &res);
|
||||
if (r != OK) {
|
||||
(void) gen_opcl(DEV_CLOSE, dev, proc_e, 0);
|
||||
(void) gen_opcl(CDEV_CLOSE, dev, proc_e, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Drop old node and use the new values */
|
||||
if ((vp = get_free_vnode()) == NULL) {
|
||||
req_putnode(PFS_PROC_NR, res.inode_nr, 1); /* is this right? */
|
||||
(void) gen_opcl(DEV_CLOSE, dev, proc_e, 0);
|
||||
(void) gen_opcl(CDEV_CLOSE, dev, proc_e, 0);
|
||||
return(err_code);
|
||||
}
|
||||
lock_vnode(vp, VNODE_OPCL);
|
||||
|
@ -409,7 +379,7 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor)
|
|||
* gen_opcl *
|
||||
*===========================================================================*/
|
||||
int gen_opcl(
|
||||
int op, /* operation, DEV_OPEN or DEV_CLOSE */
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t dev, /* device to open or close */
|
||||
endpoint_t proc_e, /* process to open/close for */
|
||||
int flags /* mode bits and flags */
|
||||
|
@ -417,10 +387,10 @@ int gen_opcl(
|
|||
{
|
||||
/* Called from the dmap struct on opens & closes of special files.*/
|
||||
devmajor_t major_dev;
|
||||
devminor_t minor_dev;
|
||||
devminor_t minor_dev, new_minor;
|
||||
struct dmap *dp;
|
||||
message dev_mess;
|
||||
int r;
|
||||
int r, r2;
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
|
@ -435,9 +405,15 @@ int gen_opcl(
|
|||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.DEVICE = minor_dev;
|
||||
dev_mess.USER_ENDPT = proc_e;
|
||||
dev_mess.COUNT = flags;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_ID = proc_e;
|
||||
if (op == CDEV_OPEN) {
|
||||
dev_mess.CDEV_USER = proc_e;
|
||||
dev_mess.CDEV_ACCESS = 0;
|
||||
if (flags & R_BIT) dev_mess.CDEV_ACCESS |= CDEV_R_BIT;
|
||||
if (flags & W_BIT) dev_mess.CDEV_ACCESS |= CDEV_W_BIT;
|
||||
if (flags & O_NOCTTY) dev_mess.CDEV_ACCESS |= CDEV_NOCTTY;
|
||||
}
|
||||
|
||||
/* Call the task. */
|
||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
@ -454,15 +430,33 @@ int gen_opcl(
|
|||
self->w_task = NONE;
|
||||
self->w_drv_sendrec = NULL;
|
||||
|
||||
r = dev_mess.CDEV_STATUS;
|
||||
|
||||
/* Some devices need special processing upon open. Such a device is "cloned",
|
||||
* i.e. on a succesful open it is replaced by a new device with a new unique
|
||||
* minor device number. This new device number identifies a new object (such
|
||||
* as a new network connection) that has been allocated within a task.
|
||||
*/
|
||||
if (op == CDEV_OPEN && r >= 0) {
|
||||
if (r & CDEV_CLONED) {
|
||||
new_minor = r & ~(CDEV_CLONED | CDEV_CTTY);
|
||||
r &= CDEV_CTTY;
|
||||
if ((r2 = cdev_clone(dev, proc_e, new_minor)) < 0)
|
||||
r = r2;
|
||||
} else
|
||||
r &= CDEV_CTTY;
|
||||
/* Upon success, we now return either OK or CDEV_CTTY. */
|
||||
}
|
||||
|
||||
/* Return the result from the driver. */
|
||||
return(dev_mess.REP_STATUS);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* tty_opcl *
|
||||
*===========================================================================*/
|
||||
int tty_opcl(
|
||||
int op, /* operation, DEV_OPEN or DEV_CLOSE */
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t dev, /* device to open or close */
|
||||
endpoint_t proc_e, /* process to open/close for */
|
||||
int flags /* mode bits and flags */
|
||||
|
@ -490,7 +484,7 @@ int tty_opcl(
|
|||
r = gen_opcl(op, dev, proc_e, flags);
|
||||
|
||||
/* Did this call make the tty the controlling tty? */
|
||||
if (r == 1) {
|
||||
if (r >= 0 && (r & CDEV_CTTY)) {
|
||||
fp->fp_tty = dev;
|
||||
r = OK;
|
||||
}
|
||||
|
@ -503,7 +497,7 @@ int tty_opcl(
|
|||
* ctty_opcl *
|
||||
*===========================================================================*/
|
||||
int ctty_opcl(
|
||||
int op, /* operation, DEV_OPEN or DEV_CLOSE */
|
||||
int op, /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t UNUSED(dev), /* device to open or close */
|
||||
endpoint_t UNUSED(proc_e), /* process to open/close for */
|
||||
int UNUSED(flags) /* mode bits and flags */
|
||||
|
@ -569,8 +563,8 @@ int do_ioctl(message *UNUSED(m_out))
|
|||
if (S_ISBLK(vp->v_mode))
|
||||
r = bdev_ioctl(dev, who_e, ioctlrequest, argx);
|
||||
else
|
||||
r = dev_io(DEV_IOCTL_S, dev, who_e, argx, 0,
|
||||
ioctlrequest, f->filp_flags);
|
||||
r = cdev_io(CDEV_IOCTL, dev, who_e, argx, 0, ioctlrequest,
|
||||
f->filp_flags);
|
||||
}
|
||||
|
||||
unlock_filp(f);
|
||||
|
@ -580,9 +574,9 @@ int do_ioctl(message *UNUSED(m_out))
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* dev_select *
|
||||
* cdev_select *
|
||||
*===========================================================================*/
|
||||
int dev_select(dev_t dev, int ops)
|
||||
int cdev_select(dev_t dev, int ops)
|
||||
{
|
||||
/* Initiate a select call on a device. Return OK iff the request was sent. */
|
||||
devmajor_t major_dev;
|
||||
|
@ -598,9 +592,9 @@ int dev_select(dev_t dev, int ops)
|
|||
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = DEV_SELECT;
|
||||
dev_mess.DEV_MINOR = minor_dev;
|
||||
dev_mess.DEV_SEL_OPS = ops;
|
||||
dev_mess.m_type = CDEV_SELECT;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_OPS = ops;
|
||||
|
||||
/* Call the task. */
|
||||
return (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
@ -608,9 +602,9 @@ int dev_select(dev_t dev, int ops)
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* dev_cancel *
|
||||
* cdev_cancel *
|
||||
*===========================================================================*/
|
||||
int dev_cancel(dev_t dev)
|
||||
int cdev_cancel(dev_t dev)
|
||||
{
|
||||
/* Cancel an I/O request, blocking until it has been cancelled. */
|
||||
devmajor_t major_dev;
|
||||
|
@ -625,14 +619,9 @@ int dev_cancel(dev_t dev)
|
|||
|
||||
memset(&dev_mess, 0, sizeof(dev_mess));
|
||||
|
||||
dev_mess.m_type = CANCEL;
|
||||
dev_mess.DEVICE = minor_dev;
|
||||
dev_mess.USER_ENDPT = fp->fp_ioproc;
|
||||
dev_mess.IO_GRANT = (char *) fp->fp_grant;
|
||||
|
||||
/* Tell driver R or W. Mode is from current call, not open. */
|
||||
/* FIXME: ioctls also pass through here! */
|
||||
dev_mess.COUNT = fp->fp_block_callnr == READ ? R_BIT : W_BIT;
|
||||
dev_mess.m_type = CDEV_CANCEL;
|
||||
dev_mess.CDEV_MINOR = minor_dev;
|
||||
dev_mess.CDEV_ID = fp->fp_endpoint;
|
||||
|
||||
r = (*dp->dmap_io)(fp->fp_task, &dev_mess);
|
||||
if (r != OK) return r; /* ctty_io returned an error? should be impossible */
|
||||
|
@ -653,7 +642,7 @@ int dev_cancel(dev_t dev)
|
|||
fp->fp_grant = GRANT_INVALID;
|
||||
}
|
||||
|
||||
r = dev_mess.REP_STATUS;
|
||||
r = dev_mess.CDEV_STATUS;
|
||||
return (r == EAGAIN) ? EINTR : r;
|
||||
}
|
||||
|
||||
|
@ -721,8 +710,6 @@ int gen_io(endpoint_t drv_e, message *mess_ptr)
|
|||
|
||||
if (r != OK) panic("VFS: asynsend in gen_io failed: %d", r);
|
||||
|
||||
/* Fake a SUSPEND */
|
||||
mess_ptr->REP_STATUS = SUSPEND;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
@ -740,6 +727,7 @@ int ctty_io(
|
|||
* major/minor pair for /dev/tty itself.
|
||||
*/
|
||||
struct dmap *dp;
|
||||
int slot;
|
||||
|
||||
if (fp->fp_tty == 0) {
|
||||
/* No controlling tty present anymore, return an I/O error. */
|
||||
|
@ -747,14 +735,14 @@ int ctty_io(
|
|||
} else {
|
||||
/* Substitute the controlling terminal device. */
|
||||
dp = &dmap[major(fp->fp_tty)];
|
||||
mess_ptr->DEVICE = minor(fp->fp_tty);
|
||||
mess_ptr->CDEV_MINOR = minor(fp->fp_tty);
|
||||
|
||||
if (dp->dmap_driver == NONE) {
|
||||
printf("FS: ctty_io: no driver for dev\n");
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
if (isokendpt(dp->dmap_driver, &dummyproc) != OK) {
|
||||
if (isokendpt(dp->dmap_driver, &slot) != OK) {
|
||||
printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
|
||||
return(EIO);
|
||||
}
|
||||
|
@ -768,7 +756,7 @@ int ctty_io(
|
|||
* no_dev *
|
||||
*===========================================================================*/
|
||||
int no_dev(
|
||||
int UNUSED(op), /* operation, DEV_OPEN or DEV_CLOSE */
|
||||
int UNUSED(op), /* operation, CDEV_OPEN or CDEV_CLOSE */
|
||||
dev_t UNUSED(dev), /* device to open or close */
|
||||
endpoint_t UNUSED(proc), /* process to open/close for */
|
||||
int UNUSED(flags) /* mode bits and flags */
|
||||
|
@ -788,35 +776,6 @@ int no_dev_io(endpoint_t UNUSED(proc), message *UNUSED(m))
|
|||
return(EIO);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* clone_opcl *
|
||||
*===========================================================================*/
|
||||
int clone_opcl(
|
||||
int op, /* operation, DEV_OPEN or DEV_CLOSE */
|
||||
dev_t dev, /* device to open or close */
|
||||
endpoint_t proc_e, /* process to open/close for */
|
||||
int flags /* mode bits and flags */
|
||||
)
|
||||
{
|
||||
/* Some devices need special processing upon open. Such a device is "cloned",
|
||||
* i.e. on a succesful open it is replaced by a new device with a new unique
|
||||
* minor device number. This new device number identifies a new object (such
|
||||
* as a new network connection) that has been allocated within a task.
|
||||
*/
|
||||
int r;
|
||||
|
||||
r = gen_opcl(op, dev, proc_e, flags);
|
||||
|
||||
if (op == DEV_OPEN && r >= 0) {
|
||||
if (r != minor(dev))
|
||||
r = cdev_clone(dev, proc_e, r);
|
||||
else
|
||||
r = OK;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* bdev_up *
|
||||
|
@ -881,74 +840,46 @@ void bdev_up(devmajor_t maj)
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* opcl_reply *
|
||||
* cdev_generic_reply *
|
||||
*===========================================================================*/
|
||||
static void opcl_reply(message *m_ptr)
|
||||
static void cdev_generic_reply(message *m_ptr)
|
||||
{
|
||||
/* A character driver has replied to an open or close request. This function
|
||||
* MUST NOT block its calling thread.
|
||||
/* A character driver has results for an open, close, read, write, or ioctl
|
||||
* call (i.e., everything except select). There may be a thread waiting for
|
||||
* these results as part of an ongoing open, close, or (for read/write/ioctl)
|
||||
* cancel call. If so, wake up that thread; if not, send a reply to the
|
||||
* requesting process. This function MUST NOT block its calling thread.
|
||||
*/
|
||||
struct fproc *rfp;
|
||||
struct worker_thread *wp;
|
||||
endpoint_t proc_e;
|
||||
int slot;
|
||||
|
||||
proc_e = m_ptr->REP_ENDPT;
|
||||
if (isokendpt(proc_e, &slot) != OK) return;
|
||||
rfp = &fproc[slot];
|
||||
wp = rfp->fp_worker;
|
||||
if (wp == NULL || wp->w_task != who_e) {
|
||||
printf("VFS: no worker thread waiting for a reply from %d\n", who_e);
|
||||
proc_e = m_ptr->CDEV_ID;
|
||||
|
||||
if (m_ptr->CDEV_STATUS == SUSPEND) {
|
||||
printf("VFS: got SUSPEND from %d, not reviving\n", m_ptr->m_source);
|
||||
return;
|
||||
}
|
||||
*wp->w_drv_sendrec = *m_ptr;
|
||||
worker_signal(wp); /* Continue open/close */
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* task_reply *
|
||||
*===========================================================================*/
|
||||
static void task_reply(message *m_ptr)
|
||||
{
|
||||
/* A character driver has results for a read, write, or ioctl call. There may
|
||||
* be a thread waiting for these results as part of an ongoing dev_cancel call.
|
||||
* If so, wake up that thread; if not, send a reply to the requesting process.
|
||||
* This function MUST NOT block its calling thread.
|
||||
*/
|
||||
struct fproc *rfp;
|
||||
struct worker_thread *wp;
|
||||
endpoint_t proc_e;
|
||||
int slot;
|
||||
|
||||
proc_e = m_ptr->REP_ENDPT;
|
||||
if (proc_e == VFS_PROC_NR)
|
||||
proc_e = find_suspended_ep(m_ptr->m_source, m_ptr->REP_IO_GRANT);
|
||||
else
|
||||
printf("VFS: endpoint %u from %u is not VFS\n",
|
||||
proc_e, m_ptr->m_source);
|
||||
|
||||
if (proc_e == NONE) {
|
||||
printf("VFS: proc with grant %d from %d not found\n",
|
||||
m_ptr->REP_IO_GRANT, m_ptr->m_source);
|
||||
} else if (m_ptr->REP_STATUS == SUSPEND) {
|
||||
printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n");
|
||||
} else {
|
||||
/* If there is a thread active for this process, we assume that this
|
||||
* thread aims to cancel the ongoing operation. In that case, wake up
|
||||
* the thread to let it finish unpausing the process. Otherwise, revive
|
||||
* the process as usual.
|
||||
if (isokendpt(proc_e, &slot) != OK) {
|
||||
printf("VFS: proc %d from %d not found\n", proc_e, m_ptr->m_source);
|
||||
return;
|
||||
}
|
||||
rfp = &fproc[slot];
|
||||
wp = rfp->fp_worker;
|
||||
if (wp != NULL && wp->w_task == who_e) {
|
||||
assert(!fp_is_blocked(rfp));
|
||||
*wp->w_drv_sendrec = *m_ptr;
|
||||
worker_signal(wp); /* Continue open/close/cancel */
|
||||
} else if (rfp->fp_blocked_on != FP_BLOCKED_ON_OTHER ||
|
||||
rfp->fp_task != m_ptr->m_source) {
|
||||
/* This would typically be caused by a protocol error, i.e. a driver
|
||||
* not properly following the character driver protocol rules.
|
||||
*/
|
||||
if (isokendpt(proc_e, &slot) != OK) return;
|
||||
rfp = &fproc[slot];
|
||||
wp = rfp->fp_worker;
|
||||
if (wp != NULL && wp->w_task == who_e) {
|
||||
assert(!fp_is_blocked(rfp));
|
||||
*wp->w_drv_sendrec = *m_ptr;
|
||||
worker_signal(wp); /* Continue cancel */
|
||||
} else {
|
||||
revive(proc_e, m_ptr->REP_STATUS);
|
||||
}
|
||||
printf("VFS: proc %d not blocked on %d\n", proc_e, m_ptr->m_source);
|
||||
} else {
|
||||
revive(proc_e, m_ptr->CDEV_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -960,15 +891,20 @@ void cdev_reply(void)
|
|||
{
|
||||
/* A character driver has results for us. */
|
||||
|
||||
if (get_dmap(who_e) == NULL) {
|
||||
printf("VFS: ignoring char dev reply from unknown driver %d\n", who_e);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (call_nr) {
|
||||
case DEV_OPEN_REPL:
|
||||
case DEV_CLOSE_REPL: opcl_reply(&m_in); break;
|
||||
case DEV_REVIVE: task_reply(&m_in); break;
|
||||
case DEV_SEL_REPL1:
|
||||
select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
|
||||
case CDEV_REPLY:
|
||||
cdev_generic_reply(&m_in);
|
||||
break;
|
||||
case DEV_SEL_REPL2:
|
||||
select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
|
||||
case CDEV_SEL1_REPLY:
|
||||
select_reply1(m_in.m_source, m_in.CDEV_MINOR, m_in.CDEV_STATUS);
|
||||
break;
|
||||
case CDEV_SEL2_REPLY:
|
||||
select_reply2(m_in.m_source, m_in.CDEV_MINOR, m_in.CDEV_STATUS);
|
||||
break;
|
||||
default:
|
||||
printf("VFS: char driver %u sent unknown reply %x\n", who_e, call_nr);
|
||||
|
@ -979,15 +915,24 @@ void cdev_reply(void)
|
|||
/*===========================================================================*
|
||||
* bdev_reply *
|
||||
*===========================================================================*/
|
||||
void bdev_reply(struct dmap *dp)
|
||||
void bdev_reply(void)
|
||||
{
|
||||
/* A block driver has results for a call. There must be a thread waiting for
|
||||
* these results - wake it up. This function MUST NOT block its calling thread.
|
||||
*/
|
||||
struct worker_thread *wp;
|
||||
struct dmap *dp;
|
||||
|
||||
assert(dp != NULL);
|
||||
assert(dp->dmap_servicing != NONE);
|
||||
if ((dp = get_dmap(who_e)) == NULL) {
|
||||
printf("VFS: ignoring block dev reply from unknown driver %d\n",
|
||||
who_e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dp->dmap_servicing == INVALID_THREAD) {
|
||||
printf("VFS: ignoring spurious block dev reply from %d\n", who_e);
|
||||
return;
|
||||
}
|
||||
|
||||
wp = worker_get(dp->dmap_servicing);
|
||||
if (wp == NULL || wp->w_task != who_e) {
|
||||
|
|
|
@ -182,9 +182,6 @@ int flags; /* device flags */
|
|||
dp->dmap_opcl = ctty_opcl;
|
||||
dp->dmap_io = ctty_io;
|
||||
break;
|
||||
case STYLE_CLONE:
|
||||
dp->dmap_opcl = clone_opcl;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
|
@ -281,7 +278,7 @@ void init_dmap()
|
|||
dmap[i].dmap_io = no_dev_io;
|
||||
dmap[i].dmap_driver = NONE;
|
||||
dmap[i].dmap_style = STYLE_NDEV;
|
||||
dmap[i].dmap_servicing = NONE;
|
||||
dmap[i].dmap_servicing = INVALID_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,7 +341,7 @@ void dmap_endpt_up(endpoint_t proc_e, int is_blk)
|
|||
if (dp->dmap_recovering) {
|
||||
printf("VFS: driver recovery failure for"
|
||||
" major %d\n", major);
|
||||
if (dp->dmap_servicing != NONE) {
|
||||
if (dp->dmap_servicing != INVALID_THREAD) {
|
||||
worker = worker_get(dp->dmap_servicing);
|
||||
worker_stop(worker);
|
||||
}
|
||||
|
@ -355,7 +352,7 @@ void dmap_endpt_up(endpoint_t proc_e, int is_blk)
|
|||
bdev_up(major);
|
||||
dp->dmap_recovering = 0;
|
||||
} else {
|
||||
if (dp->dmap_servicing != NONE) {
|
||||
if (dp->dmap_servicing != INVALID_THREAD) {
|
||||
worker = worker_get(dp->dmap_servicing);
|
||||
worker_stop(worker);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ extern struct dmap {
|
|||
int dmap_style;
|
||||
int dmap_sel_busy;
|
||||
struct filp *dmap_sel_filp;
|
||||
endpoint_t dmap_servicing;
|
||||
thread_t dmap_servicing;
|
||||
mutex_t dmap_lock;
|
||||
mutex_t *dmap_lock_ref;
|
||||
int dmap_recovering;
|
||||
|
|
|
@ -579,7 +579,7 @@ struct filp *f;
|
|||
|
||||
(void) bdev_close(dev); /* Ignore errors */
|
||||
} else {
|
||||
(void) dev_close(dev); /* Ignore errors */
|
||||
(void) cdev_close(dev); /* Ignore errors */
|
||||
}
|
||||
|
||||
f->filp_mode = FILP_CLOSED;
|
||||
|
|
|
@ -29,8 +29,6 @@ EXTERN struct fproc {
|
|||
int fp_block_callnr; /* blocked call if rd/wr can't finish */
|
||||
int fp_cum_io_partial; /* partial byte count if rd/wr can't finish */
|
||||
endpoint_t fp_task; /* which task is proc suspended on */
|
||||
endpoint_t fp_ioproc; /* proc no. in suspended-on i/o message */
|
||||
|
||||
cp_grant_id_t fp_grant; /* revoke this grant on unsuspend if > -1 */
|
||||
|
||||
uid_t fp_realuid; /* real user id */
|
||||
|
|
|
@ -124,36 +124,14 @@ int main(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* At this point we either have results from an asynchronous device
|
||||
* or a new system call. In both cases a new worker thread has to be
|
||||
* started and there might not be one available from the pool. This is
|
||||
* not a problem (requests/replies are simply queued), except when
|
||||
* they're from an FS endpoint, because these can cause a deadlock.
|
||||
* handle_work() takes care of the details. */
|
||||
if (IS_DRV_REPLY(call_nr)) {
|
||||
/* We've got results for a device request */
|
||||
|
||||
struct dmap *dp;
|
||||
|
||||
dp = get_dmap(who_e);
|
||||
if (dp != NULL) {
|
||||
if (!IS_BDEV_RS(call_nr)) {
|
||||
cdev_reply();
|
||||
|
||||
} else {
|
||||
if (dp->dmap_servicing == NONE) {
|
||||
printf("Got spurious dev reply from %d",
|
||||
who_e);
|
||||
} else {
|
||||
bdev_reply(dp);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
printf("VFS: ignoring dev reply from unknown driver %d\n",
|
||||
who_e);
|
||||
if (IS_BDEV_RS(call_nr)) {
|
||||
/* We've got results for a block device request. */
|
||||
bdev_reply();
|
||||
} else if (IS_CDEV_RS(call_nr)) {
|
||||
/* We've got results for a character device request. */
|
||||
cdev_reply();
|
||||
} else {
|
||||
/* Normal syscall. */
|
||||
/* Normal syscall. This spawns a new thread. */
|
||||
handle_work(do_work);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -659,7 +659,7 @@ static void free_proc(int flags)
|
|||
if (!S_ISCHR(vp->v_mode)) continue;
|
||||
if ((dev_t) vp->v_sdev != dev) continue;
|
||||
lock_filp(rfilp, VNODE_READ);
|
||||
(void) dev_close(dev); /* Ignore any errors. */
|
||||
(void) cdev_close(dev); /* Ignore any errors. */
|
||||
|
||||
rfilp->filp_mode = FILP_CLOSED;
|
||||
unlock_filp(rfilp);
|
||||
|
|
|
@ -156,9 +156,9 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
|||
/* Invoke the driver for special processing. */
|
||||
dev = (dev_t) vp->v_sdev;
|
||||
/* TTY needs to know about the O_NOCTTY flag. */
|
||||
r = dev_open(dev, bits | (oflags & O_NOCTTY));
|
||||
r = cdev_open(dev, bits | (oflags & O_NOCTTY));
|
||||
vp = filp->filp_vno; /* Might be updated by
|
||||
* dev_open/clone_opcl */
|
||||
* cdev_open after cloning */
|
||||
break;
|
||||
case S_IFBLK:
|
||||
|
||||
|
|
|
@ -527,7 +527,7 @@ void unpause(void)
|
|||
blocked_on = fp->fp_blocked_on;
|
||||
|
||||
/* Clear the block status now. The procedure below might make blocking calls
|
||||
* and it is imperative that while at least dev_cancel() is executing, other
|
||||
* and it is imperative that while at least cdev_cancel() is executing, other
|
||||
* parts of VFS do not perceive this process as blocked on something.
|
||||
*/
|
||||
fp->fp_blocked_on = FP_BLOCKED_ON_NONE;
|
||||
|
@ -573,7 +573,7 @@ void unpause(void)
|
|||
}
|
||||
dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */
|
||||
|
||||
status = dev_cancel(dev);
|
||||
status = cdev_cancel(dev);
|
||||
|
||||
break;
|
||||
default :
|
||||
|
|
|
@ -29,14 +29,17 @@ void fs_sendmore(struct vmnt *vmp);
|
|||
void send_work(void);
|
||||
|
||||
/* device.c */
|
||||
int dev_open(dev_t dev, int flags);
|
||||
int dev_close(dev_t dev);
|
||||
int cdev_open(dev_t dev, int flags);
|
||||
int cdev_close(dev_t dev);
|
||||
int cdev_io(int op, dev_t dev, endpoint_t proc_e, void *buf, off_t pos,
|
||||
unsigned long bytes, int flags);
|
||||
int cdev_select(dev_t dev, int ops);
|
||||
int cdev_cancel(dev_t dev);
|
||||
void cdev_reply(void);
|
||||
int bdev_open(dev_t dev, int access);
|
||||
int bdev_close(dev_t dev);
|
||||
void bdev_reply(struct dmap *dp);
|
||||
int dev_io(int op, dev_t dev, endpoint_t proc_e, void *buf, off_t pos,
|
||||
size_t bytes, int flags);
|
||||
void bdev_reply(void);
|
||||
void bdev_up(int major);
|
||||
int gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags);
|
||||
int gen_io(endpoint_t drv_e, message *mess_ptr);
|
||||
int no_dev(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
|
@ -46,10 +49,7 @@ int ctty_opcl(int op, dev_t dev, endpoint_t proc, int flags);
|
|||
int clone_opcl(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int ctty_io(endpoint_t task_nr, message *mess_ptr);
|
||||
int do_ioctl(message *m_out);
|
||||
int dev_select(dev_t dev, int ops);
|
||||
int dev_cancel(dev_t dev);
|
||||
void pm_setsid(endpoint_t proc_e);
|
||||
void bdev_up(int major);
|
||||
|
||||
/* dmap.c */
|
||||
void lock_dmap(struct dmap *dp);
|
||||
|
|
|
@ -137,6 +137,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
off_t position, res_pos;
|
||||
unsigned int cum_io, cum_io_incr, res_cum_io;
|
||||
int op, r;
|
||||
dev_t dev;
|
||||
|
||||
position = f->filp_pos;
|
||||
vp = f->filp_vno;
|
||||
|
@ -147,7 +148,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
|
||||
if (size > SSIZE_MAX) return(EINVAL);
|
||||
|
||||
op = (rw_flag == READING ? DEV_READ_S : DEV_WRITE_S);
|
||||
op = (rw_flag == READING ? CDEV_READ : CDEV_WRITE);
|
||||
|
||||
if (S_ISFIFO(vp->v_mode)) { /* Pipes */
|
||||
if (rfp->fp_cum_io_partial != 0) {
|
||||
|
@ -159,9 +160,6 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
}
|
||||
r = rw_pipe(rw_flag, for_e, f, buf, size);
|
||||
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
|
||||
dev_t dev;
|
||||
int op = (rw_flag == READING ? DEV_READ_S : DEV_WRITE_S);
|
||||
|
||||
if(rw_flag == PEEKING) {
|
||||
printf("read_write: peek on char device makes no sense\n");
|
||||
return EINVAL;
|
||||
|
@ -172,7 +170,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
|
||||
dev = (dev_t) vp->v_sdev;
|
||||
|
||||
r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags);
|
||||
r = cdev_io(op, dev, for_e, buf, position, size, f->filp_flags);
|
||||
if (r >= 0) {
|
||||
/* This should no longer happen: all calls are asynchronous. */
|
||||
printf("VFS: I/O to device %x succeeded immediately!?\n", dev);
|
||||
|
|
|
@ -406,7 +406,7 @@ static int select_request_char(struct filp *f, int *ops, int block)
|
|||
return(SUSPEND);
|
||||
|
||||
f->filp_select_flags &= ~FSF_UPDATE;
|
||||
r = dev_select(f->filp_vno->v_sdev, rops);
|
||||
r = cdev_select(f->filp_vno->v_sdev, rops);
|
||||
if (r != OK)
|
||||
return(r);
|
||||
|
||||
|
@ -719,7 +719,7 @@ void select_timeout_check(timer_t *timer)
|
|||
if (se->requestor == NULL) return;
|
||||
if (se->expiry <= 0) return; /* Strange, did we even ask for a timeout? */
|
||||
se->expiry = 0;
|
||||
if (is_deferred(se)) return; /* Wait for initial replies to DEV_SELECT */
|
||||
if (is_deferred(se)) return; /* Wait for initial replies to CDEV_SELECT */
|
||||
select_return(se);
|
||||
}
|
||||
|
||||
|
@ -771,7 +771,7 @@ endpoint_t driver_e;
|
|||
int minor;
|
||||
int status;
|
||||
{
|
||||
/* Handle the initial reply to DEV_SELECT request. This function MUST NOT
|
||||
/* Handle the initial reply to CDEV_SELECT request. This function MUST NOT
|
||||
* block its calling thread.
|
||||
*/
|
||||
int major;
|
||||
|
@ -788,7 +788,7 @@ int status;
|
|||
|
||||
/* Get filp belonging to character special file */
|
||||
if (!dp->dmap_sel_busy) {
|
||||
printf("VFS (%s:%d): major %d was not expecting a DEV_SELECT reply\n",
|
||||
printf("VFS (%s:%d): major %d was not expecting a CDEV_SELECT reply\n",
|
||||
__FILE__, __LINE__, major);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -75,13 +75,4 @@ int select(int, fd_set * __restrict, fd_set * __restrict,
|
|||
__END_DECLS
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#if defined(__minix) && defined(_NETBSD_SOURCE)
|
||||
/* possible select() operation types; read, write, errors */
|
||||
/* (FS/driver internal use only) */
|
||||
#define SEL_RD (1 << 0)
|
||||
#define SEL_WR (1 << 1)
|
||||
#define SEL_ERR (1 << 2)
|
||||
#define SEL_NOTIFY (1 << 3) /* not a real select operation */
|
||||
#endif /* defined(__minix) && defined(_NETBSD_SOURCE) */
|
||||
|
||||
#endif /* !_SYS_SELECT_H_ */
|
||||
|
|
Loading…
Reference in a new issue