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:
David van Moolenbroek 2013-09-10 20:25:01 +02:00 committed by Lionel Sambuc
parent 87337273e4
commit 665198b4c2
38 changed files with 515 additions and 661 deletions

View file

@ -335,9 +335,9 @@ static int parse_arguments(int argc, char **argv, u32_t *rss_flags)
} }
else if (strcmp(argv[i], ARG_DEVSTYLE)==0) { else if (strcmp(argv[i], ARG_DEVSTYLE)==0) {
char* dev_style_keys[] = { "STYLE_DEV", "STYLE_TTY", char* dev_style_keys[] = { "STYLE_DEV", "STYLE_TTY",
"STYLE_CTTY", "STYLE_CLONE", NULL }; "STYLE_CTTY", NULL };
int dev_style_values[] = { STYLE_DEV, STYLE_TTY, int dev_style_values[] = { STYLE_DEV, STYLE_TTY,
STYLE_CTTY, STYLE_CLONE }; STYLE_CTTY };
for(j=0;dev_style_keys[j]!=NULL;j++) { for(j=0;dev_style_keys[j]!=NULL;j++) {
if(!strcmp(dev_style_keys[j], argv[i+1])) { if(!strcmp(dev_style_keys[j], argv[i+1])) {
break; break;

View file

@ -167,17 +167,17 @@ subwrite(struct logdevice *log, size_t size, endpoint_t endpt,
log->log_source = NONE; 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 /* 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 * a blocking read (above), this can only happen if the blocking read
* didn't swallow all the data (log_size > 0). * didn't swallow all the data (log_size > 0).
*/ */
minor = log-logdevices; minor = log-logdevices;
#if LOG_DEBUG #if LOG_DEBUG
printf("select sending DEV_SEL_REPL2\n"); printf("select sending CDEV_SEL2_REPLY\n");
#endif #endif
chardriver_reply_select(log->log_select_proc, minor, SEL_RD); chardriver_reply_select(log->log_select_proc, minor, CDEV_OP_RD);
log->log_selected &= ~SEL_RD; log->log_selected &= ~CDEV_OP_RD;
} }
return r; 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_source != NONE) return OK;
if (!log->log_size && size > 0) { 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. */ /* No data available; let caller block. */
log->log_source = endpt; 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) if (minor < 0 || minor >= NR_DEVS)
return ENXIO; 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. */ /* 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 #if LOG_DEBUG
printf("log can read; size %d\n", logdevices[minor].log_size); printf("log can read; size %d\n", logdevices[minor].log_size);
#endif #endif
ready_ops |= SEL_RD; ready_ops |= CDEV_OP_RD;
} }
/* Write never blocks. */ /* 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, /* Enable select calback if not all requested operations were ready to go,
* and notify was enabled. * and notify was enabled.
*/ */
want_ops &= ~ready_ops; 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_selected |= want_ops;
logdevices[minor].log_select_proc = endpt; logdevices[minor].log_select_proc = endpt;
#if LOG_DEBUG #if LOG_DEBUG

View file

@ -5,27 +5,6 @@
* Changes: * Changes:
* May 07, 2004 fix: wait until printer is ready (Jorrit N. Herder) * May 07, 2004 fix: wait until printer is ready (Jorrit N. Herder)
* May 06, 2004 printer driver moved to user-space (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. * 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 (writing) return EIO;
if (size <= 0) return EINVAL; 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. /* If no errors occurred, continue printing with the caller.
* First wait until the printer is online to prevent stupid errors. * First wait until the printer is online to prevent stupid errors.

View file

@ -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 no data is available, suspend the caller. */
if (kbdp->avail == 0) { if (kbdp->avail == 0) {
if (flags & FLG_OP_NONBLOCK) if (flags & CDEV_NONBLOCK)
return EAGAIN; return EAGAIN;
kbdp->req_size = size; kbdp->req_size = size;
kbdp->req_id = id; kbdp->req_id = id;
@ -420,14 +420,14 @@ kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
if ((kbdp = line2kbd(minor)) == NULL) if ((kbdp = line2kbd(minor)) == NULL)
return ENXIO; return ENXIO;
watch = (ops & SEL_NOTIFY); watch = (ops & CDEV_NOTIFY);
ops &= (SEL_RD | SEL_WR | SEL_ERR); ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
ready_ops = 0; ready_ops = 0;
if (kbdp->avail && (ops & SEL_RD)) if (kbdp->avail && (ops & CDEV_OP_RD))
ready_ops |= SEL_RD; ready_ops |= CDEV_OP_RD;
if (ops & SEL_WR) if (ops & CDEV_OP_WR)
ready_ops |= SEL_WR; /* writes never block */ ready_ops |= CDEV_OP_WR; /* writes never block */
ops &= ~ready_ops; ops &= ~ready_ops;
if (ops && watch) { if (ops && watch) {
@ -543,10 +543,10 @@ void kbd_interrupt(message *UNUSED(m_ptr))
kbdp->req_caller = NONE; kbdp->req_caller = NONE;
} }
/* Only satisfy pending select if characters weren't just read. */ /* 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, chardriver_reply_select(kbdp->select_proc, kbdp->minor,
SEL_RD); CDEV_OP_RD);
kbdp->select_ops &= ~SEL_RD; kbdp->select_ops &= ~CDEV_OP_RD;
} }
return; return;
} }
@ -557,7 +557,7 @@ void kbd_interrupt(message *UNUSED(m_ptr))
if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf; if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
icount++; icount++;
tty_table[ccurrent].tty_events = 1; 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]); select_retry(&tty_table[ccurrent]);
} }
} }
@ -581,7 +581,7 @@ void do_kb_inject(message *msg)
if (injhead == injbuf + KB_IN_BYTES) injhead = injbuf; if (injhead == injbuf + KB_IN_BYTES) injhead = injbuf;
injcount++; injcount++;
tty_table[ccurrent].tty_events = 1; 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]); select_retry(&tty_table[ccurrent]);
} }
} }

View file

@ -167,7 +167,7 @@ static ssize_t pty_master_read(devminor_t minor, u64_t UNUSED(position),
return EDONTREPLY; /* already done */ return EDONTREPLY; /* already done */
} }
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN; r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
pp->rdleft = pp->rdcum = 0; pp->rdleft = pp->rdcum = 0;
pp->rdcaller = NONE; pp->rdcaller = NONE;
@ -214,7 +214,7 @@ static ssize_t pty_master_write(devminor_t minor, u64_t UNUSED(position),
return EDONTREPLY; /* already done */ return EDONTREPLY; /* already done */
} }
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN; r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
pp->wrleft = pp->wrcum = 0; pp->wrleft = pp->wrcum = 0;
pp->wrcaller = NONE; pp->wrcaller = NONE;
@ -265,18 +265,18 @@ static int select_try_pty(tty_t *tp, int ops)
pty_t *pp = tp->tty_priv; pty_t *pp = tp->tty_priv;
int r = 0; int r = 0;
if (ops & SEL_WR) { if (ops & CDEV_OP_WR) {
/* Write won't block on error. */ /* Write won't block on error. */
if (pp->state & TTY_CLOSED) r |= SEL_WR; if (pp->state & TTY_CLOSED) r |= CDEV_OP_WR;
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR; else if (pp->wrleft != 0 || pp->wrcum != 0) r |= CDEV_OP_WR;
else if (tp->tty_inleft > 0) r |= SEL_WR; /* There's a reader. */ 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. */ /* Read won't block on error. */
if (pp->state & TTY_CLOSED) r |= SEL_RD; if (pp->state & TTY_CLOSED) r |= CDEV_OP_RD;
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD; else if (pp->rdleft != 0 || pp->rdcum != 0) r |= CDEV_OP_RD;
else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */ else if (pp->ocount > 0) r |= CDEV_OP_RD; /* Actual data. */
} }
return r; return r;
@ -313,8 +313,8 @@ static int pty_master_select(devminor_t minor, unsigned int ops,
return ENXIO; return ENXIO;
pp = tp->tty_priv; pp = tp->tty_priv;
watch = (ops & SEL_NOTIFY); watch = (ops & CDEV_NOTIFY);
ops &= (SEL_RD | SEL_WR | SEL_ERR); ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
ready_ops = select_try_pty(tp, ops); ready_ops = select_try_pty(tp, ops);

View file

@ -16,38 +16,6 @@
* to, you guessed it, wake up the TTY to check if input or output can * to, you guessed it, wake up the TTY to check if input or output can
* continue. * 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: * Changes:
* Jan 20, 2004 moved TTY driver to user-space (Jorrit N. Herder) * Jan 20, 2004 moved TTY driver to user-space (Jorrit N. Herder)
* Sep 20, 2004 local timer management/ sync alarms (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 */ ; /* 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); chardriver_process(&tty_tab, &tty_mess, ipc_status);
continue; continue;
} }
@ -243,7 +211,7 @@ int main(void)
/* Only device requests should get to this point. /* Only device requests should get to this point.
* All requests have a minor device number. * All requests have a minor device number.
*/ */
line = tty_mess.DEVICE; line = tty_mess.CDEV_MINOR;
if (line == KBD_MINOR || line == KBDAUX_MINOR) { if (line == KBD_MINOR || line == KBDAUX_MINOR) {
do_kbd(&tty_mess, ipc_status); do_kbd(&tty_mess, ipc_status);
continue; continue;
@ -251,7 +219,7 @@ int main(void)
do_video(&tty_mess, ipc_status); do_video(&tty_mess, ipc_status);
continue; continue;
} else if (line - PTYPX_MINOR < NR_PTYS && } 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 /* Terminals and pseudo terminals belong together. We can only
* make a distinction between the two based on position in the * make a distinction between the two based on position in the
* tty_table and not on minor number (i.e., use ispty macro). * 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'; buf[0] = '\033';
snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color); snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color);
do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf), do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
FLG_OP_NONBLOCK, 0); CDEV_NONBLOCK, 0);
} }
static void static void
@ -288,7 +256,7 @@ reset_color(tty_t *tp)
buf[0] = '\033'; buf[0] = '\033';
snprintf(&buf[1], sizeof(buf) - 1, "[0;%dm", SGR_COLOR_RESET); 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), do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
FLG_OP_NONBLOCK, 0); CDEV_NONBLOCK, 0);
} }
tty_t * tty_t *
@ -466,7 +434,7 @@ do_new_kmess(void)
set_color(tp, kernel_msg_color); set_color(tp, kernel_msg_color);
do_write(tp->tty_minor, 0, KERNEL, do_write(tp->tty_minor, 0, KERNEL,
(cp_grant_id_t) kernel_buf_copy, bytes, (cp_grant_id_t) kernel_buf_copy, bytes,
FLG_OP_NONBLOCK, 0); CDEV_NONBLOCK, 0);
if (kernel_msg_color != 0) if (kernel_msg_color != 0)
reset_color(tp); reset_color(tp);
if (restore) { if (restore) {
@ -553,7 +521,7 @@ static ssize_t do_read(devminor_t minor, u64_t UNUSED(position),
return EDONTREPLY; /* already done */ return EDONTREPLY; /* already done */
/* There were no bytes in the input queue available. */ /* There were no bytes in the input queue available. */
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
tty_icancel(tp); tty_icancel(tp);
r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN; r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
tp->tty_inleft = tp->tty_incum = 0; 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 */ return EDONTREPLY; /* already done */
/* None or not all the bytes could be written. */ /* 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; r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
tp->tty_outleft = tp->tty_outcum = 0; tp->tty_outleft = tp->tty_outcum = 0;
tp->tty_outcaller = NONE; tp->tty_outcaller = NONE;
@ -677,7 +645,7 @@ static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
case TCSETSF: case TCSETSF:
case TCDRAIN: case TCDRAIN:
if (tp->tty_outleft > 0) { if (tp->tty_outleft > 0) {
if (flags & FLG_OP_NONBLOCK) if (flags & CDEV_NONBLOCK)
return EAGAIN; return EAGAIN;
/* Wait for all ongoing output processing to finish. */ /* Wait for all ongoing output processing to finish. */
tp->tty_iocaller = endpt; 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) 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 /* 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 * CDEV_NOCTTY is *not* set and it is not the log device. CDEV_CTTY is returned
* the tty is made the controlling tty, otherwise OK or an error code. * if the tty is made the controlling tty, otherwise OK or an error code.
*/ */
tty_t *tp; tty_t *tp;
int r = OK; 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)) { if (minor == LOG_MINOR && isconsole(tp)) {
/* The log device is a write-only diagnostics device. */ /* The log device is a write-only diagnostics device. */
if (access & R_BIT) return EACCES; if (access & CDEV_R_BIT) return EACCES;
} else { } else {
if (!(access & O_NOCTTY)) { if (!(access & CDEV_NOCTTY)) {
tp->tty_pgrp = user_endpt; tp->tty_pgrp = user_endpt;
r = 1; r = CDEV_CTTY;
} }
tp->tty_openct++; tp->tty_openct++;
if (tp->tty_openct == 1) { if (tp->tty_openct == 1) {
@ -874,10 +842,10 @@ int select_try(struct tty *tp, int ops)
ready_ops |= ops; ready_ops |= ops;
} }
if (ops & SEL_RD) { if (ops & CDEV_OP_RD) {
/* will i/o not block on read? */ /* will i/o not block on read? */
if (tp->tty_inleft > 0) { 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) { } else if (tp->tty_incount > 0) {
/* Is a regular read possible? tty_incount /* Is a regular read possible? tty_incount
* says there is data. But a read will only succeed * 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) || if (!(tp->tty_termios.c_lflag & ICANON) ||
tp->tty_eotct > 0) { tp->tty_eotct > 0) {
ready_ops |= SEL_RD; ready_ops |= CDEV_OP_RD;
} }
} }
} }
if (ops & SEL_WR) { if (ops & CDEV_OP_WR) {
if (tp->tty_outleft > 0) ready_ops |= SEL_WR; if (tp->tty_outleft > 0) ready_ops |= CDEV_OP_WR;
else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= SEL_WR; else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= CDEV_OP_WR;
} }
return ready_ops; 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) if (tp->tty_minor != minor)
return EBADF; return EBADF;
watch = (ops & SEL_NOTIFY); watch = (ops & CDEV_NOTIFY);
ops &= (SEL_RD | SEL_WR | SEL_ERR); ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
ready_ops = select_try(tp, ops); ready_ops = select_try(tp, ops);

View file

@ -25,9 +25,6 @@
#define ESC '\33' /* escape */ #define ESC '\33' /* escape */
#define O_NOCTTY 00400 /* from <fcntl.h>, or cc will choke */
#define O_NONBLOCK 04000
struct tty; struct tty;
typedef int(*devfun_t) (struct tty *tp, int try_only); typedef int(*devfun_t) (struct tty *tp, int try_only);
typedef void(*devfunarg_t) (struct tty *tp, int c); typedef void(*devfunarg_t) (struct tty *tp, int c);

View file

@ -65,10 +65,10 @@ kill_by_name syslogd
sleep 3 sleep 3
if [ X`/bin/sysenv lwip` = Xyes ] if [ X`/bin/sysenv lwip` = Xyes ]
then 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 & dhcpd --lwip &
else 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 daemonize dhcpd
fi fi
daemonize nonamed -L daemonize nonamed -L

View file

@ -188,9 +188,9 @@ start)
done done
if [ X`/bin/sysenv lwip` = Xyes ] if [ X`/bin/sysenv lwip` = Xyes ]
then then
up lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE up lwip -script /etc/rs.inet -dev /dev/ip
else else
up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE up inet -script /etc/rs.inet -dev /dev/ip
fi fi
up -n ipc up -n ipc

View file

@ -8,8 +8,8 @@
* 1 - 0xFF POSIX requests (see callnr.h) * 1 - 0xFF POSIX requests (see callnr.h)
* 0x200 - 0x2FF Data link layer requests and responses * 0x200 - 0x2FF Data link layer requests and responses
* 0x300 - 0x3FF Bus controller requests and responses * 0x300 - 0x3FF Bus controller requests and responses
* 0x400 - 0x4FF Character device requests * 0x400 - 0x4FF Character device requests and responses
* 0x500 - 0x5FF Character device responses * 0x500 - 0x5FF Block device requests and responses
* 0x600 - 0x6FF Kernel calls to SYSTEM task * 0x600 - 0x6FF Kernel calls to SYSTEM task
* 0x700 - 0x7FF Reincarnation Server (RS) requests * 0x700 - 0x7FF Reincarnation Server (RS) requests
* 0x800 - 0x8FF Data Store (DS) requests * 0x800 - 0x8FF Data Store (DS) requests
@ -25,7 +25,7 @@
* 0x1200 - 0x12FF Devman * 0x1200 - 0x12FF Devman
* 0x1300 - 0x13FF TTY Requests * 0x1300 - 0x13FF TTY Requests
* 0x1400 - 0x14FF VFS-FS transaction IDs * 0x1400 - 0x14FF VFS-FS transaction IDs
* 0x1500 - 0x15FF Block device requests and responses * 0x1500 - 0x15FF (unused)
* 0x1600 - 0x16FF VirtualBox (VBOX) requests (see vboxif.h) * 0x1600 - 0x16FF VirtualBox (VBOX) requests (see vboxif.h)
* 0x1700 - 0x17FF Real Time Clock requests and responses * 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_EXEC (BUSC_RQ_BASE + 65) /* perform i2c action */
#define BUSC_I2C_GRANT m2_i1 /* grant for request */ #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 * * Messages for networking layer *
*===========================================================================*/ *===========================================================================*/
@ -939,6 +887,11 @@
#define VFS_PFS_FD m2_i3 #define VFS_PFS_FD m2_i3
#define VFS_PFS_FILP m2_p1 #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 * * Messages for VM server *
*===========================================================================*/ *===========================================================================*/
@ -1298,13 +1251,71 @@
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1) #define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
#define IS_VFS_FS_TRANSID(type) (((type) & ~0xff) == VFS_TRANSACTION_BASE) #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 * * Messages for block devices *
*===========================================================================*/ *===========================================================================*/
/* Base type for block device requests and responses. */ /* Base type for block device requests and responses. */
#define BDEV_RQ_BASE 0x1500 #define BDEV_RQ_BASE 0x500
#define BDEV_RS_BASE 0x1580 #define BDEV_RS_BASE 0x580
#define IS_BDEV_RQ(type) (((type) & ~0x7f) == BDEV_RQ_BASE) #define IS_BDEV_RQ(type) (((type) & ~0x7f) == BDEV_RQ_BASE)
#define IS_BDEV_RS(type) (((type) & ~0x7f) == BDEV_RS_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_FORCEWRITE 0x01 /* force write to disk immediately */
# define BDEV_NOPAGE 0x02 /* eeprom: don't send page address */ # 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 * * Messages for Real Time Clocks *
*===========================================================================*/ *===========================================================================*/
@ -1382,4 +1388,10 @@
#define RTCDEV_Y2KBUG 0x01 /* Interpret 1980 as 2000 for RTC w/Y2K bug */ #define RTCDEV_Y2KBUG 0x01 /* Interpret 1980 as 2000 for RTC w/Y2K bug */
#define RTCDEV_CMOSREG 0x02 /* Also set the CMOS clock register bits. */ #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 */ /* _MINIX_COM_H */

View file

@ -4,8 +4,8 @@
#include <minix/sys_config.h> #include <minix/sys_config.h>
#include <minix/ipc.h> #include <minix/ipc.h>
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY, STYLE_CLONE }; enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY };
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CLONE) #define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CTTY)
/*===========================================================================* /*===========================================================================*
* Major and minor device numbers * * Major and minor device numbers *

View file

@ -5,23 +5,6 @@
* extra buffer space beside the dma buffer. * extra buffer space beside the dma buffer.
* This driver also support sub devices, which can be independently * This driver also support sub devices, which can be independently
* opened and closed. * 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: * The file contains one entry point:
* *

View file

@ -369,9 +369,9 @@ static void do_char_open(message *m_ptr, int ipc_status)
memset(&m_reply, 0, sizeof(m_reply)); memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DEV_OPEN_REPL; m_reply.m_type = CDEV_REPLY;
m_reply.REP_ENDPT = m_ptr->USER_ENDPT; m_reply.CDEV_STATUS = ENXIO;
m_reply.REP_STATUS = ENXIO; m_reply.CDEV_ID = m_ptr->CDEV_ID;
send_reply(m_ptr->m_source, &m_reply, ipc_status); 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 * someone creates a character device node for a block driver, opening that
* device node will cause the corresponding VFS thread to block forever. * 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); do_char_open(m_ptr, ipc_status);
return; return;

View file

@ -1,27 +1,36 @@
/* This file contains the device independent character driver interface. /* 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 * m_type MINOR GRANT COUNT FLAGS ID POS_LO POS_HI
* ---------------------------------------------------------------------------- * +-------------+-------+--------+-------+-------+------+---------+--------+
* | DEV_OPEN | device | proc nr | mode | | | | * | CDEV_OPEN | minor | access | user | | id | | |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_CLOSE | device | proc nr | | | | | * | CDEV_CLOSE | minor | | | | id | | |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_READ_S | device | proc nr | bytes | off lo | off hi i buf grant | * | CDEV_READ | minor | grant | bytes | flags | id | position |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_WRITE_S | device | proc nr | bytes | off lo | off hi | buf grant | * | CDEV_WRITE | minor | grant | bytes | flags | id | position |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_GATHER_S | device | proc nr | iov len | off lo | off hi | iov grant | * | CDEV_IOCTL | minor | grant | user | flags | id | request | |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_SCATTER_S | device | proc nr | iov len | off lo | off hi | iov grant | * | CDEV_CANCEL | minor | | | | id | | |
* |---------------+--------+---------+---------+--------+--------+-----------| * |-------------+-------+--------+-------+-------+------+---------+--------|
* | DEV_IOCTL_S | device | proc nr | request | | | buf grant | * | CDEV_SELECT | minor | ops | | | | | |
* |---------------+--------+---------+---------+--------+--------+-----------| * --------------------------------------------------------------------------
* | CANCEL | device | proc nr | r/w | | | grant | *
* |---------------+--------+---------+---------+--------+--------+-----------| * The following reply messages are used.
* | DEV_SELECT | device | ops | | | | | *
* ---------------------------------------------------------------------------- * m_type MINOR STATUS ID
* +-----------------+-------+--------+-----+-----+------+---------+--------+
* | CDEV_REPLY | | status | | | id | | |
* |-----------------+-------+--------+-----+-----+------+---------+--------|
* | CDEV_SEL1_REPLY | minor | status | | | | | |
* |-----------------+-------+--------+-----+-----+------+---------+--------|
* | CDEV_SEL2_REPLY | minor | status | | | | | |
* --------------------------------------------------------------------------
* *
* Changes: * Changes:
* Sep 01, 2013 complete rewrite of the API (D.C. van Moolenboek) * 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) if ((r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)) != OK)
panic("chardriver_init: unable to publish driver up event: %d", r); 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(); 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)); memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DEV_REVIVE; m_reply.m_type = CDEV_REPLY;
m_reply.REP_STATUS = r; m_reply.CDEV_STATUS = r;
m_reply.REP_ENDPT = endpt; /* XXX FIXME: hack */ m_reply.CDEV_ID = id;
m_reply.REP_IO_GRANT = (cp_grant_id_t) id;
if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK) if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK)
printf("chardriver_reply_task: send to %d failed: %d\n", endpt, r); 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)); memset(&m_reply, 0, sizeof(m_reply));
m_reply.m_type = DEV_SEL_REPL2; m_reply.m_type = CDEV_SEL2_REPLY;
m_reply.DEV_MINOR = minor; m_reply.CDEV_MINOR = minor;
m_reply.DEV_SEL_OPS = r; m_reply.CDEV_STATUS = r;
if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK) if ((r = asynsend3(endpt, &m_reply, AMF_NOREPLY)) != OK)
printf("chardriver_reply_select: send to %d failed: %d\n", endpt, r); 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) { if (r == EDONTREPLY) {
switch (mess->m_type) { switch (mess->m_type) {
case DEV_READ_S: case CDEV_READ:
case DEV_WRITE_S: case CDEV_WRITE:
case DEV_IOCTL_S: case CDEV_IOCTL:
#if 0 /* XXX doesn't match lwip's model, disabled for now */ /* FIXME: we should be able to check CDEV_FLAGS against
if (mess->FLAGS & FLG_OP_NONBLOCK) * 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"); panic("chardriver: cannot suspend nonblocking I/O");
#endif #endif
/*fall-through*/ /*fall-through*/
case CANCEL: case CDEV_CANCEL:
return; /* alright */ return; /* alright */
default: default:
panic("chardriver: cannot suspend request %d", mess->m_type); 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)); memset(&reply_mess, 0, sizeof(reply_mess));
switch (mess->m_type) { switch (mess->m_type) {
case DEV_OPEN: case CDEV_OPEN:
reply_mess.m_type = DEV_OPEN_REPL; case CDEV_CLOSE:
reply_mess.REP_ENDPT = mess->USER_ENDPT; case CDEV_READ:
reply_mess.REP_STATUS = r; 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; break;
case DEV_CLOSE: case CDEV_SELECT:
reply_mess.m_type = DEV_CLOSE_REPL; reply_mess.m_type = CDEV_SEL1_REPLY;
reply_mess.REP_ENDPT = mess->USER_ENDPT; reply_mess.CDEV_MINOR = mess->CDEV_MINOR;
reply_mess.REP_STATUS = r; reply_mess.CDEV_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;
break; break;
default: default:
@ -272,15 +274,18 @@ static int do_open(struct chardriver *cdp, message *m_ptr)
return OK; return OK;
/* Call the open hook. */ /* Call the open hook. */
minor = m_ptr->DEVICE; minor = m_ptr->CDEV_MINOR;
access = m_ptr->COUNT; access = m_ptr->CDEV_ACCESS;
user_endpt = m_ptr->USER_ENDPT; user_endpt = m_ptr->CDEV_USER;
r = cdp->cdr_open(minor, access, user_endpt); r = cdp->cdr_open(minor, access, user_endpt);
/* If the device has been cloned, mark the new minor as open too. */ /* If the device has been cloned, mark the new minor as open too. */
if (r >= 0 && !is_open_dev(r)) /* XXX FIXME */ if (r >= 0 && (r & CDEV_CLONED)) {
set_open_dev(r); minor = r & ~(CDEV_CLONED | CDEV_CTTY);
if (!is_open_dev(minor))
set_open_dev(minor);
}
return r; return r;
} }
@ -298,7 +303,7 @@ static int do_close(struct chardriver *cdp, message *m_ptr)
return OK; return OK;
/* Call the close hook. */ /* Call the close hook. */
minor = m_ptr->DEVICE; minor = m_ptr->CDEV_MINOR;
return cdp->cdr_close(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; cdev_id_t id;
ssize_t r; ssize_t r;
minor = m_ptr->DEVICE; minor = m_ptr->CDEV_MINOR;
position = make64(m_ptr->POSITION, m_ptr->HIGHPOS); position = make64(m_ptr->CDEV_POS_LO, m_ptr->CDEV_POS_HI);
endpt = m_ptr->m_source; endpt = m_ptr->m_source;
grant = (cp_grant_id_t) m_ptr->IO_GRANT; grant = (cp_grant_id_t) m_ptr->CDEV_GRANT;
size = m_ptr->COUNT; size = m_ptr->CDEV_COUNT;
flags = m_ptr->FLAGS; flags = m_ptr->CDEV_FLAGS;
id = (cdev_id_t) m_ptr->IO_GRANT; id = m_ptr->CDEV_ID;
/* Call the read/write hook, if the appropriate one is in place. */ /* Call the read/write hook, if the appropriate one is in place. */
if (!do_write && cdp->cdr_read != NULL) if (!do_write && cdp->cdr_read != NULL)
@ -355,13 +360,13 @@ static int do_ioctl(struct chardriver *cdp, message *m_ptr)
return ENOTTY; return ENOTTY;
/* Call the ioctl hook. */ /* Call the ioctl hook. */
minor = m_ptr->DEVICE; minor = m_ptr->CDEV_MINOR;
request = m_ptr->REQUEST; request = m_ptr->CDEV_REQUEST;
endpt = m_ptr->m_source; endpt = m_ptr->m_source;
grant = (cp_grant_id_t) m_ptr->IO_GRANT; grant = m_ptr->CDEV_GRANT;
flags = m_ptr->FLAGS; flags = m_ptr->CDEV_FLAGS;
user_endpt = (endpoint_t) m_ptr->POSITION; user_endpt = m_ptr->CDEV_USER;
id = (cdev_id_t) m_ptr->IO_GRANT; id = m_ptr->CDEV_ID;
return cdp->cdr_ioctl(minor, request, endpt, grant, flags, user_endpt, 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; return EDONTREPLY;
/* Call the cancel hook. */ /* Call the cancel hook. */
minor = m_ptr->DEVICE; minor = m_ptr->CDEV_MINOR;
endpt = m_ptr->m_source; 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); return cdp->cdr_cancel(minor, endpt, id);
} }
@ -405,8 +410,8 @@ static int do_select(struct chardriver *cdp, message *m_ptr)
return EBADF; return EBADF;
/* Call the select hook. */ /* Call the select hook. */
minor = m_ptr->DEV_MINOR; minor = m_ptr->CDEV_MINOR;
ops = m_ptr->DEV_SEL_OPS; ops = m_ptr->CDEV_OPS;
endpt = m_ptr->m_source; endpt = m_ptr->m_source;
return cdp->cdr_select(minor, ops, endpt); 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 /* We might get spurious requests if the driver has been restarted. Deny any
* requests on devices that have not previously been opened. * 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. */ /* 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 */ return; /* do not send a reply */
/* Mark the device as opened otherwise. */ /* 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. */ /* Call the appropriate function(s) for this request. */
switch (m_ptr->m_type) { switch (m_ptr->m_type) {
case DEV_OPEN: r = do_open(cdp, m_ptr); break; case CDEV_OPEN: r = do_open(cdp, m_ptr); break;
case DEV_CLOSE: r = do_close(cdp, m_ptr); break; case CDEV_CLOSE: r = do_close(cdp, m_ptr); break;
case DEV_READ_S: r = do_transfer(cdp, m_ptr, FALSE); break; case CDEV_READ: r = do_transfer(cdp, m_ptr, FALSE); break;
case DEV_WRITE_S: r = do_transfer(cdp, m_ptr, TRUE); break; case CDEV_WRITE: r = do_transfer(cdp, m_ptr, TRUE); break;
case DEV_IOCTL_S: r = do_ioctl(cdp, m_ptr); break; case CDEV_IOCTL: r = do_ioctl(cdp, m_ptr); break;
case CANCEL: r = do_cancel(cdp, m_ptr); break; case CDEV_CANCEL: r = do_cancel(cdp, m_ptr); break;
case DEV_SELECT: r = do_select(cdp, m_ptr); break; case CDEV_SELECT: r = do_select(cdp, m_ptr); break;
default: default:
if (cdp->cdr_other) if (cdp->cdr_other)
cdp->cdr_other(m_ptr, ipc_status); cdp->cdr_other(m_ptr, ipc_status);

View file

@ -261,7 +261,7 @@ struct socket * get_unused_sock(void)
static int socket_request_socket(struct socket * sock, struct sock_req * req) 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) { switch (req->type) {
case SOCK_REQ_READ: 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), static int netsock_open(devminor_t minor, int UNUSED(access),
endpoint_t UNUSED(user_endpt)) 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) 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 */ /* in this case any operation would block, no error */
if (sock->flags & SOCK_FLG_OP_PENDING) { if (sock->flags & SOCK_FLG_OP_PENDING) {
if (sel & SEL_NOTIFY) { if (sel & CDEV_NOTIFY) {
if (sel & SEL_RD) if (sel & CDEV_OP_RD)
sock->flags |= SOCK_FLG_SEL_READ; sock->flags |= SOCK_FLG_SEL_READ;
if (sel & SEL_WR) if (sel & CDEV_OP_WR)
sock->flags |= SOCK_FLG_SEL_WRITE; sock->flags |= SOCK_FLG_SEL_WRITE;
/* FIXME we do not monitor error */ /* FIXME we do not monitor error */
} }
return 0; return 0;
} }
if (sel & SEL_RD) { if (sel & CDEV_OP_RD) {
if (sock->recv_head) if (sock->recv_head)
retsel |= SEL_RD; retsel |= CDEV_OP_RD;
else if (sel & SEL_NOTIFY) else if (sel & CDEV_NOTIFY)
sock->flags |= SOCK_FLG_SEL_READ; sock->flags |= SOCK_FLG_SEL_READ;
} }
/* FIXME generic packet socket never blocks on write */ /* FIXME generic packet socket never blocks on write */
if (sel & SEL_WR) if (sel & CDEV_OP_WR)
retsel |= SEL_WR; retsel |= CDEV_OP_WR;
/* FIXME SEL_ERR is ignored, we do not generate exceptions */ /* FIXME CDEV_OP_ERR is ignored, we do not generate exceptions */
return retsel; return retsel;
} }
@ -545,7 +550,7 @@ int generic_op_select_reply(struct socket * sock)
} }
if (sock->flags & SOCK_FLG_SEL_READ && sock->recv_head) if (sock->flags & SOCK_FLG_SEL_READ && sock->recv_head)
sel |= SEL_RD; sel |= CDEV_OP_RD;
if (sel) if (sel)
sock->flags &= ~(SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_READ | sock->flags &= ~(SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_READ |

View file

@ -146,7 +146,7 @@ static int sr_open(devminor_t minor, int UNUSED(access),
return fd; return fd;
} }
sr_fd->srf_fd= fd; sr_fd->srf_fd= fd;
return i; /* cloned! */ return CDEV_CLONED | i;
} }
static int sr_close(devminor_t minor) 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(sr_fd->srf_flags & susp_flag);
assert(*q_head_ptr); assert(*q_head_ptr);
if (m->mq_req.srr_flags & FLG_OP_NONBLOCK) { if (m->mq_req.srr_flags & CDEV_NONBLOCK) {
mq_free(m); mq_free(m);
return EAGAIN; return EAGAIN;
} }
@ -264,7 +264,7 @@ static int sr_rwio(sr_req_t *req)
(printf("r= %d\n", r), 0)); (printf("r= %d\n", r), 0));
if (r == SUSPEND) { if (r == SUSPEND) {
sr_fd->srf_flags |= susp_flag; 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, r= sr_cancel(m->mq_req.srr_minor, m->mq_req.srr_endpt,
m->mq_req.srr_id); m->mq_req.srr_id);
assert(r == EDONTREPLY); /* head of the queue */ 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; sr_fd->srf_select_proc= endpt;
i_ops= 0; i_ops= 0;
if (ops & SEL_RD) i_ops |= SR_SELECT_READ; if (ops & CDEV_OP_RD) i_ops |= SR_SELECT_READ;
if (ops & SEL_WR) i_ops |= SR_SELECT_WRITE; if (ops & CDEV_OP_WR) i_ops |= SR_SELECT_WRITE;
if (ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION; if (ops & CDEV_OP_ERR) i_ops |= SR_SELECT_EXCEPTION;
if (!(ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL; if (!(ops & CDEV_NOTIFY)) i_ops |= SR_SELECT_POLL;
r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops); r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
if (r < 0) { if (r < 0) {
m_ops= r; m_ops= r;
} else { } else {
m_ops= 0; m_ops= 0;
if (r & SR_SELECT_READ) m_ops |= SEL_RD; if (r & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
if (r & SR_SELECT_WRITE) m_ops |= SEL_WR; if (r & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR; if (r & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
} }
return m_ops; return m_ops;
@ -657,9 +657,9 @@ static void sr_select_res(int fd, unsigned ops)
sr_fd= &sr_fd_table[fd]; sr_fd= &sr_fd_table[fd];
m_ops= 0; m_ops= 0;
if (ops & SR_SELECT_READ) m_ops |= SEL_RD; if (ops & SR_SELECT_READ) m_ops |= CDEV_OP_RD;
if (ops & SR_SELECT_WRITE) m_ops |= SEL_WR; if (ops & SR_SELECT_WRITE) m_ops |= CDEV_OP_WR;
if (ops & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR; if (ops & SR_SELECT_EXCEPTION) m_ops |= CDEV_OP_ERR;
chardriver_reply_select(sr_fd->srf_select_proc, fd, m_ops); chardriver_reply_select(sr_fd->srf_select_proc, fd, m_ops);
} }

View file

@ -76,7 +76,6 @@ static char * dmap_style(int dev_style)
case STYLE_DEV: return "STYLE_DEV"; case STYLE_DEV: return "STYLE_DEV";
case STYLE_TTY: return "STYLE_TTY"; case STYLE_TTY: return "STYLE_TTY";
case STYLE_CTTY: return "STYLE_CTTY"; case STYLE_CTTY: return "STYLE_CTTY";
case STYLE_CLONE: return "STYLE_CLONE";
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }

View file

@ -1082,22 +1082,22 @@ static int tcp_op_select(struct socket * sock, unsigned int sel)
/* in this case any operation would block, no error */ /* in this case any operation would block, no error */
if (sock->flags & SOCK_FLG_OP_PENDING) { if (sock->flags & SOCK_FLG_OP_PENDING) {
debug_tcp_print("SOCK_FLG_OP_PENDING"); debug_tcp_print("SOCK_FLG_OP_PENDING");
if (sel & SEL_NOTIFY) { if (sel & CDEV_NOTIFY) {
if (sel & SEL_RD) { if (sel & CDEV_OP_RD) {
sock->flags |= SOCK_FLG_SEL_READ; sock->flags |= SOCK_FLG_SEL_READ;
debug_tcp_print("monitor read"); debug_tcp_print("monitor read");
} }
if (sel & SEL_WR) { if (sel & CDEV_OP_WR) {
sock->flags |= SOCK_FLG_SEL_WRITE; sock->flags |= SOCK_FLG_SEL_WRITE;
debug_tcp_print("monitor write"); debug_tcp_print("monitor write");
} }
if (sel & SEL_ERR) if (sel & CDEV_OP_ERR)
sock->flags |= SOCK_FLG_SEL_ERROR; sock->flags |= SOCK_FLG_SEL_ERROR;
} }
return 0; return 0;
} }
if (sel & SEL_RD) { if (sel & CDEV_OP_RD) {
/* /*
* If recv_head is not NULL we can either read or accept a * If recv_head is not NULL we can either read or accept a
* connection which is the same for select() * 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->pcb) {
if (sock->recv_head && if (sock->recv_head &&
!(sock->flags & SOCK_FLG_OP_WRITING)) !(sock->flags & SOCK_FLG_OP_WRITING))
retsel |= SEL_RD; retsel |= CDEV_OP_RD;
else if (!(sock->flags & SOCK_FLG_OP_LISTENING) && else if (!(sock->flags & SOCK_FLG_OP_LISTENING) &&
((struct tcp_pcb *) sock->pcb)->state != ESTABLISHED) ((struct tcp_pcb *) sock->pcb)->state != ESTABLISHED)
retsel |= SEL_RD; retsel |= CDEV_OP_RD;
else if (sel & SEL_NOTIFY) { else if (sel & CDEV_NOTIFY) {
sock->flags |= SOCK_FLG_SEL_READ; sock->flags |= SOCK_FLG_SEL_READ;
debug_tcp_print("monitor read"); debug_tcp_print("monitor read");
} }
} else } else /* not connected read does not block */
retsel |= SEL_RD; /* not connected read does not block */ retsel |= CDEV_OP_RD;
} }
if (sel & SEL_WR) { if (sel & CDEV_OP_WR) {
if (sock->pcb) { if (sock->pcb) {
if (((struct tcp_pcb *) sock->pcb)->state == ESTABLISHED) if (((struct tcp_pcb *) sock->pcb)->state == ESTABLISHED)
retsel |= SEL_WR; retsel |= CDEV_OP_WR;
else if (sel & SEL_NOTIFY) { else if (sel & CDEV_NOTIFY) {
sock->flags |= SOCK_FLG_SEL_WRITE; sock->flags |= SOCK_FLG_SEL_WRITE;
debug_tcp_print("monitor write"); debug_tcp_print("monitor write");
} }
} else } else /* not connected write does not block */
retsel |= SEL_WR; /* 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"); debug_tcp_print("read won't block");
} }
if (retsel & SEL_WR) { if (retsel & CDEV_OP_WR) {
debug_tcp_print("write won't block"); debug_tcp_print("write won't block");
} }
/* we only monitor if errors will happen in the future */ /* 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; sock->flags |= SOCK_FLG_SEL_ERROR;
return retsel; return retsel;
@ -1160,7 +1160,7 @@ static int tcp_op_select_reply(struct socket * sock)
(!(sock->flags & SOCK_FLG_OP_LISTENING) && (!(sock->flags & SOCK_FLG_OP_LISTENING) &&
((struct tcp_pcb *) sock->pcb)->state != ((struct tcp_pcb *) sock->pcb)->state !=
ESTABLISHED)) { ESTABLISHED)) {
sel |= SEL_RD; sel |= CDEV_OP_RD;
debug_tcp_print("read won't block"); debug_tcp_print("read won't block");
} }
} }
@ -1169,7 +1169,7 @@ static int tcp_op_select_reply(struct socket * sock)
(sock->pcb == NULL || (sock->pcb == NULL ||
((struct tcp_pcb *) sock->pcb)->state == ((struct tcp_pcb *) sock->pcb)->state ==
ESTABLISHED)) { ESTABLISHED)) {
sel |= SEL_WR; sel |= CDEV_OP_WR;
debug_tcp_print("write won't block"); debug_tcp_print("write won't block");
} }

View file

@ -12,10 +12,9 @@
* *
* Overview * Overview
* *
* The interface to unix domain sockets is similar to the * The interface to unix domain sockets is similar to the interface to network
* the interface to network sockets. There is a character * sockets. There is a character device (/dev/uds) and this server is a
* device (/dev/uds) that uses STYLE_CLONE and this server * 'driver' for that device.
* is a 'driver' for that device.
*/ */
#define DEBUG 0 #define DEBUG 0
@ -190,7 +189,7 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
/* Process the response */ /* Process the response */
uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR; 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) 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; return EINVAL;
} }
watch = (ops & SEL_NOTIFY); watch = (ops & CDEV_NOTIFY);
ops &= (SEL_RD | SEL_WR | SEL_ERR); ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
ready_ops = 0; ready_ops = 0;
/* check if there is data available to read */ /* 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); bytes = uds_perform_read(minor, NONE, GRANT_INVALID, 1, 1);
if (bytes > 0) { if (bytes > 0) {
/* there is data in the pipe for us to read */ /* 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) { } else if (uds_fd_table[minor].listening == 1) {
/* check for pending connections */ /* check for pending connections */
for (i = 0; i < uds_fd_table[minor].backlog_size; i++) for (i = 0; i < uds_fd_table[minor].backlog_size; i++)
{ {
if (uds_fd_table[minor].backlog[i] != -1) { if (uds_fd_table[minor].backlog[i] != -1) {
ready_ops |= SEL_RD; ready_ops |= CDEV_OP_RD;
break; break;
} }
} }
} else if (bytes != SUSPEND) { } else if (bytes != SUSPEND) {
ready_ops |= SEL_RD; ready_ops |= CDEV_OP_RD;
} }
} }
/* check if we can write without blocking */ /* 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, bytes = uds_perform_write(minor, NONE, GRANT_INVALID, PIPE_BUF,
1); 1);
if (bytes != 0 && bytes != SUSPEND) { if (bytes != 0 && bytes != SUSPEND) {
/* There is room to write or there is an error /* There is room to write or there is an error
* condition. * 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 * 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. * 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)){ (uds_fd_table[minor].size+uds_fd_table[minor].pos + 1 < PIPE_BUF)){
/* a write on peer is possible now */ /* a write on peer is possible now */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer, chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
SEL_WR); CDEV_OP_WR);
uds_fd_table[peer].sel_ops &= ~SEL_WR; uds_fd_table[peer].sel_ops &= ~CDEV_OP_WR;
} }
return fs_m_out.RES_NBYTES; /* return number of bytes read */ 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 * data ready to read and it doesn't know about it already, then let
* the peer know we have data for it. * 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 */ /* a read on peer is possible now */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer, chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
SEL_RD); CDEV_OP_RD);
uds_fd_table[peer].sel_ops &= ~SEL_RD; uds_fd_table[peer].sel_ops &= ~CDEV_OP_RD;
} }
return fs_m_out.RES_NBYTES; /* return number of bytes written */ 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; uds_fd_table[minor].susp_id = id;
/* If the call wasn't supposed to block, cancel immediately. */ /* If the call wasn't supposed to block, cancel immediately. */
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
uds_cancel(minor, endpt, id); uds_cancel(minor, endpt, id);
rc = EAGAIN; 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; uds_fd_table[minor].susp_id = id;
/* If the call wasn't supposed to block, cancel immediately. */ /* If the call wasn't supposed to block, cancel immediately. */
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
uds_cancel(minor, endpt, id); uds_cancel(minor, endpt, id);
rc = EAGAIN; 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; uds_fd_table[minor].susp_id = id;
/* If the call wasn't supposed to block, cancel immediately. */ /* If the call wasn't supposed to block, cancel immediately. */
if (flags & FLG_OP_NONBLOCK) { if (flags & CDEV_NONBLOCK) {
uds_cancel(minor, endpt, id); uds_cancel(minor, endpt, id);
rc = EAGAIN; rc = EAGAIN;

View file

@ -42,7 +42,7 @@ int main(int argc, char *argv[])
get_work(&pfs_m_in, &ipc_status); get_work(&pfs_m_in, &ipc_status);
/* If this is a UDS device request, process it and continue. */ /* 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); uds_request(&pfs_m_in, ipc_status);
continue; continue;

View file

@ -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() */ /* 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 /* if the server wants to know about
* data ready to read and it doesn't * data ready to read and it doesn't
* doesn't know about it already, then * 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( chardriver_reply_select(
uds_fd_table[i].sel_endpt, i, 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 */ /* we found our server */

View file

@ -179,7 +179,7 @@ struct uds_fd {
*/ */
endpoint_t sel_endpt; 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; unsigned int sel_ops;
}; };

View file

@ -48,7 +48,7 @@ struct boot_image_dev boot_image_dev_table[] = {
{ TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY }, { TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY },
{ MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV }, { MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV },
{ LOG_PROC_NR, SRV_DF, LOG_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 { DEFAULT_BOOT_NR, SRV_DF, 0, STYLE_NDEV, STYLE_NDEV } /* default
* entry * entry
*/ */

View file

@ -93,7 +93,7 @@ int drv_sendrec(endpoint_t drv_e, message *reqmp)
panic("driver endpoint %d invalid", drv_e); panic("driver endpoint %d invalid", drv_e);
lock_dmap(dp); lock_dmap(dp);
if (dp->dmap_servicing != NONE) if (dp->dmap_servicing != INVALID_THREAD)
panic("driver locking inconsistency"); panic("driver locking inconsistency");
dp->dmap_servicing = self->w_tid; dp->dmap_servicing = self->w_tid;
self->w_task = drv_e; self->w_task = drv_e;
@ -108,7 +108,7 @@ int drv_sendrec(endpoint_t drv_e, message *reqmp)
util_stacktrace(); util_stacktrace();
} }
dp->dmap_servicing = NONE; dp->dmap_servicing = INVALID_THREAD;
self->w_task = NONE; self->w_task = NONE;
self->w_drv_sendrec = NULL; self->w_drv_sendrec = NULL;
unlock_dmap(dp); unlock_dmap(dp);

View file

@ -26,14 +26,7 @@
/* test if the process is blocked on something */ /* test if the process is blocked on something */
#define fp_is_blocked(fp) ((fp)->fp_blocked_on != FP_BLOCKED_ON_NONE) #define fp_is_blocked(fp) ((fp)->fp_blocked_on != FP_BLOCKED_ON_NONE)
/* test if reply is a driver reply */ #define INVALID_THREAD ((thread_t) -1) /* known-invalid thread ID */
#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 SYMLOOP 16 #define SYMLOOP 16
@ -43,4 +36,10 @@
*/ */
#define FSTYPE_MAX VFS_NAMELEN /* maximum file system type size */ #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 #endif

View file

@ -2,24 +2,25 @@
* Special character files also require I/O. The routines for these are here. * Special character files also require I/O. The routines for these are here.
* *
* The entry points in this file are: * The entry points in this file are:
* dev_open: open a character device * cdev_open: open a character device
* dev_close: close a character device * cdev_close: close a character device
* cdev_reply: process the result of a character driver request * cdev_io: initiate a read, write, or ioctl to a character device
* bdev_open: open a block device * cdev_select: initiate a select call on a device
* bdev_close: close a block device * cdev_cancel: cancel an I/O request, blocking until it has been cancelled
* bdev_reply: process the result of a block driver request * cdev_reply: process the result of a character driver request
* dev_io: FS does a read or write on a device * bdev_open: open a block device
* gen_opcl: generic call to a character driver to perform an open/close * bdev_close: close a block device
* gen_io: generic call to a character driver to initiate I/O * bdev_reply: process the result of a block driver request
* no_dev: open/close processing for devices that don't exist * bdev_up: a block driver has been mapped in
* no_dev_io: i/o processing for devices that don't exist * gen_opcl: generic call to a character driver to perform an open/close
* tty_opcl: perform tty-specific processing for open/close * gen_io: generic call to a character driver to initiate I/O
* ctty_opcl: perform controlling-tty-specific processing for open/close * no_dev: open/close processing for devices that don't exist
* ctty_io: perform controlling-tty-specific processing for I/O * no_dev_io: i/o processing for devices that don't exist
* pm_setsid: perform VFS's side of setsid system call * tty_opcl: perform tty-specific processing for open/close
* do_ioctl: perform the IOCTL system call * ctty_opcl: perform controlling-tty-specific processing for open/close
* dev_select: initiate a select call on a device * ctty_io: perform controlling-tty-specific processing for I/O
* dev_cancel: cancel an I/O request, blocking until it has been cancelled * pm_setsid: perform VFS's side of setsid system call
* do_ioctl: perform the IOCTL system call
*/ */
#include "fs.h" #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, static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
void *buf, unsigned long size); void *buf, unsigned long size);
static int dummyproc;
/*===========================================================================* /*===========================================================================*
* dev_open * * cdev_open *
*===========================================================================*/ *===========================================================================*/
int dev_open( int cdev_open(dev_t dev, int flags)
dev_t dev, /* device to open */
int flags /* mode bits and flags */
)
{ {
/* Open a character device. */ /* Open a character device. */
devmajor_t major_dev; devmajor_t major_dev;
@ -65,17 +61,15 @@ int dev_open(
major_dev = major(dev); major_dev = major(dev);
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO); if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
if (dmap[major_dev].dmap_driver == NONE) 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); return(r);
} }
/*===========================================================================* /*===========================================================================*
* dev_close * * cdev_close *
*===========================================================================*/ *===========================================================================*/
int dev_close( int cdev_close(dev_t dev)
dev_t dev /* device to close */
)
{ {
/* Close a character device. */ /* Close a character device. */
devmajor_t major_dev; devmajor_t major_dev;
@ -85,7 +79,7 @@ int dev_close(
major_dev = major(dev); major_dev = major(dev);
if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO); if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO);
if (dmap[major_dev].dmap_driver == NONE) 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); 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 * * 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; size_t size;
switch (op) { switch (op) {
case DEV_READ_S: case CDEV_READ:
case DEV_WRITE_S: case CDEV_WRITE:
gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, 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; break;
case DEV_IOCTL_S: case CDEV_IOCTL:
case BDEV_IOCTL: case BDEV_IOCTL:
/* For IOCTLs, the bytes parameter contains the IOCTL request. /* For IOCTLs, the bytes parameter contains the IOCTL request.
* This request encodes the requested access method and buffer size. * 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 else
size = _MINIX_IOCTL_SIZE(bytes); size = _MINIX_IOCTL_SIZE(bytes);
/* Grant access to the buffer even if no I/O happens with the ioctl, in /* Grant access to the buffer even if no I/O happens with the ioctl,
* order to disambiguate requests with DEV_IOCTL_S. * 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); gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, size, access);
break; 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 cdev_io(
int op, /* DEV_READ_S, DEV_WRITE_S, or DEV_IOCTL_S */ int op, /* CDEV_READ, CDEV_WRITE, or CDEV_IOCTL */
dev_t dev, /* major-minor device number */ dev_t dev, /* major-minor device number */
endpoint_t proc_e, /* in whose address space is buf? */ endpoint_t proc_e, /* in whose address space is buf? */
void *buf, /* virtual address of the buffer */ void *buf, /* virtual address of the buffer */
off_t pos, /* byte position */ 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 */ 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; struct dmap *dp;
message dev_mess; message dev_mess;
cp_grant_id_t gid; cp_grant_id_t gid;
devmajor_t major_dev; devmajor_t major_dev;
devminor_t minor_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. */ /* Determine task dmap. */
major_dev = major(dev); major_dev = major(dev);
@ -307,7 +278,7 @@ int dev_io(
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
if (dp->dmap_driver == NONE) return(ENXIO); 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, printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
dp->dmap_driver); dp->dmap_driver);
return(ENXIO); return(ENXIO);
@ -318,21 +289,21 @@ int dev_io(
/* Set up the rest of the message that will be sent to the driver. */ /* Set up the rest of the message that will be sent to the driver. */
memset(&dev_mess, 0, sizeof(dev_mess)); memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = op; dev_mess.m_type = op;
dev_mess.DEVICE = minor_dev; dev_mess.CDEV_MINOR = minor_dev;
if (op == DEV_IOCTL_S) { if (op == CDEV_IOCTL) {
dev_mess.REQUEST = bytes; dev_mess.CDEV_REQUEST = bytes;
dev_mess.POSITION = proc_e; dev_mess.CDEV_USER = proc_e;
} else { } else {
dev_mess.POSITION = ex64lo(pos); dev_mess.CDEV_POS_LO = ex64lo(pos);
dev_mess.COUNT = bytes; dev_mess.CDEV_POS_HI = ex64hi(pos);
dev_mess.CDEV_COUNT = (size_t) bytes;
} }
dev_mess.HIGHPOS = ex64hi(pos); dev_mess.CDEV_ID = proc_e;
dev_mess.USER_ENDPT = VFS_PROC_NR; dev_mess.CDEV_GRANT = gid;
dev_mess.IO_GRANT = (void *) gid; dev_mess.CDEV_FLAGS = 0;
dev_mess.FLAGS = 0;
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK)
dev_mess.FLAGS |= FLG_OP_NONBLOCK; dev_mess.CDEV_FLAGS |= CDEV_NONBLOCK;
/* Send the request to the driver. */ /* Send the request to the driver. */
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess); r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
@ -347,7 +318,6 @@ int dev_io(
wait_for(dp->dmap_driver); wait_for(dp->dmap_driver);
assert(!GRANT_VALID(fp->fp_grant)); assert(!GRANT_VALID(fp->fp_grant));
fp->fp_grant = gid; /* revoke this when unsuspended. */ fp->fp_grant = gid; /* revoke this when unsuspended. */
fp->fp_ioproc = VFS_PROC_NR;
return SUSPEND; 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, r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
ALL_MODES | I_CHAR_SPECIAL, dev, &res); ALL_MODES | I_CHAR_SPECIAL, dev, &res);
if (r != OK) { if (r != OK) {
(void) gen_opcl(DEV_CLOSE, dev, proc_e, 0); (void) gen_opcl(CDEV_CLOSE, dev, proc_e, 0);
return r; return r;
} }
/* Drop old node and use the new values */ /* Drop old node and use the new values */
if ((vp = get_free_vnode()) == NULL) { if ((vp = get_free_vnode()) == NULL) {
req_putnode(PFS_PROC_NR, res.inode_nr, 1); /* is this right? */ 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); return(err_code);
} }
lock_vnode(vp, VNODE_OPCL); 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 * * gen_opcl *
*===========================================================================*/ *===========================================================================*/
int 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 */ dev_t dev, /* device to open or close */
endpoint_t proc_e, /* process to open/close for */ endpoint_t proc_e, /* process to open/close for */
int flags /* mode bits and flags */ int flags /* mode bits and flags */
@ -417,10 +387,10 @@ int gen_opcl(
{ {
/* Called from the dmap struct on opens & closes of special files.*/ /* Called from the dmap struct on opens & closes of special files.*/
devmajor_t major_dev; devmajor_t major_dev;
devminor_t minor_dev; devminor_t minor_dev, new_minor;
struct dmap *dp; struct dmap *dp;
message dev_mess; message dev_mess;
int r; int r, r2;
/* Determine task dmap. */ /* Determine task dmap. */
major_dev = major(dev); major_dev = major(dev);
@ -435,9 +405,15 @@ int gen_opcl(
memset(&dev_mess, 0, sizeof(dev_mess)); memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = op; dev_mess.m_type = op;
dev_mess.DEVICE = minor_dev; dev_mess.CDEV_MINOR = minor_dev;
dev_mess.USER_ENDPT = proc_e; dev_mess.CDEV_ID = proc_e;
dev_mess.COUNT = flags; 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. */ /* Call the task. */
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess); r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
@ -454,15 +430,33 @@ int gen_opcl(
self->w_task = NONE; self->w_task = NONE;
self->w_drv_sendrec = NULL; 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 the result from the driver. */
return(dev_mess.REP_STATUS); return(r);
} }
/*===========================================================================* /*===========================================================================*
* tty_opcl * * tty_opcl *
*===========================================================================*/ *===========================================================================*/
int 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 */ dev_t dev, /* device to open or close */
endpoint_t proc_e, /* process to open/close for */ endpoint_t proc_e, /* process to open/close for */
int flags /* mode bits and flags */ int flags /* mode bits and flags */
@ -490,7 +484,7 @@ int tty_opcl(
r = gen_opcl(op, dev, proc_e, flags); r = gen_opcl(op, dev, proc_e, flags);
/* Did this call make the tty the controlling tty? */ /* Did this call make the tty the controlling tty? */
if (r == 1) { if (r >= 0 && (r & CDEV_CTTY)) {
fp->fp_tty = dev; fp->fp_tty = dev;
r = OK; r = OK;
} }
@ -503,7 +497,7 @@ int tty_opcl(
* ctty_opcl * * ctty_opcl *
*===========================================================================*/ *===========================================================================*/
int 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 */ dev_t UNUSED(dev), /* device to open or close */
endpoint_t UNUSED(proc_e), /* process to open/close for */ endpoint_t UNUSED(proc_e), /* process to open/close for */
int UNUSED(flags) /* mode bits and flags */ int UNUSED(flags) /* mode bits and flags */
@ -569,8 +563,8 @@ int do_ioctl(message *UNUSED(m_out))
if (S_ISBLK(vp->v_mode)) if (S_ISBLK(vp->v_mode))
r = bdev_ioctl(dev, who_e, ioctlrequest, argx); r = bdev_ioctl(dev, who_e, ioctlrequest, argx);
else else
r = dev_io(DEV_IOCTL_S, dev, who_e, argx, 0, r = cdev_io(CDEV_IOCTL, dev, who_e, argx, 0, ioctlrequest,
ioctlrequest, f->filp_flags); f->filp_flags);
} }
unlock_filp(f); 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. */ /* Initiate a select call on a device. Return OK iff the request was sent. */
devmajor_t major_dev; devmajor_t major_dev;
@ -598,9 +592,9 @@ int dev_select(dev_t dev, int ops)
memset(&dev_mess, 0, sizeof(dev_mess)); memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = DEV_SELECT; dev_mess.m_type = CDEV_SELECT;
dev_mess.DEV_MINOR = minor_dev; dev_mess.CDEV_MINOR = minor_dev;
dev_mess.DEV_SEL_OPS = ops; dev_mess.CDEV_OPS = ops;
/* Call the task. */ /* Call the task. */
return (*dp->dmap_io)(dp->dmap_driver, &dev_mess); 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. */ /* Cancel an I/O request, blocking until it has been cancelled. */
devmajor_t major_dev; devmajor_t major_dev;
@ -625,14 +619,9 @@ int dev_cancel(dev_t dev)
memset(&dev_mess, 0, sizeof(dev_mess)); memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = CANCEL; dev_mess.m_type = CDEV_CANCEL;
dev_mess.DEVICE = minor_dev; dev_mess.CDEV_MINOR = minor_dev;
dev_mess.USER_ENDPT = fp->fp_ioproc; dev_mess.CDEV_ID = fp->fp_endpoint;
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;
r = (*dp->dmap_io)(fp->fp_task, &dev_mess); r = (*dp->dmap_io)(fp->fp_task, &dev_mess);
if (r != OK) return r; /* ctty_io returned an error? should be impossible */ 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; fp->fp_grant = GRANT_INVALID;
} }
r = dev_mess.REP_STATUS; r = dev_mess.CDEV_STATUS;
return (r == EAGAIN) ? EINTR : r; 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); if (r != OK) panic("VFS: asynsend in gen_io failed: %d", r);
/* Fake a SUSPEND */
mess_ptr->REP_STATUS = SUSPEND;
return(OK); return(OK);
} }
@ -740,6 +727,7 @@ int ctty_io(
* major/minor pair for /dev/tty itself. * major/minor pair for /dev/tty itself.
*/ */
struct dmap *dp; struct dmap *dp;
int slot;
if (fp->fp_tty == 0) { if (fp->fp_tty == 0) {
/* No controlling tty present anymore, return an I/O error. */ /* No controlling tty present anymore, return an I/O error. */
@ -747,14 +735,14 @@ int ctty_io(
} else { } else {
/* Substitute the controlling terminal device. */ /* Substitute the controlling terminal device. */
dp = &dmap[major(fp->fp_tty)]; 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) { if (dp->dmap_driver == NONE) {
printf("FS: ctty_io: no driver for dev\n"); printf("FS: ctty_io: no driver for dev\n");
return(EIO); 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); printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
return(EIO); return(EIO);
} }
@ -768,7 +756,7 @@ int ctty_io(
* no_dev * * no_dev *
*===========================================================================*/ *===========================================================================*/
int 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 */ dev_t UNUSED(dev), /* device to open or close */
endpoint_t UNUSED(proc), /* process to open/close for */ endpoint_t UNUSED(proc), /* process to open/close for */
int UNUSED(flags) /* mode bits and flags */ int UNUSED(flags) /* mode bits and flags */
@ -788,35 +776,6 @@ int no_dev_io(endpoint_t UNUSED(proc), message *UNUSED(m))
return(EIO); 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 * * 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 /* A character driver has results for an open, close, read, write, or ioctl
* MUST NOT block its calling thread. * 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 fproc *rfp;
struct worker_thread *wp; struct worker_thread *wp;
endpoint_t proc_e; endpoint_t proc_e;
int slot; int slot;
proc_e = m_ptr->REP_ENDPT; proc_e = m_ptr->CDEV_ID;
if (isokendpt(proc_e, &slot) != OK) return;
rfp = &fproc[slot]; if (m_ptr->CDEV_STATUS == SUSPEND) {
wp = rfp->fp_worker; printf("VFS: got SUSPEND from %d, not reviving\n", m_ptr->m_source);
if (wp == NULL || wp->w_task != who_e) {
printf("VFS: no worker thread waiting for a reply from %d\n", who_e);
return; return;
} }
*wp->w_drv_sendrec = *m_ptr;
worker_signal(wp); /* Continue open/close */
}
if (isokendpt(proc_e, &slot) != OK) {
/*===========================================================================* printf("VFS: proc %d from %d not found\n", proc_e, m_ptr->m_source);
* task_reply * return;
*===========================================================================*/ }
static void task_reply(message *m_ptr) rfp = &fproc[slot];
{ wp = rfp->fp_worker;
/* A character driver has results for a read, write, or ioctl call. There may if (wp != NULL && wp->w_task == who_e) {
* be a thread waiting for these results as part of an ongoing dev_cancel call. assert(!fp_is_blocked(rfp));
* If so, wake up that thread; if not, send a reply to the requesting process. *wp->w_drv_sendrec = *m_ptr;
* This function MUST NOT block its calling thread. worker_signal(wp); /* Continue open/close/cancel */
*/ } else if (rfp->fp_blocked_on != FP_BLOCKED_ON_OTHER ||
struct fproc *rfp; rfp->fp_task != m_ptr->m_source) {
struct worker_thread *wp; /* This would typically be caused by a protocol error, i.e. a driver
endpoint_t proc_e; * not properly following the character driver protocol rules.
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) return; printf("VFS: proc %d not blocked on %d\n", proc_e, m_ptr->m_source);
rfp = &fproc[slot]; } else {
wp = rfp->fp_worker; revive(proc_e, m_ptr->CDEV_STATUS);
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);
}
} }
} }
@ -960,15 +891,20 @@ void cdev_reply(void)
{ {
/* A character driver has results for us. */ /* 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) { switch (call_nr) {
case DEV_OPEN_REPL: case CDEV_REPLY:
case DEV_CLOSE_REPL: opcl_reply(&m_in); break; cdev_generic_reply(&m_in);
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);
break; break;
case DEV_SEL_REPL2: case CDEV_SEL1_REPLY:
select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS); 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; break;
default: default:
printf("VFS: char driver %u sent unknown reply %x\n", who_e, call_nr); printf("VFS: char driver %u sent unknown reply %x\n", who_e, call_nr);
@ -979,15 +915,24 @@ void cdev_reply(void)
/*===========================================================================* /*===========================================================================*
* bdev_reply * * 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 /* 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. * these results - wake it up. This function MUST NOT block its calling thread.
*/ */
struct worker_thread *wp; struct worker_thread *wp;
struct dmap *dp;
assert(dp != NULL); if ((dp = get_dmap(who_e)) == NULL) {
assert(dp->dmap_servicing != NONE); 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); wp = worker_get(dp->dmap_servicing);
if (wp == NULL || wp->w_task != who_e) { if (wp == NULL || wp->w_task != who_e) {

View file

@ -182,9 +182,6 @@ int flags; /* device flags */
dp->dmap_opcl = ctty_opcl; dp->dmap_opcl = ctty_opcl;
dp->dmap_io = ctty_io; dp->dmap_io = ctty_io;
break; break;
case STYLE_CLONE:
dp->dmap_opcl = clone_opcl;
dp->dmap_io = gen_io;
break; break;
default: default:
return(EINVAL); return(EINVAL);
@ -281,7 +278,7 @@ void init_dmap()
dmap[i].dmap_io = no_dev_io; dmap[i].dmap_io = no_dev_io;
dmap[i].dmap_driver = NONE; dmap[i].dmap_driver = NONE;
dmap[i].dmap_style = STYLE_NDEV; 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) { if (dp->dmap_recovering) {
printf("VFS: driver recovery failure for" printf("VFS: driver recovery failure for"
" major %d\n", major); " major %d\n", major);
if (dp->dmap_servicing != NONE) { if (dp->dmap_servicing != INVALID_THREAD) {
worker = worker_get(dp->dmap_servicing); worker = worker_get(dp->dmap_servicing);
worker_stop(worker); worker_stop(worker);
} }
@ -355,7 +352,7 @@ void dmap_endpt_up(endpoint_t proc_e, int is_blk)
bdev_up(major); bdev_up(major);
dp->dmap_recovering = 0; dp->dmap_recovering = 0;
} else { } else {
if (dp->dmap_servicing != NONE) { if (dp->dmap_servicing != INVALID_THREAD) {
worker = worker_get(dp->dmap_servicing); worker = worker_get(dp->dmap_servicing);
worker_stop(worker); worker_stop(worker);
} }

View file

@ -22,7 +22,7 @@ extern struct dmap {
int dmap_style; int dmap_style;
int dmap_sel_busy; int dmap_sel_busy;
struct filp *dmap_sel_filp; struct filp *dmap_sel_filp;
endpoint_t dmap_servicing; thread_t dmap_servicing;
mutex_t dmap_lock; mutex_t dmap_lock;
mutex_t *dmap_lock_ref; mutex_t *dmap_lock_ref;
int dmap_recovering; int dmap_recovering;

View file

@ -579,7 +579,7 @@ struct filp *f;
(void) bdev_close(dev); /* Ignore errors */ (void) bdev_close(dev); /* Ignore errors */
} else { } else {
(void) dev_close(dev); /* Ignore errors */ (void) cdev_close(dev); /* Ignore errors */
} }
f->filp_mode = FILP_CLOSED; f->filp_mode = FILP_CLOSED;

View file

@ -29,8 +29,6 @@ EXTERN struct fproc {
int fp_block_callnr; /* blocked call if rd/wr can't finish */ 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 */ 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_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 */ cp_grant_id_t fp_grant; /* revoke this grant on unsuspend if > -1 */
uid_t fp_realuid; /* real user id */ uid_t fp_realuid; /* real user id */

View file

@ -124,36 +124,14 @@ int main(void)
continue; continue;
} }
/* At this point we either have results from an asynchronous device if (IS_BDEV_RS(call_nr)) {
* or a new system call. In both cases a new worker thread has to be /* We've got results for a block device request. */
* started and there might not be one available from the pool. This is bdev_reply();
* not a problem (requests/replies are simply queued), except when } else if (IS_CDEV_RS(call_nr)) {
* they're from an FS endpoint, because these can cause a deadlock. /* We've got results for a character device request. */
* handle_work() takes care of the details. */ cdev_reply();
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);
} else { } else {
/* Normal syscall. */ /* Normal syscall. This spawns a new thread. */
handle_work(do_work); handle_work(do_work);
} }
} }

