Rewrite character driver protocol
As a side effect, remove the clone style, as the normal device style supports device cloning now. Change-Id: Ie82d1ef0385514a04a8faa139129a617895780b5
This commit is contained in:
parent
87337273e4
commit
665198b4c2
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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:
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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 :
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
Loading…
Reference in a new issue