From: Ben Gras Date: Tue, 20 Jun 2006 09:02:54 +0000 (+0000) Subject: . Safe I/O, ioctl() and DIAGNOSTICS variants conversion - safe copies, X-Git-Tag: v3.1.3~327 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch03.html?a=commitdiff_plain;h=1c8b206a5d97365b0ef8edb14e54002750fd38e7;p=minix.git . 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 --- diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index a5d87b782..79edcd8c4 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -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 diff --git a/drivers/tty/console.c b/drivers/tty/console.c index b49acb545..57984be33 100644 --- a/drivers/tty/console.c +++ b/drivers/tty/console.c @@ -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; } diff --git a/drivers/tty/keyboard.c b/drivers/tty/keyboard.c index 023807527..9b0357a23 100644 --- a/drivers/tty/keyboard.c +++ b/drivers/tty/keyboard.c @@ -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; iCOUNT; 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; diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 9e3ffd4ae..76b38dce2 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -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, + 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) { - printf("pty tty%d: copy failed (error %d)\n", s); 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 diff --git a/drivers/tty/rs232.c b/drivers/tty/rs232.c index ed6b384f5..bcaa6907e 100644 --- a/drivers/tty/rs232.c +++ b/drivers/tty/rs232.c @@ -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. */ diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c index fc5d3de43..64193dd97 100644 --- a/drivers/tty/tty.c +++ b/drivers/tty/tty.c @@ -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 -#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT -#include -#endif #include #include #include @@ -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 */ - diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h index fb7da506e..a3fba614f 100644 --- a/drivers/tty/tty.h +++ b/drivers/tty/tty.h @@ -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) );