View file

@ -659,7 +659,7 @@ static void free_proc(int flags)
if (!S_ISCHR(vp->v_mode)) continue; if (!S_ISCHR(vp->v_mode)) continue;
if ((dev_t) vp->v_sdev != dev) continue; if ((dev_t) vp->v_sdev != dev) continue;
lock_filp(rfilp, VNODE_READ); lock_filp(rfilp, VNODE_READ);
(void) dev_close(dev); /* Ignore any errors. */ (void) cdev_close(dev); /* Ignore any errors. */
rfilp->filp_mode = FILP_CLOSED; rfilp->filp_mode = FILP_CLOSED;
unlock_filp(rfilp); unlock_filp(rfilp);

View file

@ -156,9 +156,9 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
/* Invoke the driver for special processing. */ /* Invoke the driver for special processing. */
dev = (dev_t) vp->v_sdev; dev = (dev_t) vp->v_sdev;
/* TTY needs to know about the O_NOCTTY flag. */ /* 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 vp = filp->filp_vno; /* Might be updated by
* dev_open/clone_opcl */ * cdev_open after cloning */
break; break;
case S_IFBLK: case S_IFBLK:

View file

@ -527,7 +527,7 @@ void unpause(void)
blocked_on = fp->fp_blocked_on; blocked_on = fp->fp_blocked_on;
/* Clear the block status now. The procedure below might make blocking calls /* 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. * parts of VFS do not perceive this process as blocked on something.
*/ */
fp->fp_blocked_on = FP_BLOCKED_ON_NONE; 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 */ dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */
status = dev_cancel(dev); status = cdev_cancel(dev);
break; break;
default : default :

