. Safe I/O, ioctl() and DIAGNOSTICS variants conversion - safe copies,
include grant id in DEV_REVIVE messages. . Removal of TTY_FLAGS field (and so O_NONBLOCK support). . Fixed CANCEL behaviour and return code on blocking I/O, previously handled by O_NONBLOCK . Totally removed REVIVE replies, previously still possible on blocking ioctls (REVIVE directly called) and ptys (missing TTY_REVIVE check), removes deadlock bug with FS . Removed obsolete *COMPAT options and associated code
This commit is contained in:
parent
9fa06d5e3f
commit
1c8b206a5d
@ -14,7 +14,7 @@ MAKE = exec make
|
||||
CC = exec cc
|
||||
CFLAGS = -I$i
|
||||
LDFLAGS = -i
|
||||
LIBS = -lsys -lsysutil -ltimers
|
||||
LIBS = -lsysutil -lsys -ltimers
|
||||
|
||||
OBJ = tty.o console.o vidcopy.o keyboard.o pty.o rs232.o
|
||||
|
||||
|
||||
@ -167,13 +167,20 @@ int try;
|
||||
*/
|
||||
do {
|
||||
if (count > sizeof(buf)) count = sizeof(buf);
|
||||
if ((result = sys_vircopy(tp->tty_outproc, D, tp->tty_out_vir,
|
||||
if(tp->tty_out_safe) {
|
||||
if ((result = sys_safecopyfrom(tp->tty_outproc, tp->tty_out_vir_g,
|
||||
tp->tty_out_vir_offset, (vir_bytes) buf, count, D)) != OK)
|
||||
break;
|
||||
tp->tty_out_vir_offset += count;
|
||||
} else {
|
||||
if ((result = sys_vircopy(tp->tty_outproc, D, tp->tty_out_vir_g,
|
||||
SELF, D, (vir_bytes) buf, (vir_bytes) count)) != OK)
|
||||
break;
|
||||
tp->tty_out_vir_g += count;
|
||||
}
|
||||
tbuf = buf;
|
||||
|
||||
/* Update terminal data structure. */
|
||||
tp->tty_out_vir += count;
|
||||
tp->tty_outcum += count;
|
||||
tp->tty_outleft -= count;
|
||||
|
||||
@ -777,7 +784,7 @@ PRIVATE void beep()
|
||||
*===========================================================================*/
|
||||
PUBLIC void do_video(message *m)
|
||||
{
|
||||
int i, n, r, ops, watch;
|
||||
int i, n, r, ops, watch, safe = 0;
|
||||
unsigned char c;
|
||||
|
||||
/* Execute the requested device driver function. */
|
||||
@ -790,6 +797,9 @@ PUBLIC void do_video(message *m)
|
||||
case DEV_CLOSE:
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_IOCTL_S:
|
||||
safe=1;
|
||||
/* Fallthrough. */
|
||||
case DEV_IOCTL:
|
||||
if (m->TTY_REQUEST == MIOCMAP || m->TTY_REQUEST == MIOCUNMAP)
|
||||
{
|
||||
@ -799,18 +809,30 @@ PUBLIC void do_video(message *m)
|
||||
do_map= (m->REQUEST == MIOCMAP); /* else unmap */
|
||||
|
||||
/* Get request structure */
|
||||
r= sys_vircopy(m->IO_ENDPT, D,
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(m->IO_ENDPT,
|
||||
(vir_bytes)m->ADDRESS, 0, (vir_bytes) &mapreq,
|
||||
sizeof(mapreq), D);
|
||||
} else {
|
||||
r= sys_vircopy(m->IO_ENDPT, D,
|
||||
(vir_bytes)m->ADDRESS,
|
||||
SELF, D, (vir_bytes)&mapreq, sizeof(mapreq));
|
||||
}
|
||||
if (r != OK)
|
||||
{
|
||||
tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT,
|
||||
r);
|
||||
return;
|
||||
}
|
||||
r= sys_vm_map(m->IO_ENDPT, do_map,
|
||||
(phys_bytes)mapreq.base, mapreq.size,
|
||||
mapreq.offset);
|
||||
|
||||
/* In safe ioctl mode, the POSITION field contains
|
||||
* the endpt number of the original requestor.
|
||||
* IO_ENDPT is always FS.
|
||||
*/
|
||||
|
||||
r= sys_vm_map(safe ? m->POSITION : m->IO_ENDPT,
|
||||
do_map, (phys_bytes)mapreq.base, mapreq.size,
|
||||
mapreq.offset);
|
||||
tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
|
||||
return;
|
||||
}
|
||||
@ -1057,20 +1079,27 @@ message *m;
|
||||
/*===========================================================================*
|
||||
* do_diagnostics *
|
||||
*===========================================================================*/
|
||||
PUBLIC void do_diagnostics(m_ptr)
|
||||
PUBLIC void do_diagnostics(m_ptr, safe)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
int safe;
|
||||
{
|
||||
/* Print a string for a server. */
|
||||
char c;
|
||||
vir_bytes src;
|
||||
int count;
|
||||
int count, offset = 0;
|
||||
int result = OK;
|
||||
int proc_nr = m_ptr->DIAG_ENDPT;
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
int proc_nr = m_ptr->m_source;
|
||||
|
||||
src = (vir_bytes) m_ptr->DIAG_PRINT_BUF;
|
||||
src = (vir_bytes) m_ptr->DIAG_PRINT_BUF_G;
|
||||
for (count = m_ptr->DIAG_BUF_COUNT; count > 0; count--) {
|
||||
if (sys_vircopy(proc_nr, D, src++, SELF, D, (vir_bytes) &c, 1) != OK) {
|
||||
int r;
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(proc_nr, src, offset, (vir_bytes) &c, 1, D);
|
||||
} else {
|
||||
r = sys_vircopy(proc_nr, D, src+offset, SELF, D, (vir_bytes) &c, 1);
|
||||
}
|
||||
offset++;
|
||||
if(r != OK) {
|
||||
result = EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -110,7 +110,9 @@ PRIVATE struct kbd
|
||||
int avail;
|
||||
int req_size;
|
||||
int req_proc;
|
||||
vir_bytes req_addr;
|
||||
int req_safe; /* nonzero: safe (req_addr_g is grant) */
|
||||
vir_bytes req_addr_g; /* Virtual address or grant */
|
||||
vir_bytes req_addr_offset;
|
||||
int incaller;
|
||||
int select_ops;
|
||||
int select_proc;
|
||||
@ -188,7 +190,7 @@ PRIVATE void handle_req(kbdp, m)
|
||||
struct kbd *kbdp;
|
||||
message *m;
|
||||
{
|
||||
int i, n, r, ops, watch;
|
||||
int i, n, r, ops, watch, safecopy = 0;
|
||||
unsigned char c;
|
||||
|
||||
/* Execute the requested device driver function. */
|
||||
@ -209,6 +211,9 @@ message *m;
|
||||
kbdp->avail= 0;
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_READ_S:
|
||||
safecopy = 1;
|
||||
/* Fallthrough. */
|
||||
case DEV_READ:
|
||||
if (kbdp->req_size)
|
||||
{
|
||||
@ -221,7 +226,9 @@ message *m;
|
||||
/* Should record proc */
|
||||
kbdp->req_size= m->COUNT;
|
||||
kbdp->req_proc= m->IO_ENDPT;
|
||||
kbdp->req_addr= (vir_bytes)m->ADDRESS;
|
||||
kbdp->req_addr_g= (vir_bytes)m->ADDRESS;
|
||||
kbdp->req_addr_offset= 0;
|
||||
kbdp->req_safe= safecopy;
|
||||
kbdp->incaller= m->m_source;
|
||||
r= SUSPEND;
|
||||
break;
|
||||
@ -235,17 +242,27 @@ message *m;
|
||||
n= KBD_BUFSZ-kbdp->offset;
|
||||
if (n <= 0)
|
||||
panic("TTY", "do_kbd(READ): bad n", n);
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
|
||||
if(safecopy) {
|
||||
r= sys_safecopyto(m->IO_ENDPT, (vir_bytes) m->ADDRESS, 0,
|
||||
(vir_bytes) &kbdp->buf[kbdp->offset], n, D);
|
||||
} else {
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
|
||||
m->IO_ENDPT, D, (vir_bytes) m->ADDRESS, n);
|
||||
}
|
||||
if (r == OK)
|
||||
{
|
||||
kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r= n;
|
||||
} else {
|
||||
printf("copy in read kbd failed: %d\n", r);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DEV_WRITE_S:
|
||||
safecopy = 1;
|
||||
/* Fallthrough. */
|
||||
case DEV_WRITE:
|
||||
if (kbdp != &kbdaux)
|
||||
{
|
||||
@ -260,8 +277,14 @@ message *m;
|
||||
*/
|
||||
for (i= 0; i<m->COUNT; i++)
|
||||
{
|
||||
r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS+i,
|
||||
if(safecopy) {
|
||||
r= sys_safecopyfrom(m->IO_ENDPT, (vir_bytes)
|
||||
m->ADDRESS, i, (vir_bytes)&c, 1, D);
|
||||
} else {
|
||||
r= sys_vircopy(m->IO_ENDPT, D,
|
||||
(vir_bytes) m->ADDRESS+i,
|
||||
SELF, D, (vir_bytes)&c, 1);
|
||||
}
|
||||
if (r != OK)
|
||||
break;
|
||||
kbc_cmd1(KBC_WRITE_AUX, c);
|
||||
@ -290,14 +313,24 @@ message *m;
|
||||
kbdp->select_proc= m->m_source;
|
||||
}
|
||||
break;
|
||||
case DEV_IOCTL_S:
|
||||
safecopy=1;
|
||||
/* Fallthrough. */
|
||||
case DEV_IOCTL:
|
||||
if (kbdp == &kbd && m->TTY_REQUEST == KIOCSLEDS)
|
||||
{
|
||||
kio_leds_t leds;
|
||||
unsigned char b;
|
||||
|
||||
r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
|
||||
if(safecopy) {
|
||||
r= sys_safecopyfrom(m->IO_ENDPT, (vir_bytes)
|
||||
m->ADDRESS, 0, (vir_bytes)&leds,
|
||||
sizeof(leds), D);
|
||||
} else {
|
||||
r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
SELF, D, (vir_bytes)&leds, sizeof(leds));
|
||||
}
|
||||
if (r != OK)
|
||||
break;
|
||||
b= 0;
|
||||
@ -330,8 +363,14 @@ message *m;
|
||||
kio_bell_t bell;
|
||||
clock_t ticks;
|
||||
|
||||
r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
if(safecopy) {
|
||||
r= sys_safecopyfrom(m->IO_ENDPT, (vir_bytes)
|
||||
m->ADDRESS, 0, (vir_bytes)&bell,
|
||||
sizeof(bell), D);
|
||||
} else {
|
||||
r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
SELF, D, (vir_bytes)&bell, sizeof(bell));
|
||||
}
|
||||
if (r != OK)
|
||||
break;
|
||||
|
||||
@ -376,17 +415,23 @@ message *m;
|
||||
if (n <= 0)
|
||||
panic("TTY", "kbd_status: bad n", n);
|
||||
kbdp->req_size= 0;
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
|
||||
kbdp->req_proc, D, kbdp->req_addr, n);
|
||||
if(kbdp->req_safe) {
|
||||
r= sys_safecopyto(kbdp->req_proc, kbdp->req_addr_g, 0,
|
||||
(vir_bytes)&kbdp->buf[kbdp->offset], n, D);
|
||||
} else {
|
||||
r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
|
||||
kbdp->req_proc, D, kbdp->req_addr_g, n);
|
||||
}
|
||||
if (r == OK)
|
||||
{
|
||||
kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r= n;
|
||||
}
|
||||
} else printf("copy in revive kbd failed: %d\n", r);
|
||||
|
||||
m->m_type = DEV_REVIVE;
|
||||
m->REP_ENDPT= kbdp->req_proc;
|
||||
m->REP_IO_GRANT= kbdp->req_addr_g;
|
||||
m->REP_STATUS= r;
|
||||
return 1;
|
||||
}
|
||||
@ -472,15 +517,18 @@ message *m_ptr;
|
||||
/* raw scan codes or aux data */
|
||||
if (kbdp->avail >= KBD_BUFSZ)
|
||||
{
|
||||
#if 0
|
||||
printf("kbd_interrupt: %s buffer is full\n",
|
||||
isaux ? "kbdaux" : "keyboard");
|
||||
#endif
|
||||
return; /* Buffer is full */
|
||||
}
|
||||
o= (kbdp->offset + kbdp->avail) % KBD_BUFSZ;
|
||||
kbdp->buf[o]= scode;
|
||||
kbdp->avail++;
|
||||
if (kbdp->req_size)
|
||||
if (kbdp->req_size) {
|
||||
notify(kbdp->incaller);
|
||||
}
|
||||
if (kbdp->select_ops & SEL_RD)
|
||||
notify(kbdp->select_proc);
|
||||
return;
|
||||
@ -583,14 +631,18 @@ PRIVATE void kbd_send()
|
||||
if (kbdout.expect_ack)
|
||||
return;
|
||||
|
||||
sys_inb(KB_STATUS, &sb);
|
||||
if((r=sys_inb(KB_STATUS, &sb)) != OK) {
|
||||
printf("kbd_send: 1 sys_inb() failed: %d\n", r);
|
||||
}
|
||||
if (sb & (KB_OUT_FULL|KB_IN_FULL))
|
||||
{
|
||||
printf("not sending 1: sb = 0x%x\n", sb);
|
||||
return;
|
||||
}
|
||||
micro_delay(KBC_IN_DELAY);
|
||||
sys_inb(KB_STATUS, &sb);
|
||||
if((r=sys_inb(KB_STATUS, &sb)) != OK) {
|
||||
printf("kbd_send: 2 sys_inb() failed: %d\n", r);
|
||||
}
|
||||
if (sb & (KB_OUT_FULL|KB_IN_FULL))
|
||||
{
|
||||
printf("not sending 2: sb = 0x%x\n", sb);
|
||||
@ -601,7 +653,9 @@ PRIVATE void kbd_send()
|
||||
#if 0
|
||||
printf("sending byte 0x%x to keyboard\n", kbdout.buf[kbdout.offset]);
|
||||
#endif
|
||||
sys_outb(KEYBD, kbdout.buf[kbdout.offset]);
|
||||
if((r=sys_outb(KEYBD, kbdout.buf[kbdout.offset])) != OK) {
|
||||
printf("kbd_send: 3 sys_inb() failed: %d\n", r);
|
||||
}
|
||||
kbdout.offset++;
|
||||
kbdout.avail--;
|
||||
kbdout.expect_ack= 1;
|
||||
@ -734,7 +788,8 @@ PRIVATE void kbc_cmd0(cmd)
|
||||
int cmd;
|
||||
{
|
||||
kb_wait();
|
||||
sys_outb(KB_COMMAND, cmd);
|
||||
if(sys_outb(KB_COMMAND, cmd) != OK)
|
||||
printf("kbc_cmd0: sys_outb failed\n");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
@ -745,9 +800,11 @@ int cmd;
|
||||
int data;
|
||||
{
|
||||
kb_wait();
|
||||
sys_outb(KB_COMMAND, cmd);
|
||||
if(sys_outb(KB_COMMAND, cmd) != OK)
|
||||
printf("kbc_cmd1: 1 sys_outb failed\n");
|
||||
kb_wait();
|
||||
sys_outb(KEYBD, data);
|
||||
if(sys_outb(KEYBD, data) != OK)
|
||||
printf("kbc_cmd1: 2 sys_outb failed\n");
|
||||
}
|
||||
|
||||
|
||||
@ -775,11 +832,13 @@ PRIVATE int kbc_read()
|
||||
do
|
||||
#endif
|
||||
{
|
||||
sys_inb(KB_STATUS, &st);
|
||||
if(sys_inb(KB_STATUS, &st) != OK)
|
||||
printf("kbc_read: 1 sys_inb failed\n");
|
||||
if (st & KB_OUT_FULL)
|
||||
{
|
||||
micro_delay(KBC_IN_DELAY);
|
||||
sys_inb(KEYBD, &byte);
|
||||
if(sys_inb(KEYBD, &byte) != OK)
|
||||
printf("kbc_read: 2 sys_inb failed\n");
|
||||
if (st & KB_AUX_BYTE)
|
||||
{
|
||||
#if DEBUG
|
||||
@ -819,6 +878,8 @@ PRIVATE int kb_wait()
|
||||
retries = MAX_KB_BUSY_RETRIES + 1; /* wait until not busy */
|
||||
do {
|
||||
s = sys_inb(KB_STATUS, &status);
|
||||
if(s != OK)
|
||||
printf("kb_wait: sys_inb failed: %d\n", s);
|
||||
if (status & KB_OUT_FULL) {
|
||||
if (scan_keyboard(&byte, &isaux))
|
||||
{
|
||||
@ -847,6 +908,8 @@ PRIVATE int kb_ack()
|
||||
retries = MAX_KB_ACK_RETRIES + 1;
|
||||
do {
|
||||
s = sys_inb(KEYBD, &u8val);
|
||||
if(s != OK)
|
||||
printf("kb_ack: sys_inb failed: %d\n", s);
|
||||
if (u8val == KB_ACK)
|
||||
break; /* wait for ack */
|
||||
} while(--retries != 0); /* continue unless timeout */
|
||||
@ -925,14 +988,20 @@ PUBLIC void kb_init_once(void)
|
||||
/*===========================================================================*
|
||||
* kbd_loadmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int kbd_loadmap(m)
|
||||
PUBLIC int kbd_loadmap(m, safe)
|
||||
message *m;
|
||||
int safe;
|
||||
{
|
||||
/* Load a new keymap. */
|
||||
int result;
|
||||
result = sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
if(safe) {
|
||||
result = sys_safecopyfrom(m->IO_ENDPT, (vir_bytes) m->ADDRESS,
|
||||
0, (vir_bytes) keymap, (vir_bytes) sizeof(keymap), D);
|
||||
} else {
|
||||
result = sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
|
||||
SELF, D, (vir_bytes) keymap,
|
||||
(vir_bytes) sizeof(keymap));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
@ -1137,30 +1206,35 @@ int *isauxp;
|
||||
|
||||
byte_in[0].port = KEYBD; /* get the scan code for the key struck */
|
||||
byte_in[1].port = PORT_B; /* strobe the keyboard to ack the char */
|
||||
sys_vinb(byte_in, 2); /* request actual input */
|
||||
if(sys_vinb(byte_in, 2) != OK) /* request actual input */
|
||||
printf("scan_keyboard: sys_vinb failed\n");
|
||||
|
||||
pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
|
||||
pv_set(byte_out[1], PORT_B, byte_in[1].value); /* then strobe low */
|
||||
sys_voutb(byte_out, 2); /* request actual output */
|
||||
if(sys_voutb(byte_out, 2) != OK) /* request actual output */
|
||||
printf("scan_keyboard: sys_voutb failed\n");
|
||||
|
||||
return(byte_in[0].value); /* return scan code */
|
||||
#else
|
||||
unsigned long b, sb;
|
||||
|
||||
sys_inb(KB_STATUS, &sb);
|
||||
if(sys_inb(KB_STATUS, &sb) != OK)
|
||||
printf("scan_keyboard: sys_inb failed\n");
|
||||
|
||||
if (!(sb & KB_OUT_FULL))
|
||||
{
|
||||
if (kbdout.avail && !kbdout.expect_ack)
|
||||
kbd_send();
|
||||
return 0;
|
||||
}
|
||||
sys_inb(KEYBD, &b);
|
||||
if(sys_inb(KEYBD, &b) != OK)
|
||||
printf("scan_keyboard: 2 sys_inb failed\n");
|
||||
#if 0
|
||||
printf("got byte 0x%x from %s\n", b, (sb & KB_AUX_BYTE) ? "AUX" : "keyboard");
|
||||
#endif
|
||||
if (!(sb & KB_AUX_BYTE) && b == KB_ACK && kbdout.expect_ack)
|
||||
{
|
||||
#if 1
|
||||
#if 0
|
||||
printf("got ACK from keyboard\n");
|
||||
#endif
|
||||
kbdout.expect_ack= 0;
|
||||
|
||||
@ -36,7 +36,9 @@ typedef struct pty {
|
||||
char rdsendreply; /* send a reply (instead of notify) */
|
||||
int rdcaller; /* process making the call (usually FS) */
|
||||
int rdproc; /* process that wants to read from the pty */
|
||||
vir_bytes rdvir; /* virtual address in readers address space */
|
||||
vir_bytes rdvir_g; /* virtual address in readers address space */
|
||||
vir_bytes rdvir_offset; /* offset in above grant */
|
||||
int rdsafe; /* safe read mode? */
|
||||
int rdleft; /* # bytes yet to be read */
|
||||
int rdcum; /* # bytes written so far */
|
||||
|
||||
@ -44,14 +46,16 @@ typedef struct pty {
|
||||
char wrsendreply; /* send a reply (instead of notify) */
|
||||
int wrcaller; /* process making the call (usually FS) */
|
||||
int wrproc; /* process that wants to write to the pty */
|
||||
vir_bytes wrvir; /* virtual address in writers address space */
|
||||
vir_bytes wrvir_g; /* virtual address in writers address space */
|
||||
vir_bytes wrvir_offset; /* offset in above grant */
|
||||
int wrsafe; /* safe write mode? */
|
||||
int wrleft; /* # bytes yet to be written */
|
||||
int wrcum; /* # bytes written so far */
|
||||
|
||||
/* Output buffer. */
|
||||
int ocount; /* # characters in the buffer */
|
||||
char *ohead, *otail; /* head and tail of the circular buffer */
|
||||
char obuf[128]; /* buffer for bytes going to the pty reader */
|
||||
char obuf[2048]; /* buffer for bytes going to the pty reader */
|
||||
|
||||
/* select() data. */
|
||||
int select_ops, /* Which operations do we want to know about? */
|
||||
@ -86,8 +90,12 @@ message *m_ptr;
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int r;
|
||||
phys_bytes p;
|
||||
int safe = 0;
|
||||
|
||||
switch (m_ptr->m_type) {
|
||||
case DEV_READ_S:
|
||||
safe=1;
|
||||
/* fallthrough */
|
||||
case DEV_READ:
|
||||
/* Check, store information on the reader, do I/O. */
|
||||
if (pp->state & TTY_CLOSED) {
|
||||
@ -114,21 +122,31 @@ message *m_ptr;
|
||||
pp->rdsendreply = TRUE;
|
||||
pp->rdcaller = m_ptr->m_source;
|
||||
pp->rdproc = m_ptr->IO_ENDPT;
|
||||
pp->rdvir = (vir_bytes) m_ptr->ADDRESS;
|
||||
pp->rdvir_g = (vir_bytes) m_ptr->ADDRESS;
|
||||
pp->rdvir_offset = 0;
|
||||
pp->rdsafe = safe;
|
||||
pp->rdleft = m_ptr->COUNT;
|
||||
pty_start(pp);
|
||||
handle_events(tp);
|
||||
if (pp->rdleft == 0) return; /* already done */
|
||||
if (pp->rdleft == 0) {
|
||||
return; /* already done */
|
||||
}
|
||||
|
||||
#if DEAD_CODE
|
||||
if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
|
||||
r = EAGAIN; /* don't suspend */
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
r = SUSPEND; /* do suspend */
|
||||
pp->rdsendreply = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEV_WRITE_S:
|
||||
safe=1;
|
||||
/* fallthrough */
|
||||
case DEV_WRITE:
|
||||
/* Check, store information on the writer, do I/O. */
|
||||
if (pp->state & TTY_CLOSED) {
|
||||
@ -156,15 +174,22 @@ message *m_ptr;
|
||||
pp->wrsendreply = TRUE;
|
||||
pp->wrcaller = m_ptr->m_source;
|
||||
pp->wrproc = m_ptr->IO_ENDPT;
|
||||
pp->wrvir = (vir_bytes) m_ptr->ADDRESS;
|
||||
pp->wrvir_g = (vir_bytes) m_ptr->ADDRESS;
|
||||
pp->wrvir_offset = 0;
|
||||
pp->wrsafe = safe;
|
||||
pp->wrleft = m_ptr->COUNT;
|
||||
handle_events(tp);
|
||||
if (pp->wrleft == 0) return; /* already done */
|
||||
if (pp->wrleft == 0) {
|
||||
return; /* already done */
|
||||
}
|
||||
|
||||
#if DEAD_CODE
|
||||
if (m_ptr->TTY_FLAGS & O_NONBLOCK) { /* don't suspend */
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
pp->wrsendreply = FALSE; /* do suspend */
|
||||
r = SUSPEND;
|
||||
}
|
||||
@ -192,15 +217,17 @@ message *m_ptr;
|
||||
break;
|
||||
|
||||
case CANCEL:
|
||||
r = EINTR;
|
||||
if (m_ptr->IO_ENDPT == pp->rdproc) {
|
||||
/* Cancel a read from a PTY. */
|
||||
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
}
|
||||
if (m_ptr->IO_ENDPT == pp->wrproc) {
|
||||
/* Cancel a write to a PTY. */
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
}
|
||||
r = EINTR;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -227,9 +254,14 @@ int try;
|
||||
if (pp->state & PTY_CLOSED) {
|
||||
if (try) return 1;
|
||||
if (tp->tty_outleft > 0) {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -245,10 +277,16 @@ int try;
|
||||
break;
|
||||
|
||||
/* Copy from user space to the PTY output buffer. */
|
||||
if ((s = sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
|
||||
SELF, D, (vir_bytes) pp->ohead, (phys_bytes) count)) != OK) {
|
||||
printf("pty tty%d: copy failed (error %d)\n", s);
|
||||
if(tp->tty_out_safe) {
|
||||
if ((s = sys_safecopyfrom(tp->tty_outproc, tp->tty_out_vir_g,
|
||||
tp->tty_out_vir_offset, (vir_bytes) pp->ohead, count, D))!=OK) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((s = sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir_g,
|
||||
SELF, D, (vir_bytes) pp->ohead, (phys_bytes) count)) != OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform output processing on the output buffer. */
|
||||
@ -263,13 +301,21 @@ int try;
|
||||
if ((pp->ohead += ocount) >= bufend(pp->obuf))
|
||||
pp->ohead -= buflen(pp->obuf);
|
||||
pty_start(pp);
|
||||
tp->tty_out_vir += count;
|
||||
|
||||
if(tp->tty_out_safe) tp->tty_out_vir_offset += count;
|
||||
else tp->tty_out_vir_g += count;
|
||||
|
||||
tp->tty_outcum += count;
|
||||
if ((tp->tty_outleft -= count) == 0) {
|
||||
/* Output is finished, reply to the writer. */
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
tp->tty_outcum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
pty_finish(pp);
|
||||
@ -319,16 +365,24 @@ pty_t *pp;
|
||||
if (count == 0) break;
|
||||
|
||||
/* Copy from the output buffer to the readers address space. */
|
||||
if ((s = sys_vircopy(SELF, D, (vir_bytes)pp->otail,
|
||||
(vir_bytes) pp->rdproc, D, (vir_bytes) pp->rdvir, (phys_bytes) count)) != OK) {
|
||||
printf("pty tty%d: copy failed (error %d)\n", s);
|
||||
if (pp->rdsafe) {
|
||||
if((s = sys_safecopyto(pp->rdproc, pp->rdvir_g,
|
||||
pp->rdvir_offset, (vir_bytes) pp->otail, count, D)) != OK) {
|
||||
break;
|
||||
}
|
||||
pp->rdvir_offset += count;
|
||||
} else {
|
||||
if ((s = sys_vircopy(SELF, D, (vir_bytes)pp->otail,
|
||||
(vir_bytes) pp->rdproc, D, (vir_bytes) pp->rdvir_g, (phys_bytes) count)) != OK) {
|
||||
printf("pty tty: copy failed (error %d)\n", s);
|
||||
break;
|
||||
}
|
||||
pp->rdvir_g += count;
|
||||
}
|
||||
|
||||
/* Bookkeeping. */
|
||||
pp->ocount -= count;
|
||||
if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf;
|
||||
pp->rdvir += count;
|
||||
pp->rdcum += count;
|
||||
pp->rdleft -= count;
|
||||
}
|
||||
@ -370,9 +424,14 @@ int try;
|
||||
if (pp->state & PTY_CLOSED) {
|
||||
if (try) return 1;
|
||||
if (tp->tty_inleft > 0) {
|
||||
tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
|
||||
tp->tty_incum);
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
if(tp->tty_inrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_incaller);
|
||||
tp->tty_inrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_inrepcode, tp->tty_incaller,
|
||||
tp->tty_inproc, tp->tty_incum);
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -387,17 +446,26 @@ int try;
|
||||
int s;
|
||||
|
||||
/* Transfer one character to 'c'. */
|
||||
if ((s = sys_vircopy(pp->wrproc, D, (vir_bytes) pp->wrvir,
|
||||
if(pp->wrsafe) {
|
||||
if ((s = sys_safecopyfrom(pp->wrproc, pp->wrvir_g,
|
||||
pp->wrvir_offset, (vir_bytes) &c, 1, D)) != OK) {
|
||||
printf("pty: safecopy failed (error %d)\n", s);
|
||||
break;
|
||||
}
|
||||
pp->wrvir_offset++;
|
||||
} else {
|
||||
if ((s = sys_vircopy(pp->wrproc, D, (vir_bytes) pp->wrvir_g,
|
||||
SELF, D, (vir_bytes) &c, (phys_bytes) 1)) != OK) {
|
||||
printf("pty: copy failed (error %d)\n", s);
|
||||
break;
|
||||
}
|
||||
pp->wrvir_g++;
|
||||
}
|
||||
|
||||
/* Input processing. */
|
||||
if (in_process(tp, &c, 1) == 0) break;
|
||||
|
||||
/* PTY writer bookkeeping. */
|
||||
pp->wrvir++;
|
||||
pp->wrcum++;
|
||||
if (--pp->wrleft == 0) {
|
||||
if (pp->wrsendreply) {
|
||||
@ -447,7 +515,6 @@ int try;
|
||||
pty_t *pp = tp->tty_priv;
|
||||
|
||||
if (pp->wrleft > 0) {
|
||||
assert(!pp->wrsendreply);
|
||||
pp->wrcum += pp->wrleft;
|
||||
pp->wrleft= 0;
|
||||
notify(pp->wrcaller);
|
||||
@ -512,6 +579,7 @@ PUBLIC int pty_status(message *m_ptr)
|
||||
{
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = pp->rdproc;
|
||||
m_ptr->REP_IO_GRANT = pp->rdvir_g;
|
||||
m_ptr->REP_STATUS = pp->rdcum;
|
||||
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
@ -525,6 +593,7 @@ PUBLIC int pty_status(message *m_ptr)
|
||||
{
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = pp->wrproc;
|
||||
m_ptr->REP_IO_GRANT = pp->wrvir_g;
|
||||
if (pp->wrcum == 0)
|
||||
m_ptr->REP_STATUS = EIO;
|
||||
else
|
||||
|
||||
@ -321,8 +321,13 @@ int try;
|
||||
if (try) return 1;
|
||||
|
||||
/* Copy from user space to the RS232 output buffer. */
|
||||
sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
|
||||
if(tp->tty_out_safe) {
|
||||
sys_safecopyfrom(tp->tty_outproc, tp->tty_out_vir_g,
|
||||
tp->tty_out_vir_offset, (vir_bytes) rs->ohead, count, D);
|
||||
} else {
|
||||
sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir_g,
|
||||
SELF, D, (vir_bytes) rs->ohead, (phys_bytes) count);
|
||||
}
|
||||
|
||||
/* Perform output processing on the output buffer. */
|
||||
out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
|
||||
@ -338,7 +343,11 @@ int try;
|
||||
unlock();
|
||||
if ((rs->ohead += ocount) >= bufend(rs->obuf))
|
||||
rs->ohead -= buflen(rs->obuf);
|
||||
tp->tty_out_vir += count;
|
||||
if(tp->tty_out_safe) {
|
||||
tp->tty_out_vir_offset += count;
|
||||
} else {
|
||||
tp->tty_out_vir_g += count;
|
||||
}
|
||||
tp->tty_outcum += count;
|
||||
if ((tp->tty_outleft -= count) == 0) {
|
||||
/* Output is finished, reply to the writer. */
|
||||
|
||||
@ -29,26 +29,26 @@
|
||||
* DEV_STATUS: FS wants to know status for SELECT or REVIVE
|
||||
* CANCEL: terminate a previous incomplete system call immediately
|
||||
*
|
||||
* m_type TTY_LINE IO_ENDPT COUNT TTY_SPEK TTY_FLAGS ADDRESS
|
||||
* ---------------------------------------------------------------------------
|
||||
* | HARD_INT | | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | SYS_SIG | sig set | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_READ |minor dev| proc nr | count | O_NONBLOCK| buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE |minor dev| proc nr | count | | | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_IOCTL |minor dev| proc nr |func code|erase etc| flags | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_OPEN |minor dev| proc nr | O_NOCTTY| | | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE |minor dev| proc nr | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | DEV_STATUS | | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------+---------|
|
||||
* | CANCEL |minor dev| proc nr | | | | |
|
||||
* ---------------------------------------------------------------------------
|
||||
* m_type TTY_LINE IO_ENDPT COUNT TTY_SPEKS ADDRESS
|
||||
* -----------------------------------------------------------------
|
||||
* | HARD_INT | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | SYS_SIG | sig set | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_READ |minor dev| proc nr | count | | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE |minor dev| proc nr | count | | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_IOCTL |minor dev| proc nr |func code|erase etc| |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_OPEN |minor dev| proc nr | O_NOCTTY| | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE |minor dev| proc nr | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | DEV_STATUS | | | | | |
|
||||
* |-------------+---------+---------+---------+---------+---------|
|
||||
* | CANCEL |minor dev| proc nr | | | |
|
||||
* -----------------------------------------------------------------
|
||||
*
|
||||
* Changes:
|
||||
* Jan 20, 2004 moved TTY driver to user-space (Jorrit N. Herder)
|
||||
@ -58,9 +58,6 @@
|
||||
|
||||
#include "../drivers.h"
|
||||
#include <termios.h>
|
||||
#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
|
||||
#include <sgtty.h>
|
||||
#endif
|
||||
#include <sys/ioc_tty.h>
|
||||
#include <signal.h>
|
||||
#include <minix/callnr.h>
|
||||
@ -106,11 +103,11 @@ FORWARD _PROTOTYPE( void tty_timed_out, (timer_t *tp) );
|
||||
FORWARD _PROTOTYPE( void expire_timers, (void) );
|
||||
FORWARD _PROTOTYPE( void settimer, (tty_t *tty_ptr, int enable) );
|
||||
FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr, int s) );
|
||||
FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr, int s) );
|
||||
FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr, int s) );
|
||||
FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void do_status, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp) );
|
||||
@ -122,17 +119,6 @@ FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp) );
|
||||
FORWARD _PROTOTYPE( void setattr, (tty_t *tp) );
|
||||
FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp) );
|
||||
FORWARD _PROTOTYPE( void tty_init, (void) );
|
||||
#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
|
||||
FORWARD _PROTOTYPE( int compat_getp, (tty_t *tp, struct sgttyb *sg) );
|
||||
FORWARD _PROTOTYPE( int compat_getc, (tty_t *tp, struct tchars *sg) );
|
||||
FORWARD _PROTOTYPE( int compat_setp, (tty_t *tp, struct sgttyb *sg) );
|
||||
FORWARD _PROTOTYPE( int compat_setc, (tty_t *tp, struct tchars *sg) );
|
||||
FORWARD _PROTOTYPE( int tspd2sgspd, (speed_t tspd) );
|
||||
FORWARD _PROTOTYPE( speed_t sgspd2tspd, (int sgspd) );
|
||||
#if ENABLE_BINCOMPAT
|
||||
FORWARD _PROTOTYPE( void do_ioctl_compat, (tty_t *tp, message *m_ptr) );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Default attributes. */
|
||||
PRIVATE struct termios termios_defaults = {
|
||||
@ -165,17 +151,6 @@ PUBLIC void main(void)
|
||||
register struct proc *rp;
|
||||
register tty_t *tp;
|
||||
|
||||
#if DEBUG
|
||||
kputc('H');
|
||||
kputc('e');
|
||||
kputc('l');
|
||||
kputc('l');
|
||||
kputc('o');
|
||||
kputc(',');
|
||||
kputc(' ');
|
||||
printf("TTY\n");
|
||||
#endif
|
||||
|
||||
/* Get kernel environment (protected_mode, pc_at and ega are needed). */
|
||||
if (OK != (s=sys_getmachine(&machine))) {
|
||||
panic("TTY","Couldn't obtain kernel environment.", s);
|
||||
@ -229,13 +204,6 @@ PUBLIC void main(void)
|
||||
}
|
||||
case PROC_EVENT: {
|
||||
cons_stop(); /* switch to primary console */
|
||||
printf("TTY got PROC_EVENT, assuming SIGTERM\n");
|
||||
#if DEAD_CODE
|
||||
if (irq_hook_id != -1) {
|
||||
sys_irqdisable(&irq_hook_id);
|
||||
sys_irqrmpolicy(KEYBOARD_IRQ, &irq_hook_id);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
case SYS_SIG: { /* system signal */
|
||||
@ -244,7 +212,10 @@ PUBLIC void main(void)
|
||||
continue;
|
||||
}
|
||||
case DIAGNOSTICS: /* a server wants to print some */
|
||||
do_diagnostics(&tty_mess);
|
||||
do_diagnostics(&tty_mess, 0);
|
||||
continue;
|
||||
case DIAGNOSTICS_S:
|
||||
do_diagnostics(&tty_mess, 1);
|
||||
continue;
|
||||
case GET_KMESS:
|
||||
do_get_kmess(&tty_mess);
|
||||
@ -284,7 +255,8 @@ PUBLIC void main(void)
|
||||
tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
|
||||
} else if ((line - PTYPX_MINOR) < NR_PTYS) {
|
||||
tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
|
||||
if (tty_mess.m_type != DEV_IOCTL) {
|
||||
if (tty_mess.m_type != DEV_IOCTL &&
|
||||
tty_mess.m_type != DEV_IOCTL_S) {
|
||||
do_pty(tp, &tty_mess);
|
||||
continue;
|
||||
}
|
||||
@ -306,9 +278,12 @@ PUBLIC void main(void)
|
||||
|
||||
/* Execute the requested device driver function. */
|
||||
switch (tty_mess.m_type) {
|
||||
case DEV_READ: do_read(tp, &tty_mess); break;
|
||||
case DEV_WRITE: do_write(tp, &tty_mess); break;
|
||||
case DEV_IOCTL: do_ioctl(tp, &tty_mess); break;
|
||||
case DEV_READ: do_read(tp, &tty_mess, 0); break;
|
||||
case DEV_READ_S: do_read(tp, &tty_mess, 1); break;
|
||||
case DEV_WRITE: do_write(tp, &tty_mess, 0); break;
|
||||
case DEV_WRITE_S: do_write(tp, &tty_mess, 1); break;
|
||||
case DEV_IOCTL: do_ioctl(tp, &tty_mess, 0); break;
|
||||
case DEV_IOCTL_S: do_ioctl(tp, &tty_mess, 1); break;
|
||||
case DEV_OPEN: do_open(tp, &tty_mess); break;
|
||||
case DEV_CLOSE: do_close(tp, &tty_mess); break;
|
||||
case DEV_SELECT: do_select(tp, &tty_mess); break;
|
||||
@ -356,6 +331,7 @@ message *m_ptr;
|
||||
/* Suspended request finished. Send a REVIVE. */
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = tp->tty_inproc;
|
||||
m_ptr->REP_IO_GRANT = tp->tty_in_vir_g;
|
||||
m_ptr->REP_STATUS = tp->tty_incum;
|
||||
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
@ -368,6 +344,7 @@ message *m_ptr;
|
||||
/* Suspended request finished. Send a REVIVE. */
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = tp->tty_outproc;
|
||||
m_ptr->REP_IO_GRANT = tp->tty_out_vir_g;
|
||||
m_ptr->REP_STATUS = tp->tty_outcum;
|
||||
|
||||
tp->tty_outcum = 0;
|
||||
@ -375,6 +352,16 @@ message *m_ptr;
|
||||
event_found = 1;
|
||||
break;
|
||||
}
|
||||
else if (tp->tty_iorevived && tp->tty_iocaller == m_ptr->m_source) {
|
||||
/* Suspended request finished. Send a REVIVE. */
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = tp->tty_ioproc;
|
||||
m_ptr->REP_IO_GRANT = tp->tty_iovir_g;
|
||||
m_ptr->REP_STATUS = tp->tty_iostatus;
|
||||
tp->tty_iorevived = 0; /* unmark revive event */
|
||||
event_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if NR_PTYS > 0
|
||||
@ -398,36 +385,30 @@ message *m_ptr;
|
||||
/*===========================================================================*
|
||||
* do_read *
|
||||
*===========================================================================*/
|
||||
PRIVATE void do_read(tp, m_ptr)
|
||||
PRIVATE void do_read(tp, m_ptr, safe)
|
||||
register tty_t *tp; /* pointer to tty struct */
|
||||
register message *m_ptr; /* pointer to message sent to the task */
|
||||
int safe; /* use safecopies? */
|
||||
{
|
||||
/* A process wants to read from a terminal. */
|
||||
int r, status;
|
||||
phys_bytes phys_addr;
|
||||
int more_verbose= (tp == tty_addr(NR_CONS));
|
||||
|
||||
/* Check if there is already a process hanging in a read, check if the
|
||||
* parameters are correct, do I/O.
|
||||
*/
|
||||
if (tp->tty_inleft > 0) {
|
||||
if (more_verbose) printf("do_read: EIO\n");
|
||||
r = EIO;
|
||||
} else
|
||||
if (m_ptr->COUNT <= 0) {
|
||||
if (more_verbose) printf("do_read: EINVAL\n");
|
||||
r = EINVAL;
|
||||
} else
|
||||
if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
|
||||
&phys_addr) != OK) {
|
||||
if (more_verbose) printf("do_read: EFAULT\n");
|
||||
r = EFAULT;
|
||||
} else {
|
||||
/* Copy information from the message to the tty struct. */
|
||||
tp->tty_inrepcode = TASK_REPLY;
|
||||
tp->tty_incaller = m_ptr->m_source;
|
||||
tp->tty_inproc = m_ptr->IO_ENDPT;
|
||||
tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_in_vir_g = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_in_vir_offset = 0;
|
||||
tp->tty_in_safe = safe;
|
||||
tp->tty_inleft = m_ptr->COUNT;
|
||||
|
||||
if (!(tp->tty_termios.c_lflag & ICANON)
|
||||
@ -459,18 +440,12 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
return; /* already done */
|
||||
}
|
||||
|
||||
/* There were no bytes in the input queue available, so either suspend
|
||||
* the caller or break off the read if nonblocking.
|
||||
/* There were no bytes in the input queue available, so suspend
|
||||
* the caller.
|
||||
*/
|
||||
if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
|
||||
r = EAGAIN; /* cancel the read */
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
} else {
|
||||
r = SUSPEND; /* suspend the caller */
|
||||
tp->tty_inrepcode = REVIVE;
|
||||
}
|
||||
r = SUSPEND; /* suspend the caller */
|
||||
tp->tty_inrepcode = TTY_REVIVE;
|
||||
}
|
||||
if (more_verbose) printf("do_read: replying %d\n", r);
|
||||
tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
|
||||
if (tp->tty_select_ops)
|
||||
select_retry(tp);
|
||||
@ -479,13 +454,13 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
/*===========================================================================*
|
||||
* do_write *
|
||||
*===========================================================================*/
|
||||
PRIVATE void do_write(tp, m_ptr)
|
||||
PRIVATE void do_write(tp, m_ptr, safe)
|
||||
register tty_t *tp;
|
||||
register message *m_ptr; /* pointer to message sent to the task */
|
||||
int safe;
|
||||
{
|
||||
/* A process wants to write on a terminal. */
|
||||
int r;
|
||||
phys_bytes phys_addr;
|
||||
|
||||
/* Check if there is already a process hanging in a write, check if the
|
||||
* parameters are correct, do I/O.
|
||||
@ -495,16 +470,14 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
} else
|
||||
if (m_ptr->COUNT <= 0) {
|
||||
r = EINVAL;
|
||||
} else
|
||||
if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
|
||||
&phys_addr) != OK) {
|
||||
r = EFAULT;
|
||||
} else {
|
||||
/* Copy message parameters to the tty structure. */
|
||||
tp->tty_outrepcode = TASK_REPLY;
|
||||
tp->tty_outcaller = m_ptr->m_source;
|
||||
tp->tty_outproc = m_ptr->IO_ENDPT;
|
||||
tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_out_vir_g = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_out_vir_offset = 0;
|
||||
tp->tty_out_safe = safe;
|
||||
tp->tty_outleft = m_ptr->COUNT;
|
||||
|
||||
/* Try to write. */
|
||||
@ -512,16 +485,11 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
if (tp->tty_outleft == 0)
|
||||
return; /* already done */
|
||||
|
||||
/* None or not all the bytes could be written, so either suspend the
|
||||
* caller or break off the write if nonblocking.
|
||||
/* None or not all the bytes could be written, so suspend the
|
||||
* caller.
|
||||
*/
|
||||
if (m_ptr->TTY_FLAGS & O_NONBLOCK) { /* cancel the write */
|
||||
r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
} else {
|
||||
r = SUSPEND; /* suspend the caller */
|
||||
tp->tty_outrepcode = REVIVE;
|
||||
}
|
||||
r = SUSPEND; /* suspend the caller */
|
||||
tp->tty_outrepcode = TTY_REVIVE;
|
||||
}
|
||||
tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
|
||||
}
|
||||
@ -529,9 +497,10 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
/*===========================================================================*
|
||||
* do_ioctl *
|
||||
*===========================================================================*/
|
||||
PRIVATE void do_ioctl(tp, m_ptr)
|
||||
PRIVATE void do_ioctl(tp, m_ptr, safe)
|
||||
register tty_t *tp;
|
||||
message *m_ptr; /* pointer to message sent to task */
|
||||
int safe;
|
||||
{
|
||||
/* Perform an IOCTL on this terminal. Posix termios calls are handled
|
||||
* by the IOCTL system call
|
||||
@ -540,10 +509,6 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
int r;
|
||||
union {
|
||||
int i;
|
||||
#if ENABLE_SRCCOMPAT
|
||||
struct sgttyb sg;
|
||||
struct tchars tc;
|
||||
#endif
|
||||
} param;
|
||||
size_t size;
|
||||
|
||||
@ -569,17 +534,6 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
size = sizeof(struct winsize);
|
||||
break;
|
||||
|
||||
#if ENABLE_SRCCOMPAT
|
||||
case TIOCGETP: /* BSD-style get terminal properties */
|
||||
case TIOCSETP: /* BSD-style set terminal properties */
|
||||
size = sizeof(struct sgttyb);
|
||||
break;
|
||||
|
||||
case TIOCGETC: /* BSD-style get terminal special characters */
|
||||
case TIOCSETC: /* BSD-style get terminal special characters */
|
||||
size = sizeof(struct tchars);
|
||||
break;
|
||||
#endif
|
||||
#if (MACHINE == IBM_PC)
|
||||
case KIOCSMAP: /* load keymap (Minix extension) */
|
||||
size = sizeof(keymap_t);
|
||||
@ -598,9 +552,14 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
switch (m_ptr->TTY_REQUEST) {
|
||||
case TCGETS:
|
||||
/* Get the termios attributes. */
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_termios,
|
||||
if(safe) {
|
||||
r = sys_safecopyto(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) &tp->tty_termios, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_termios,
|
||||
m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
(vir_bytes) size);
|
||||
}
|
||||
break;
|
||||
|
||||
case TCSETSW:
|
||||
@ -611,7 +570,8 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
tp->tty_iocaller = m_ptr->m_source;
|
||||
tp->tty_ioproc = m_ptr->IO_ENDPT;
|
||||
tp->tty_ioreq = m_ptr->REQUEST;
|
||||
tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_iovir_g = (vir_bytes) m_ptr->ADDRESS;
|
||||
tp->tty_io_safe = safe;
|
||||
r = SUSPEND;
|
||||
break;
|
||||
}
|
||||
@ -620,15 +580,25 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
/*FALL THROUGH*/
|
||||
case TCSETS:
|
||||
/* Set the termios attributes. */
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) &tp->tty_termios, (vir_bytes) size);
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) &tp->tty_termios, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) &tp->tty_termios, (vir_bytes) size);
|
||||
}
|
||||
if (r != OK) break;
|
||||
setattr(tp);
|
||||
break;
|
||||
|
||||
case TCFLSH:
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) ¶m.i, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) ¶m.i, (vir_bytes) size);
|
||||
}
|
||||
if (r != OK) break;
|
||||
switch (param.i) {
|
||||
case TCIFLUSH: tty_icancel(tp); break;
|
||||
@ -639,8 +609,13 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
break;
|
||||
|
||||
case TCFLOW:
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) ¶m.i, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) ¶m.i, (vir_bytes) size);
|
||||
}
|
||||
if (r != OK) break;
|
||||
switch (param.i) {
|
||||
case TCOOFF:
|
||||
@ -664,51 +639,31 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
break;
|
||||
|
||||
case TIOCGWINSZ:
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_winsize,
|
||||
if(safe) {
|
||||
r = sys_safecopyto(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) &tp->tty_winsize, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_winsize,
|
||||
m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
(vir_bytes) size);
|
||||
}
|
||||
break;
|
||||
|
||||
case TIOCSWINSZ:
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
if(safe) {
|
||||
r = sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS, 0,
|
||||
(vir_bytes) &tp->tty_winsize, (vir_bytes) size, D);
|
||||
} else {
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) &tp->tty_winsize, (vir_bytes) size);
|
||||
}
|
||||
sigchar(tp, SIGWINCH);
|
||||
break;
|
||||
|
||||
#if ENABLE_SRCCOMPAT
|
||||
case TIOCGETP:
|
||||
compat_getp(tp, ¶m.sg);
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) ¶m.sg,
|
||||
m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
(vir_bytes) size);
|
||||
break;
|
||||
|
||||
case TIOCSETP:
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) ¶m.sg, (vir_bytes) size);
|
||||
if (r != OK) break;
|
||||
compat_setp(tp, ¶m.sg);
|
||||
break;
|
||||
|
||||
case TIOCGETC:
|
||||
compat_getc(tp, ¶m.tc);
|
||||
r = sys_vircopy(SELF, D, (vir_bytes) ¶m.tc,
|
||||
m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
(vir_bytes) size);
|
||||
break;
|
||||
|
||||
case TIOCSETC:
|
||||
r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
|
||||
SELF, D, (vir_bytes) ¶m.tc, (vir_bytes) size);
|
||||
if (r != OK) break;
|
||||
compat_setc(tp, ¶m.tc);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if (MACHINE == IBM_PC)
|
||||
case KIOCSMAP:
|
||||
/* Load a new keymap (only /dev/console). */
|
||||
if (isconsole(tp)) r = kbd_loadmap(m_ptr);
|
||||
if (isconsole(tp)) r = kbd_loadmap(m_ptr, safe);
|
||||
break;
|
||||
|
||||
case TIOCSFON:
|
||||
@ -729,12 +684,7 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
case TIOCGPGRP:
|
||||
case TIOCSPGRP:
|
||||
default:
|
||||
#if ENABLE_BINCOMPAT
|
||||
do_ioctl_compat(tp, m_ptr);
|
||||
return;
|
||||
#else
|
||||
r = ENOTTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send the reply. */
|
||||
@ -801,26 +751,33 @@ message *m_ptr; /* pointer to message sent to task */
|
||||
|
||||
int proc_nr;
|
||||
int mode;
|
||||
int r = EINTR;
|
||||
|
||||
/* Check the parameters carefully, to avoid cancelling twice. */
|
||||
proc_nr = m_ptr->IO_ENDPT;
|
||||
mode = m_ptr->COUNT;
|
||||
if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
|
||||
if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc &&
|
||||
(!tp->tty_in_safe || tp->tty_in_vir_g==(vir_bytes)m_ptr->IO_GRANT)) {
|
||||
/* Process was reading when killed. Clean up input. */
|
||||
tty_icancel(tp);
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
}
|
||||
if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
|
||||
tty_icancel(tp);
|
||||
r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
|
||||
tp->tty_inleft = tp->tty_incum = tp->tty_inrevived = 0;
|
||||
}
|
||||
if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc &&
|
||||
(!tp->tty_out_safe || tp->tty_out_vir_g==(vir_bytes)m_ptr->IO_GRANT)) {
|
||||
/* Process was writing when killed. Clean up output. */
|
||||
(*tp->tty_ocancel)(tp, 0);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
}
|
||||
#if DEAD_CODE
|
||||
(*tp->tty_ocancel)(tp, 0);
|
||||
#endif
|
||||
r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
|
||||
tp->tty_outleft = tp->tty_outcum = tp->tty_outrevived = 0;
|
||||
}
|
||||
if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
|
||||
/* Process was waiting for output to drain. */
|
||||
tp->tty_ioreq = 0;
|
||||
}
|
||||
tp->tty_events = 1;
|
||||
tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
|
||||
tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, r);
|
||||
}
|
||||
|
||||
PUBLIC int select_try(struct tty *tp, int ops)
|
||||
@ -905,7 +862,7 @@ tty_t *tp; /* TTY to check for events. */
|
||||
|
||||
/* Reply if enough bytes are available. */
|
||||
if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
|
||||
if (tp->tty_inrepcode == REVIVE) {
|
||||
if (tp->tty_inrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_incaller);
|
||||
tp->tty_inrevived = 1;
|
||||
} else {
|
||||
@ -952,10 +909,18 @@ register tty_t *tp; /* pointer to terminal to read from */
|
||||
tp->tty_inleft--;
|
||||
if (++bp == bufend(buf)) {
|
||||
/* Temp buffer full, copy to user space. */
|
||||
sys_vircopy(SELF, D, (vir_bytes) buf,
|
||||
tp->tty_inproc, D, tp->tty_in_vir,
|
||||
(vir_bytes) buflen(buf));
|
||||
tp->tty_in_vir += buflen(buf);
|
||||
if(tp->tty_in_safe) {
|
||||
sys_safecopyto(tp->tty_inproc,
|
||||
tp->tty_in_vir_g, tp->tty_in_vir_offset,
|
||||
(vir_bytes) buf,
|
||||
(vir_bytes) buflen(buf), D);
|
||||
tp->tty_in_vir_offset += buflen(buf);
|
||||
} else {
|
||||
sys_vircopy(SELF, D, (vir_bytes) buf,
|
||||
tp->tty_inproc, D, tp->tty_in_vir_g,
|
||||
(vir_bytes) buflen(buf));
|
||||
tp->tty_in_vir_g += buflen(buf);
|
||||
}
|
||||
tp->tty_incum += buflen(buf);
|
||||
bp = buf;
|
||||
}
|
||||
@ -975,15 +940,22 @@ register tty_t *tp; /* pointer to terminal to read from */
|
||||
if (bp > buf) {
|
||||
/* Leftover characters in the buffer. */
|
||||
count = bp - buf;
|
||||
sys_vircopy(SELF, D, (vir_bytes) buf,
|
||||
tp->tty_inproc, D, tp->tty_in_vir, (vir_bytes) count);
|
||||
tp->tty_in_vir += count;
|
||||
if(tp->tty_in_safe) {
|
||||
sys_safecopyto(tp->tty_inproc,
|
||||
tp->tty_in_vir_g, tp->tty_in_vir_offset,
|
||||
(vir_bytes) buf, (vir_bytes) count, D);
|
||||
tp->tty_in_vir_offset += count;
|
||||
} else {
|
||||
sys_vircopy(SELF, D, (vir_bytes) buf,
|
||||
tp->tty_inproc, D, tp->tty_in_vir_g, (vir_bytes) count);
|
||||
tp->tty_in_vir_g += count;
|
||||
}
|
||||
tp->tty_incum += count;
|
||||
}
|
||||
|
||||
/* Usually reply to the reader, possibly even if incum == 0 (EOF). */
|
||||
if (tp->tty_inleft == 0) {
|
||||
if (tp->tty_inrepcode == REVIVE) {
|
||||
if (tp->tty_inrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_incaller);
|
||||
tp->tty_inrevived = 1;
|
||||
} else {
|
||||
@ -1398,13 +1370,21 @@ tty_t *tp;
|
||||
|
||||
if (tp->tty_ioreq != TCDRAIN) {
|
||||
if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
|
||||
result = sys_vircopy(tp->tty_ioproc, D, tp->tty_iovir,
|
||||
if(tp->tty_io_safe) {
|
||||
result = sys_safecopyfrom(tp->tty_ioproc, tp->tty_iovir_g, 0,
|
||||
(vir_bytes) &tp->tty_termios,
|
||||
(vir_bytes) sizeof(tp->tty_termios), D);
|
||||
} else {
|
||||
result = sys_vircopy(tp->tty_ioproc, D, tp->tty_iovir_g,
|
||||
SELF, D, (vir_bytes) &tp->tty_termios,
|
||||
(vir_bytes) sizeof(tp->tty_termios));
|
||||
}
|
||||
setattr(tp);
|
||||
}
|
||||
tp->tty_ioreq = 0;
|
||||
tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, result);
|
||||
notify(tp->tty_iocaller);
|
||||
tp->tty_iorevived = 1;
|
||||
tp->tty_iostatus = result;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
@ -1463,7 +1443,11 @@ tty_t *tp;
|
||||
/*===========================================================================*
|
||||
* tty_reply *
|
||||
*===========================================================================*/
|
||||
PUBLIC void tty_reply(code, replyee, proc_nr, status)
|
||||
PUBLIC void
|
||||
tty_reply_f(
|
||||
file, line, code, replyee, proc_nr, status)
|
||||
char *file;
|
||||
int line;
|
||||
int code; /* TASK_REPLY or REVIVE */
|
||||
int replyee; /* destination address for the reply */
|
||||
int proc_nr; /* to whom should the reply go? */
|
||||
@ -1476,8 +1460,17 @@ int status; /* reply code */
|
||||
tty_mess.REP_ENDPT = proc_nr;
|
||||
tty_mess.REP_STATUS = status;
|
||||
|
||||
/* TTY is not supposed to send a TTY_REVIVE message. The
|
||||
* REVIVE message is gone, TTY_REVIVE is only used as an internal
|
||||
* placeholder for something that is not supposed to be a message.
|
||||
*/
|
||||
if(code == TTY_REVIVE) {
|
||||
panicing = 1;
|
||||
printf("%s:%d: ", file, line);
|
||||
panic("TTY","tty_reply sending TTY_REVIVE", NO_NUM);
|
||||
}
|
||||
|
||||
if ((status = send(replyee, &tty_mess)) != OK) {
|
||||
printf("TTY: couldn't reply to %d\n", replyee);
|
||||
panic("TTY","tty_reply failed, status\n", status);
|
||||
}
|
||||
}
|
||||
@ -1496,9 +1489,11 @@ int sig; /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
|
||||
*/
|
||||
int status;
|
||||
|
||||
if (tp->tty_pgrp != 0)
|
||||
if (OK != (status = sys_kill(tp->tty_pgrp, sig)))
|
||||
if (tp->tty_pgrp != 0) {
|
||||
if (OK != (status = sys_kill(tp->tty_pgrp, sig))) {
|
||||
panic("TTY","Error, call to sys_kill failed", status);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(tp->tty_termios.c_lflag & NOFLSH)) {
|
||||
tp->tty_incount = tp->tty_eotct = 0; /* kill earlier input */
|
||||
@ -1685,341 +1680,3 @@ register message *m_ptr; /* pointer to message sent to the task */
|
||||
return;
|
||||
}
|
||||
|
||||
#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
|
||||
/*===========================================================================*
|
||||
* compat_getp *
|
||||
*===========================================================================*/
|
||||
PRIVATE int compat_getp(tp, sg)
|
||||
tty_t *tp;
|
||||
struct sgttyb *sg;
|
||||
{
|
||||
/* Translate an old TIOCGETP to the termios equivalent. */
|
||||
int flgs;
|
||||
|
||||
sg->sg_erase = tp->tty_termios.c_cc[VERASE];
|
||||
sg->sg_kill = tp->tty_termios.c_cc[VKILL];
|
||||
sg->sg_ospeed = tspd2sgspd(cfgetospeed(&tp->tty_termios));
|
||||
sg->sg_ispeed = tspd2sgspd(cfgetispeed(&tp->tty_termios));
|
||||
|
||||
flgs = 0;
|
||||
|
||||
/* XTABS - if OPOST and XTABS */
|
||||
if ((tp->tty_termios.c_oflag & (OPOST|XTABS)) == (OPOST|XTABS))
|
||||
flgs |= 0006000;
|
||||
|
||||
/* BITS5..BITS8 - map directly to CS5..CS8 */
|
||||
flgs |= (tp->tty_termios.c_cflag & CSIZE) << (8-2);
|
||||
|
||||
/* EVENP - if PARENB and not PARODD */
|
||||
if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == PARENB)
|
||||
flgs |= 0000200;
|
||||
|
||||
/* ODDP - if PARENB and PARODD */
|
||||
if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == (PARENB|PARODD))
|
||||
flgs |= 0000100;
|
||||
|
||||
/* RAW - if not ICANON and not ISIG */
|
||||
if (!(tp->tty_termios.c_lflag & (ICANON|ISIG)))
|
||||
flgs |= 0000040;
|
||||
|
||||
/* CRMOD - if ICRNL */
|
||||
if (tp->tty_termios.c_iflag & ICRNL)
|
||||
flgs |= 0000020;
|
||||
|
||||
/* ECHO - if ECHO */
|
||||
if (tp->tty_termios.c_lflag & ECHO)
|
||||
flgs |= 0000010;
|
||||
|
||||
/* CBREAK - if not ICANON and ISIG */
|
||||
if ((tp->tty_termios.c_lflag & (ICANON|ISIG)) == ISIG)
|
||||
flgs |= 0000002;
|
||||
|
||||
sg->sg_flags = flgs;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* compat_getc *
|
||||
*===========================================================================*/
|
||||
PRIVATE int compat_getc(tp, tc)
|
||||
tty_t *tp;
|
||||
struct tchars *tc;
|
||||
{
|
||||
/* Translate an old TIOCGETC to the termios equivalent. */
|
||||
|
||||
tc->t_intrc = tp->tty_termios.c_cc[VINTR];
|
||||
tc->t_quitc = tp->tty_termios.c_cc[VQUIT];
|
||||
tc->t_startc = tp->tty_termios.c_cc[VSTART];
|
||||
tc->t_stopc = tp->tty_termios.c_cc[VSTOP];
|
||||
tc->t_brkc = tp->tty_termios.c_cc[VEOL];
|
||||
tc->t_eofc = tp->tty_termios.c_cc[VEOF];
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* compat_setp *
|
||||
*===========================================================================*/
|
||||
PRIVATE int compat_setp(tp, sg)
|
||||
tty_t *tp;
|
||||
struct sgttyb *sg;
|
||||
{
|
||||
/* Translate an old TIOCSETP to the termios equivalent. */
|
||||
struct termios termios;
|
||||
int flags;
|
||||
|
||||
termios = tp->tty_termios;
|
||||
|
||||
termios.c_cc[VERASE] = sg->sg_erase;
|
||||
termios.c_cc[VKILL] = sg->sg_kill;
|
||||
cfsetispeed(&termios, sgspd2tspd(sg->sg_ispeed & BYTE));
|
||||
cfsetospeed(&termios, sgspd2tspd(sg->sg_ospeed & BYTE));
|
||||
flags = sg->sg_flags;
|
||||
|
||||
/* Input flags */
|
||||
|
||||
/* BRKINT - not changed */
|
||||
/* ICRNL - set if CRMOD is set and not RAW */
|
||||
/* (CRMOD also controls output) */
|
||||
termios.c_iflag &= ~ICRNL;
|
||||
if ((flags & 0000020) && !(flags & 0000040))
|
||||
termios.c_iflag |= ICRNL;
|
||||
|
||||
/* IGNBRK - not changed */
|
||||
/* IGNCR - forced off (ignoring cr's is not supported) */
|
||||
termios.c_iflag &= ~IGNCR;
|
||||
|
||||
/* IGNPAR - not changed */
|
||||
/* INLCR - forced off (mapping nl's to cr's is not supported) */
|
||||
termios.c_iflag &= ~INLCR;
|
||||
|
||||
/* INPCK - not changed */
|
||||
/* ISTRIP - not changed */
|
||||
/* IXOFF - not changed */
|
||||
/* IXON - forced on if not RAW */
|
||||
termios.c_iflag &= ~IXON;
|
||||
if (!(flags & 0000040))
|
||||
termios.c_iflag |= IXON;
|
||||
|
||||
/* PARMRK - not changed */
|
||||
|
||||
/* Output flags */
|
||||
|
||||
/* OPOST - forced on if not RAW */
|
||||
termios.c_oflag &= ~OPOST;
|
||||
if (!(flags & 0000040))
|
||||
termios.c_oflag |= OPOST;
|
||||
|
||||
/* ONLCR - forced on if CRMOD */
|
||||
termios.c_oflag &= ~ONLCR;
|
||||
if (flags & 0000020)
|
||||
termios.c_oflag |= ONLCR;
|
||||
|
||||
/* XTABS - forced on if XTABS */
|
||||
termios.c_oflag &= ~XTABS;
|
||||
if (flags & 0006000)
|
||||
termios.c_oflag |= XTABS;
|
||||
|
||||
/* CLOCAL - not changed */
|
||||
/* CREAD - forced on (receiver is always enabled) */
|
||||
termios.c_cflag |= CREAD;
|
||||
|
||||
/* CSIZE - CS5-CS8 correspond directly to BITS5-BITS8 */
|
||||
termios.c_cflag = (termios.c_cflag & ~CSIZE) | ((flags & 0001400) >> (8-2));
|
||||
|
||||
/* CSTOPB - not changed */
|
||||
/* HUPCL - not changed */
|
||||
/* PARENB - set if EVENP or ODDP is set */
|
||||
termios.c_cflag &= ~PARENB;
|
||||
if (flags & (0000200|0000100))
|
||||
termios.c_cflag |= PARENB;
|
||||
|
||||
/* PARODD - set if ODDP is set */
|
||||
termios.c_cflag &= ~PARODD;
|
||||
if (flags & 0000100)
|
||||
termios.c_cflag |= PARODD;
|
||||
|
||||
/* Local flags */
|
||||
|
||||
/* ECHO - set if ECHO is set */
|
||||
termios.c_lflag &= ~ECHO;
|
||||
if (flags & 0000010)
|
||||
termios.c_lflag |= ECHO;
|
||||
|
||||
/* ECHOE - not changed */
|
||||
/* ECHOK - not changed */
|
||||
/* ECHONL - not changed */
|
||||
/* ICANON - set if neither CBREAK nor RAW */
|
||||
termios.c_lflag &= ~ICANON;
|
||||
if (!(flags & (0000002|0000040)))
|
||||
termios.c_lflag |= ICANON;
|
||||
|
||||
/* IEXTEN - set if not RAW */
|
||||
/* ISIG - set if not RAW */
|
||||
termios.c_lflag &= ~(IEXTEN|ISIG);
|
||||
if (!(flags & 0000040))
|
||||
termios.c_lflag |= (IEXTEN|ISIG);
|
||||
|
||||
/* NOFLSH - not changed */
|
||||
/* TOSTOP - not changed */
|
||||
|
||||
tp->tty_termios = termios;
|
||||
setattr(tp);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* compat_setc *
|
||||
*===========================================================================*/
|
||||
PRIVATE int compat_setc(tp, tc)
|
||||
tty_t *tp;
|
||||
struct tchars *tc;
|
||||
{
|
||||
/* Translate an old TIOCSETC to the termios equivalent. */
|
||||
struct termios termios;
|
||||
|
||||
termios = tp->tty_termios;
|
||||
|
||||
termios.c_cc[VINTR] = tc->t_intrc;
|
||||
termios.c_cc[VQUIT] = tc->t_quitc;
|
||||
termios.c_cc[VSTART] = tc->t_startc;
|
||||
termios.c_cc[VSTOP] = tc->t_stopc;
|
||||
termios.c_cc[VEOL] = tc->t_brkc;
|
||||
termios.c_cc[VEOF] = tc->t_eofc;
|
||||
|
||||
tp->tty_termios = termios;
|
||||
setattr(tp);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* Table of termios line speed to sgtty line speed translations. All termios
|
||||
* speeds are present even if sgtty didn't know about them. (Now it does.)
|
||||
*/
|
||||
PRIVATE struct s2s {
|
||||
speed_t tspd;
|
||||
u8_t sgspd;
|
||||
} ts2sgs[] = {
|
||||
{ B0, 0 },
|
||||
{ B50, 50 },
|
||||
{ B75, 75 },
|
||||
{ B110, 1 },
|
||||
{ B134, 134 },
|
||||
{ B200, 2 },
|
||||
{ B300, 3 },
|
||||
{ B600, 6 },
|
||||
{ B1200, 12 },
|
||||
{ B1800, 18 },
|
||||
{ B2400, 24 },
|
||||
{ B4800, 48 },
|
||||
{ B9600, 96 },
|
||||
{ B19200, 192 },
|
||||
{ B38400, 195 },
|
||||
{ B57600, 194 },
|
||||
{ B115200, 193 },
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* tspd2sgspd *
|
||||
*===========================================================================*/
|
||||
PRIVATE int tspd2sgspd(tspd)
|
||||
speed_t tspd;
|
||||
{
|
||||
/* Translate a termios speed to sgtty speed. */
|
||||
struct s2s *s;
|
||||
|
||||
for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
|
||||
if (s->tspd == tspd) return(s->sgspd);
|
||||
}
|
||||
return 96;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sgspd2tspd *
|
||||
*===========================================================================*/
|
||||
PRIVATE speed_t sgspd2tspd(sgspd)
|
||||
int sgspd;
|
||||
{
|
||||
/* Translate a sgtty speed to termios speed. */
|
||||
struct s2s *s;
|
||||
|
||||
for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
|
||||
if (s->sgspd == sgspd) return(s->tspd);
|
||||
}
|
||||
return B9600;
|
||||
}
|
||||
|
||||
#if ENABLE_BINCOMPAT
|
||||
/*===========================================================================*
|
||||
* do_ioctl_compat *
|
||||
*===========================================================================*/
|
||||
PRIVATE void do_ioctl_compat(tp, m_ptr)
|
||||
tty_t *tp;
|
||||
message *m_ptr;
|
||||
{
|
||||
/* Handle the old sgtty ioctl's that packed the sgtty or tchars struct into
|
||||
* the Minix message. Efficient then, troublesome now.
|
||||
*/
|
||||
int minor, proc, func, result, r;
|
||||
long flags, erki, spek;
|
||||
u8_t erase, kill, intr, quit, xon, xoff, brk, eof, ispeed, ospeed;
|
||||
struct sgttyb sg;
|
||||
struct tchars tc;
|
||||
message reply_mess;
|
||||
|
||||
minor = m_ptr->TTY_LINE;
|
||||
proc = m_ptr->IO_ENDPT;
|
||||
func = m_ptr->REQUEST;
|
||||
spek = m_ptr->m2_l1;
|
||||
flags = m_ptr->m2_l2;
|
||||
|
||||
switch(func)
|
||||
{
|
||||
case (('t'<<8) | 8): /* TIOCGETP */
|
||||
r = compat_getp(tp, &sg);
|
||||
erase = sg.sg_erase;
|
||||
kill = sg.sg_kill;
|
||||
ispeed = sg.sg_ispeed;
|
||||
ospeed = sg.sg_ospeed;
|
||||
flags = sg.sg_flags;
|
||||
erki = ((long)ospeed<<24) | ((long)ispeed<<16) | ((long)erase<<8) |kill;
|
||||
break;
|
||||
case (('t'<<8) | 18): /* TIOCGETC */
|
||||
r = compat_getc(tp, &tc);
|
||||
intr = tc.t_intrc;
|
||||
quit = tc.t_quitc;
|
||||
xon = tc.t_startc;
|
||||
xoff = tc.t_stopc;
|
||||
brk = tc.t_brkc;
|
||||
eof = tc.t_eofc;
|
||||
erki = ((long)intr<<24) | ((long)quit<<16) | ((long)xon<<8) | xoff;
|
||||
flags = (eof << 8) | brk;
|
||||
break;
|
||||
case (('t'<<8) | 17): /* TIOCSETC */
|
||||
tc.t_stopc = (spek >> 0) & 0xFF;
|
||||
tc.t_startc = (spek >> 8) & 0xFF;
|
||||
tc.t_quitc = (spek >> 16) & 0xFF;
|
||||
tc.t_intrc = (spek >> 24) & 0xFF;
|
||||
tc.t_brkc = (flags >> 0) & 0xFF;
|
||||
tc.t_eofc = (flags >> 8) & 0xFF;
|
||||
r = compat_setc(tp, &tc);
|
||||
break;
|
||||
case (('t'<<8) | 9): /* TIOCSETP */
|
||||
sg.sg_erase = (spek >> 8) & 0xFF;
|
||||
sg.sg_kill = (spek >> 0) & 0xFF;
|
||||
sg.sg_ispeed = (spek >> 16) & 0xFF;
|
||||
sg.sg_ospeed = (spek >> 24) & 0xFF;
|
||||
sg.sg_flags = flags;
|
||||
r = compat_setp(tp, &sg);
|
||||
break;
|
||||
default:
|
||||
r = ENOTTY;
|
||||
}
|
||||
reply_mess.m_type = TASK_REPLY;
|
||||
reply_mess.REP_ENDPT = m_ptr->IO_ENDPT;
|
||||
reply_mess.REP_STATUS = r;
|
||||
reply_mess.m2_l1 = erki;
|
||||
reply_mess.m2_l2 = flags;
|
||||
send(m_ptr->m_source, &reply_mess);
|
||||
}
|
||||
#endif /* ENABLE_BINCOMPAT */
|
||||
#endif /* ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT */
|
||||
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#undef lock
|
||||
#undef unlock
|
||||
|
||||
#define TTY_REVIVE 6767
|
||||
|
||||
/* First minor numbers for the various classes of TTY devices. */
|
||||
#define CONS_MINOR 0
|
||||
#define LOG_MINOR 15
|
||||
@ -66,20 +68,27 @@ typedef struct tty {
|
||||
char tty_inrevived; /* set to 1 if revive callback is pending */
|
||||
int tty_incaller; /* process that made the call (usually FS) */
|
||||
int tty_inproc; /* process that wants to read from tty */
|
||||
vir_bytes tty_in_vir; /* virtual address where data is to go */
|
||||
vir_bytes tty_in_vir_g; /* address or grant where data is to go */
|
||||
vir_bytes tty_in_vir_offset; /* offset into grant */
|
||||
int tty_in_safe; /* nonzero: safecopies (in_vir is grantid) */
|
||||
int tty_inleft; /* how many chars are still needed */
|
||||
int tty_incum; /* # chars input so far */
|
||||
int tty_outrepcode; /* reply code, TASK_REPLY or REVIVE */
|
||||
int tty_outrevived; /* set to 1 if revive callback is pending */
|
||||
int tty_outcaller; /* process that made the call (usually FS) */
|
||||
int tty_outproc; /* process that wants to write to tty */
|
||||
vir_bytes tty_out_vir; /* virtual address where data comes from */
|
||||
vir_bytes tty_out_vir_g; /* address or grant where data comes from */
|
||||
vir_bytes tty_out_vir_offset; /* offset into grant */
|
||||
int tty_out_safe; /* nonzero: safecopies (out_vir is grantid) */
|
||||
int tty_outleft; /* # chars yet to be output */
|
||||
int tty_outcum; /* # chars output so far */
|
||||
int tty_iocaller; /* process that made the call (usually FS) */
|
||||
int tty_iorevived; /* set to 1 if revive callback is pending */
|
||||
int tty_ioproc; /* process that wants to do an ioctl */
|
||||
int tty_iostatus; /* result */
|
||||
int tty_ioreq; /* ioctl request code */
|
||||
vir_bytes tty_iovir; /* virtual address of ioctl buffer */
|
||||
int tty_io_safe; /* safe copy mode? (iovir is grant id) */
|
||||
vir_bytes tty_iovir_g; /* virtual address of ioctl buffer or grant */
|
||||
|
||||
/* select() data */
|
||||
int tty_select_ops; /* which operations are interesting */
|
||||
@ -146,7 +155,8 @@ _PROTOTYPE( int in_process, (struct tty *tp, char *buf, int count) );
|
||||
_PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos,
|
||||
char *bend, int *icount, int *ocount) );
|
||||
_PROTOTYPE( void tty_wakeup, (clock_t now) );
|
||||
_PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
|
||||
#define tty_reply(c, r, p, s) tty_reply_f(__FILE__, __LINE__, (c), (r), (p), (s))
|
||||
_PROTOTYPE( void tty_reply_f, (char *f, int l, int code, int replyee, int proc_nr,
|
||||
int status) );
|
||||
_PROTOTYPE( int tty_devnop, (struct tty *tp, int try) );
|
||||
_PROTOTYPE( int select_try, (struct tty *tp, int ops) );
|
||||
@ -161,7 +171,7 @@ _PROTOTYPE( void rs_interrupt, (message *m) );
|
||||
_PROTOTYPE( void kputc, (int c) );
|
||||
_PROTOTYPE( void cons_stop, (void) );
|
||||
_PROTOTYPE( void do_new_kmess, (message *m) );
|
||||
_PROTOTYPE( void do_diagnostics, (message *m) );
|
||||
_PROTOTYPE( void do_diagnostics, (message *m, int safe) );
|
||||
_PROTOTYPE( void do_get_kmess, (message *m) );
|
||||
_PROTOTYPE( void scr_init, (struct tty *tp) );
|
||||
_PROTOTYPE( void toggle_scroll, (void) );
|
||||
@ -173,7 +183,7 @@ _PROTOTYPE( void do_video, (message *m) );
|
||||
/* keyboard.c */
|
||||
_PROTOTYPE( void kb_init, (struct tty *tp) );
|
||||
_PROTOTYPE( void kb_init_once, (void) );
|
||||
_PROTOTYPE( int kbd_loadmap, (message *m) );
|
||||
_PROTOTYPE( int kbd_loadmap, (message *m, int safe) );
|
||||
_PROTOTYPE( void do_panic_dumps, (message *m) );
|
||||
_PROTOTYPE( void do_fkey_ctl, (message *m) );
|
||||
_PROTOTYPE( void kbd_interrupt, (message *m) );
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user