View file

@ -29,14 +29,17 @@ void fs_sendmore(struct vmnt *vmp);
void send_work(void); void send_work(void);
/* device.c */ /* device.c */
int dev_open(dev_t dev, int flags); int cdev_open(dev_t dev, int flags);
int dev_close(dev_t dev); 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); void cdev_reply(void);
int bdev_open(dev_t dev, int access); int bdev_open(dev_t dev, int access);
int bdev_close(dev_t dev); int bdev_close(dev_t dev);
void bdev_reply(struct dmap *dp); void bdev_reply(void);
int dev_io(int op, dev_t dev, endpoint_t proc_e, void *buf, off_t pos, void bdev_up(int major);
size_t bytes, int flags);
int gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags); 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 gen_io(endpoint_t drv_e, message *mess_ptr);
int no_dev(int op, dev_t dev, endpoint_t proc, int flags); 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 clone_opcl(int op, dev_t dev, endpoint_t proc, int flags);
int ctty_io(endpoint_t task_nr, message *mess_ptr); int ctty_io(endpoint_t task_nr, message *mess_ptr);
int do_ioctl(message *m_out); 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 pm_setsid(endpoint_t proc_e);
void bdev_up(int major);
/* dmap.c */ /* dmap.c */
void lock_dmap(struct dmap *dp); void lock_dmap(struct dmap *dp);

View file

@ -137,6 +137,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
off_t position, res_pos; off_t position, res_pos;
unsigned int cum_io, cum_io_incr, res_cum_io; unsigned int cum_io, cum_io_incr, res_cum_io;
int op, r; int op, r;
dev_t dev;
position = f->filp_pos; position = f->filp_pos;
vp = f->filp_vno; 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); 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 (S_ISFIFO(vp->v_mode)) { /* Pipes */
if (rfp->fp_cum_io_partial != 0) { 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); r = rw_pipe(rw_flag, for_e, f, buf, size);
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */ } 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) { if(rw_flag == PEEKING) {
printf("read_write: peek on char device makes no sense\n"); printf("read_write: peek on char device makes no sense\n");
return EINVAL; return EINVAL;
@ -172,7 +170,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
dev = (dev_t) vp->v_sdev; 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) { if (r >= 0) {
/* This should no longer happen: all calls are asynchronous. */ /* This should no longer happen: all calls are asynchronous. */
printf("VFS: I/O to device %x succeeded immediately!?\n", dev); printf("VFS: I/O to device %x succeeded immediately!?\n", dev);

View file

@ -406,7 +406,7 @@ static int select_request_char(struct filp *f, int *ops, int block)
return(SUSPEND); return(SUSPEND);
f->filp_select_flags &= ~FSF_UPDATE; 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) if (r != OK)
return(r); return(r);
@ -719,7 +719,7 @@ void select_timeout_check(timer_t *timer)
if (se->requestor == NULL) return; if (se->requestor == NULL) return;
if (se->expiry <= 0) return; /* Strange, did we even ask for a timeout? */ if (se->expiry <= 0) return; /* Strange, did we even ask for a timeout? */
se->expiry = 0; 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); select_return(se);
} }
@ -771,7 +771,7 @@ endpoint_t driver_e;
int minor; int minor;
int status; 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. * block its calling thread.
*/ */
int major; int major;
@ -788,7 +788,7 @@ int status;
/* Get filp belonging to character special file */ /* Get filp belonging to character special file */
if (!dp->dmap_sel_busy) { 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); __FILE__, __LINE__, major);
return; return;
} }

View file

@ -75,13 +75,4 @@ int select(int, fd_set * __restrict, fd_set * __restrict,
__END_DECLS __END_DECLS
#endif /* _KERNEL */ #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_ */ #endif /* !_SYS_SELECT_H_ */