From 3d697930dd107c20a5178887f70cd0baa848ac0d Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Wed, 11 Sep 2013 12:48:10 +0200 Subject: [PATCH] TTY: use libchardriver; clean up - writing to a PTY master side blocks if there is not already a blocked reader on the slave side, and select now reflects this; - internally, TTY now uses a test based on "caller != NONE" rather than "grant != GRANT_INVALID" to identify whether a call is currently ongoing; - "offset" fields have been removed as they equal the corresponding "cum" fields; - improved variable typing and function naming here and there; - various other small fixes. Change-Id: I6b51452888942e864b4e034e8c8490576184a23e --- distrib/sets/lists/minix/mi | 2 +- drivers/tty/Makefile | 4 +- drivers/tty/arch/earm/console.c | 4 +- drivers/tty/arch/earm/keyboard.c | 9 +- drivers/tty/arch/earm/rs232.c | 15 +- drivers/tty/arch/i386/console.c | 171 ++++----- drivers/tty/arch/i386/keyboard.c | 461 +++++++++++++---------- drivers/tty/arch/i386/rs232.c | 17 +- drivers/tty/pty.c | 610 ++++++++++++++++-------------- drivers/tty/tty.c | 626 +++++++++++++------------------ drivers/tty/tty.h | 44 +-- include/minix/Makefile | 2 +- include/minix/com.h | 1 - include/minix/tty.h | 28 -- include/sys/ioc_tty.h | 1 - 15 files changed, 966 insertions(+), 1029 deletions(-) delete mode 100644 include/minix/tty.h diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index 4f5a1493d..ad6db8feb 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -1221,7 +1221,7 @@ ./usr/include/minix/sysutil.h minix-sys ./usr/include/minix/termios.h minix-sys ./usr/include/minix/timers.h minix-sys -./usr/include/minix/tty.h minix-sys +./usr/include/minix/tty.h minix-sys obsolete ./usr/include/minix/type.h minix-sys ./usr/include/minix/types.h minix-sys obsolete ./usr/include/minix/u64.h minix-sys diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 6f0336eac..5575a4ccf 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -6,8 +6,8 @@ PROG= tty SRCS += tty.c pty.c -DPADD+= ${LIBSYS} ${LIBTIMERS} -LDADD+= -lsys -ltimers +DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS} +LDADD+= -lchardriver -lsys -ltimers MAN= diff --git a/drivers/tty/arch/earm/console.c b/drivers/tty/arch/earm/console.c index 3c820bcea..04a5aff34 100644 --- a/drivers/tty/arch/earm/console.c +++ b/drivers/tty/arch/earm/console.c @@ -4,7 +4,7 @@ #include "tty.h" void -do_video(message *m) +do_video(message *m, int ipc_status) { } @@ -19,7 +19,7 @@ cons_stop(void) } int -con_loadfont(message *m) +con_loadfont(endpoint_t endpt, cp_grant_id_t grant) { return 0; } diff --git a/drivers/tty/arch/earm/keyboard.c b/drivers/tty/arch/earm/keyboard.c index 7ab1ef158..cf278378b 100644 --- a/drivers/tty/arch/earm/keyboard.c +++ b/drivers/tty/arch/earm/keyboard.c @@ -19,12 +19,7 @@ do_kb_inject(message *m) } void -do_kbd(message *m) -{ -} - -void -do_kbdaux(message *m) +do_kbd(message *m, int ipc_status) { } @@ -34,7 +29,7 @@ kb_init_once(void) } int -kbd_loadmap(message *m) +kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant) { return 0; } diff --git a/drivers/tty/arch/earm/rs232.c b/drivers/tty/arch/earm/rs232.c index f8b40cefd..9d30c8e48 100644 --- a/drivers/tty/arch/earm/rs232.c +++ b/drivers/tty/arch/earm/rs232.c @@ -237,11 +237,11 @@ rs_write(register tty_t *tp, int try) if (tp->tty_outcaller == KERNEL) { /* We're trying to print on kernel's behalf */ memcpy(rs->ohead, - (void *) tp->tty_outgrant + tp->tty_outoffset, + (char *) tp->tty_outgrant + tp->tty_outcum, count); } else { if ((r = sys_safecopyfrom(tp->tty_outcaller, - tp->tty_outgrant, tp->tty_outoffset, + tp->tty_outgrant, tp->tty_outcum, (vir_bytes) rs->ohead, count)) != OK) { return 0; } @@ -262,24 +262,21 @@ rs_write(register tty_t *tp, int try) rs_ostart(rs); if ((rs->ohead += ocount) >= bufend(rs->obuf)) rs->ohead -= buflen(rs->obuf); - tp->tty_outoffset += count; tp->tty_outcum += count; if ((tp->tty_outleft -= count) == 0) { /* Output is finished, reply to the writer. */ - tty_reply(DEV_REVIVE, tp->tty_outcaller, - tp->tty_outproc, tp->tty_outgrant, + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, tp->tty_outcum); tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } } if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) { /* Oops, the line has hung up. */ - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, EIO); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO); tp->tty_outleft = tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } return 1; diff --git a/drivers/tty/arch/i386/console.c b/drivers/tty/arch/i386/console.c index 16652bf30..d8034190c 100644 --- a/drivers/tty/arch/i386/console.c +++ b/drivers/tty/arch/i386/console.c @@ -18,16 +18,10 @@ #include #include -#include #include #include #include #include -#include -#include -#include -#include -#include #include "tty.h" /* Set this to 1 if you want console output duplicated on the first @@ -142,6 +136,18 @@ static void vid_vid_copy(int src, int dst, int count); static void get_6845(int reg, unsigned *val); #endif +static int video_open(devminor_t minor, int access, endpoint_t user_endpt); +static int video_close(devminor_t minor); +static int video_ioctl(devminor_t minor, unsigned long request, + endpoint_t endpt, cp_grant_id_t grant, int flags, + endpoint_t user_endpt, cdev_id_t id); + +static struct chardriver video_tab = { + .cdr_open = video_open, + .cdr_close = video_close, + .cdr_ioctl = video_ioctl +}; + /*===========================================================================* * cons_write * *===========================================================================*/ @@ -174,16 +180,14 @@ int try; if (count > sizeof(buf)) count = sizeof(buf); if (tp->tty_outcaller == KERNEL) { /* We're trying to print on kernel's behalf */ - memcpy(buf, (void *) tp->tty_outgrant + tp->tty_outoffset, - count); + memcpy(buf, (char *) tp->tty_outgrant + tp->tty_outcum, count); } else { if ((result = sys_safecopyfrom(tp->tty_outcaller, - tp->tty_outgrant, tp->tty_outoffset, + tp->tty_outgrant, tp->tty_outcum, (vir_bytes) buf, count)) != OK) { break; } } - tp->tty_outoffset += count; tbuf = buf; /* Update terminal data structure. */ @@ -215,10 +219,10 @@ int try; /* Reply to the writer if all output is finished or if an error occured. */ if (tp->tty_outleft == 0 || result != OK) { - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, result != OK ? result : tp->tty_outcum); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, + result != OK ? result : tp->tty_outcum); tp->tty_outcum = tp->tty_outleft = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } return 0; @@ -807,83 +811,68 @@ static void beep() } } - /*===========================================================================* - * do_video * + * video_open * *===========================================================================*/ -void do_video(message *m) +static int video_open(devminor_t minor, int UNUSED(access), + endpoint_t UNUSED(user_endpt)) { - int r; - - /* Execute the requested device driver function. */ - r= EINVAL; /* just in case */ - switch (m->m_type) { - case DEV_OPEN: - /* Should grant IOPL */ - disable_console(); - tty_reply(DEV_OPEN_REPL, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, OK); - return; - case DEV_CLOSE: - reenable_console(); - tty_reply(DEV_CLOSE_REPL, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, OK); - return; - case DEV_IOCTL_S: - switch(m->REQUEST) { - case TIOCMAPMEM: - case TIOCUNMAPMEM: { - int r, do_map; - struct mapreqvm mapreqvm; - - do_map= (m->REQUEST == TIOCMAPMEM); /* else unmap */ - - r = sys_safecopyfrom(m->m_source, - (cp_grant_id_t) m->IO_GRANT, 0, - (vir_bytes) &mapreqvm, sizeof(mapreqvm)); - - if (r != OK) - { - printf("tty: sys_safecopyfrom failed\n"); - break; - } + /* Should grant IOPL */ + disable_console(); + return OK; +} - /* In safe ioctl mode, the POSITION field contains - * the endpt number of the original requestor. - * USER_ENDPT is always FS. - */ - - if(do_map) { - mapreqvm.vaddr_ret = vm_map_phys(m->POSITION, - (void *) mapreqvm.phys_offset, mapreqvm.size); - if((r = sys_safecopyto(m->m_source, - (cp_grant_id_t) m->IO_GRANT, 0, - (vir_bytes) &mapreqvm, - sizeof(mapreqvm))) != OK) { - printf("tty: sys_safecopyto failed\n"); - } - } else { - r = vm_unmap_phys(m->POSITION, - mapreqvm.vaddr, mapreqvm.size); - } - break; - } - default: - r= ENOTTY; - break; - } - break; +/*===========================================================================* + * video_close * + *===========================================================================*/ +static int video_close(devminor_t minor) +{ + reenable_console(); + return OK; +} - default: - printf( - "Warning, TTY(video) got unexpected request %d from %d\n", - m->m_type, m->m_source); - r= EINVAL; +/*===========================================================================* + * video_ioctl * + *===========================================================================*/ +static int video_ioctl(devminor_t minor, unsigned long request, + endpoint_t endpt, cp_grant_id_t grant, int flags, + endpoint_t user_endpt, cdev_id_t id) +{ + struct mapreqvm mapreqvm; + int r, do_map; + + switch (request) { + case TIOCMAPMEM: + case TIOCUNMAPMEM: + do_map = (request == TIOCMAPMEM); /* else unmap */ + + if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &mapreqvm, + sizeof(mapreqvm))) != OK) + return r; + + if (do_map) { + mapreqvm.vaddr_ret = vm_map_phys(user_endpt, + (void *) mapreqvm.phys_offset, mapreqvm.size); + r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &mapreqvm, + sizeof(mapreqvm)); + } else { + r = vm_unmap_phys(user_endpt, mapreqvm.vaddr, mapreqvm.size); } - tty_reply(DEV_REVIVE, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, r); + + return r; + + default: + return ENOTTY; + } } +/*===========================================================================* + * do_video * + *===========================================================================*/ +void do_video(message *m, int ipc_status) +{ + chardriver_process(&video_tab, m, ipc_status); +} /*===========================================================================* * beep_x * @@ -1137,12 +1126,11 @@ void select_console(int cons_line) /*===========================================================================* * con_loadfont * *===========================================================================*/ -int con_loadfont(m) -message *m; +int con_loadfont(endpoint_t endpt, cp_grant_id_t grant) { /* Load a font into the EGA or VGA adapter. */ - int result; + int r, r2; static struct sequence seq1[7] = { { GA_SEQUENCER_INDEX, 0x00, 0x01 }, { GA_SEQUENCER_INDEX, 0x02, 0x04 }, @@ -1164,17 +1152,14 @@ message *m; seq2[6].value= color ? 0x0E : 0x0A; - result = ga_program(seq1); /* bring font memory into view */ + r = ga_program(seq1); /* bring font memory into view */ + if (r != OK) return r; - if(sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0, - (vir_bytes) font_memory, GA_FONT_SIZE) != OK) { - printf("tty: copying from %d failed\n", m->m_source); - return EFAULT; - } + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) font_memory, GA_FONT_SIZE); - result = ga_program(seq2); /* restore */ + r2 = ga_program(seq2); /* restore */ - return(result); + return(r != OK ? r : r2); } /*===========================================================================* diff --git a/drivers/tty/arch/i386/keyboard.c b/drivers/tty/arch/i386/keyboard.c index 6a737fa34..3b601da33 100644 --- a/drivers/tty/arch/i386/keyboard.c +++ b/drivers/tty/arch/i386/keyboard.c @@ -123,19 +123,17 @@ static obs_t sfkey_obs[12]; /* observers for SHIFT F1-F12 */ static struct kbd { - int minor; + devminor_t minor; int nr_open; char buf[KBD_BUFSZ]; int offset; int avail; - int req_size; - int req_proc; + size_t req_size; + cdev_id_t req_id; cp_grant_id_t req_grant; - vir_bytes req_addr_offset; - int incaller; - int select_ops; - int select_proc; - int select_minor; /* sanity check only, can be removed */ + endpoint_t req_caller; + unsigned int select_ops; + endpoint_t select_proc; } kbd, kbdaux; /* Data that is to be sent to the keyboard. Each byte is ACKed by the @@ -155,7 +153,6 @@ static long sticky_alt_mode = 0; static long debug_fkeys = 1; static timer_t tmr_kbd_wd; -static void handle_req(struct kbd *kbdp, message *m); static void kbc_cmd0(int cmd); static void kbc_cmd1(int cmd, int data); static int kbc_read(void); @@ -171,220 +168,284 @@ static int kb_read(struct tty *tp, int try); static unsigned map_key(int scode); static void kbd_watchdog(timer_t *tmrp); -int micro_delay(u32_t usecs) +static int kbd_open(devminor_t minor, int access, endpoint_t user_endpt); +static int kbd_close(devminor_t minor); +static ssize_t kbd_read(devminor_t minor, u64_t position, endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); +static ssize_t kbd_write(devminor_t minor, u64_t position, endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); +static int kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, + cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id); +static int kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id); +static int kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt); + +static struct chardriver kbd_tab = { + .cdr_open = kbd_open, + .cdr_close = kbd_close, + .cdr_read = kbd_read, + .cdr_write = kbd_write, + .cdr_ioctl = kbd_ioctl, + .cdr_cancel = kbd_cancel, + .cdr_select = kbd_select +}; + +/*===========================================================================* + * line2kbd * + *===========================================================================*/ +static struct kbd * +line2kbd(devminor_t minor) { - /* TTY can't use the library micro_delay() as that calls PM. */ - tickdelay(micros_to_ticks(usecs)); - return OK; + switch (minor) { + case KBD_MINOR: return &kbd; + case KBDAUX_MINOR: return &kbdaux; + default: return NULL; + } } /*===========================================================================* - * do_kbd * + * kbd_open * *===========================================================================*/ -void do_kbd(message *m) +static int +kbd_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt)) { - handle_req(&kbd, m); -} + struct kbd *kbdp; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + kbdp->nr_open++; + return OK; +} /*===========================================================================* - * do_kbdaux * + * kbd_close * *===========================================================================*/ -void do_kbdaux(message *m) +static int +kbd_close(devminor_t minor) { - handle_req(&kbdaux, m); + struct kbd *kbdp; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + + kbdp->nr_open--; + if (kbdp->nr_open < 0) { + printf("TTY(kbd): open count is negative\n"); + kbdp->nr_open= 0; + } + if (kbdp->nr_open == 0) + kbdp->avail= 0; + + return OK; } +/*===========================================================================* + * kbd_read * + *===========================================================================*/ +static ssize_t +kbd_read(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id) +{ + ssize_t n, r; + struct kbd *kbdp; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + + /* We handle only one request at a time. */ + if (kbdp->req_size) + return EIO; + + if ((ssize_t) size <= 0) + return EINVAL; + + /* If no data is available, suspend the caller. */ + if (kbdp->avail == 0) { + if (flags & FLG_OP_NONBLOCK) + return EAGAIN; + kbdp->req_size = size; + kbdp->req_id = id; + kbdp->req_grant = grant; + kbdp->req_caller = endpt; + return EDONTREPLY; + } + + /* Handle read request. */ + n = kbdp->avail; + if (n > (ssize_t) size) + n = size; + if (kbdp->offset + n > KBD_BUFSZ) + n = KBD_BUFSZ - kbdp->offset; + if (n <= 0) + panic("do_kbd(READ): bad n: %d", n); + r = sys_safecopyto(endpt, grant, 0, + (vir_bytes) &kbdp->buf[kbdp->offset], n); + if (r == OK) { + kbdp->offset = (kbdp->offset + n) % KBD_BUFSZ; + kbdp->avail -= n; + r = n; + } else + printf("TTY(kbd): copy in read kbd failed: %d\n", r); + + return r; +} /*===========================================================================* - * handle_req * + * kbd_write * *===========================================================================*/ -static void handle_req(kbdp, m) -struct kbd *kbdp; -message *m; +static ssize_t +kbd_write(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id) { - int i, n, r, ops, watch; + struct kbd *kbdp; unsigned char c; + size_t i; + int r; - /* Execute the requested device driver function. */ - r= EINVAL; /* just in case */ - switch (m->m_type) { - case DEV_OPEN: - kbdp->nr_open++; - tty_reply(DEV_OPEN_REPL, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, OK); - return; - case DEV_CLOSE: - kbdp->nr_open--; - if (kbdp->nr_open < 0) - { - printf("TTY(kbd): open count is negative\n"); - kbdp->nr_open= 0; - } - if (kbdp->nr_open == 0) - kbdp->avail= 0; - tty_reply(DEV_CLOSE_REPL, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, OK); - return; - case DEV_READ_S: - if (kbdp->req_size) - { - /* We handle only request at a time */ - r= EIO; - break; - } - if (kbdp->avail == 0) - { - if (m->FLAGS & FLG_OP_NONBLOCK) { - r = EAGAIN; - break; - } - /* Should record proc */ - kbdp->req_size= m->COUNT; - kbdp->req_proc= m->USER_ENDPT; - kbdp->req_grant= (cp_grant_id_t) m->IO_GRANT; - kbdp->req_addr_offset= 0; - kbdp->incaller= m->m_source; - return; - } + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + if (kbdp != &kbdaux) { + printf("TTY(kbd): write to keyboard not implemented\n"); + return EINVAL; + } - /* Handle read request */ - n= kbdp->avail; - if (n > m->COUNT) - n= m->COUNT; - if (kbdp->offset + n > KBD_BUFSZ) - n= KBD_BUFSZ-kbdp->offset; - if (n <= 0) - panic("do_kbd(READ): bad n: %d", n); - r= sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0, - (vir_bytes) &kbdp->buf[kbdp->offset], n); - if (r == OK) - { - kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ; - kbdp->avail -= n; - r= n; + /* + * Assume that output to AUX only happens during initialization and we + * can afford to lose input. This should be fixed at a later time. + */ + for (i = 0; i < size; i++) { + r = sys_safecopyfrom(endpt, grant, i, (vir_bytes) &c, 1); + if (r != OK) + return i ? i : r; + kbc_cmd1(KBC_WRITE_AUX, c); + } + + return r; +} + +/*===========================================================================* + * kbd_ioctl * + *===========================================================================*/ +static int +kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, + cp_grant_id_t grant, int flags, endpoint_t UNUSED(user_endpt), + cdev_id_t id) +{ + struct kbd *kbdp; + kio_leds_t leds; + kio_bell_t bell; + clock_t ticks; + unsigned char b; + int r; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + if (kbdp != &kbd) + return ENOTTY; /* we only support ioctls on keyboards now */ + + switch (request) { + case KIOCSLEDS: + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &leds, + sizeof(leds)); + if (r != OK) + return r; + + b = 0; + if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK; + if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK; + if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK; + if (kbdout.avail == 0) + kbdout.offset = 0; + if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ) { + /* Output buffer is full. Ignore this command. + * Reset ACK flag. + */ + kbdout.expect_ack = 0; } else { - printf("copy in read kbd failed: %d\n", r); + kbdout.buf[kbdout.offset+kbdout.avail] = LED_CODE; + kbdout.buf[kbdout.offset+kbdout.avail+1] = b; + kbdout.avail += 2; } + if (!kbdout.expect_ack) + kbd_send(); - break; + return OK; - case DEV_WRITE_S: - if (kbdp != &kbdaux) - { - printf("write to keyboard not implemented\n"); - r= EINVAL; - break; - } + case KIOCBELL: + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &bell, + sizeof(bell)); + if (r != OK) + return r; - /* Assume that output to AUX only happens during - * initialization and we can afford to lose input. This should - * be fixed at a later time. - */ - for (i= 0; iCOUNT; i++) - { - r= sys_safecopyfrom(m->m_source, (cp_grant_id_t) - m->IO_GRANT, i, (vir_bytes) &c, 1); - if (r != OK) - break; - kbc_cmd1(KBC_WRITE_AUX, c); - } - r= i; - break; + ticks = bell.kb_duration.tv_usec * system_hz / 1000000; + ticks += bell.kb_duration.tv_sec * system_hz; + if (!ticks) + ticks++; + beep_x(bell.kb_pitch, ticks); - case CANCEL: - kbdp->req_size= 0; - r= EAGAIN; - break; - case DEV_SELECT: - ops = m->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR); - watch = (m->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0; - - r= 0; - if (kbdp->avail && (ops & SEL_RD)) - { - r |= SEL_RD; - break; - } + return OK; - if (ops && watch) - { - kbdp->select_ops |= ops; - kbdp->select_proc= m->m_source; - kbdp->select_minor= m->DEV_MINOR; - } - assert(kbdp->minor == m->DEV_MINOR); - select_reply(DEV_SEL_REPL1, m->m_source, m->DEV_MINOR, r); - return; - case DEV_IOCTL_S: - if (kbdp == &kbd && m->REQUEST == KIOCSLEDS) - { - kio_leds_t leds; - unsigned char b; - - - r= sys_safecopyfrom(m->m_source, (cp_grant_id_t) - m->IO_GRANT, 0, (vir_bytes) &leds, - sizeof(leds)); - if (r != OK) - break; - b= 0; - if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK; - if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK; - if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK; - if (kbdout.avail == 0) - kbdout.offset= 0; - if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ) - { - /* Output buffer is full. Ignore this command. - * Reset ACK flag. - */ - kbdout.expect_ack= 0; - } - else - { - kbdout.buf[kbdout.offset+kbdout.avail]= - LED_CODE; - kbdout.buf[kbdout.offset+kbdout.avail+1]= b; - kbdout.avail += 2; - } - if (!kbdout.expect_ack) - kbd_send(); - r= OK; - break; - } - if (kbdp == &kbd && m->REQUEST == KIOCBELL) - { - kio_bell_t bell; - clock_t ticks; - - r = sys_safecopyfrom(m->m_source, (cp_grant_id_t) - m->IO_GRANT, 0, (vir_bytes) &bell, - sizeof(bell)); - if (r != OK) - break; - - ticks= bell.kb_duration.tv_usec * system_hz / 1000000; - ticks += bell.kb_duration.tv_sec * system_hz; - if (!ticks) - ticks++; - beep_x(bell.kb_pitch, ticks); - - r= OK; - break; - } - r= ENOTTY; - break; + default: + return ENOTTY; + } +} + +/*===========================================================================* + * kbd_cancel * + *===========================================================================*/ +static int +kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) +{ + struct kbd *kbdp; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + + if (kbdp->req_size > 0 && endpt == kbdp->req_caller && + id == kbdp->req_id) + return EINTR; + + return EDONTREPLY; +} + +/*===========================================================================* + * kbd_select * + *===========================================================================*/ +static int +kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt) +{ + struct kbd *kbdp; + int watch, ready_ops; + + if ((kbdp = line2kbd(minor)) == NULL) + return ENXIO; + + watch = (ops & SEL_NOTIFY); + ops &= (SEL_RD | SEL_WR | SEL_ERR); + + ready_ops = 0; + if (kbdp->avail && (ops & SEL_RD)) + ready_ops |= SEL_RD; + if (ops & SEL_WR) + ready_ops |= SEL_WR; /* writes never block */ - default: - printf("Warning, TTY(kbd) got unexpected request %d from %d\n", - m->m_type, m->m_source); - r= EINVAL; + ops &= ~ready_ops; + if (ops && watch) { + kbdp->select_ops |= ops; + kbdp->select_proc = endpt; } - tty_reply(DEV_REVIVE, m->m_source, m->USER_ENDPT, - (cp_grant_id_t) m->IO_GRANT, r); + + return ready_ops; } +/*===========================================================================* + * do_kbd * + *===========================================================================*/ +void +do_kbd(message *m, int ipc_status) +{ + chardriver_process(&kbd_tab, m, ipc_status); +} /*===========================================================================* * map_key * @@ -469,7 +530,7 @@ void kbd_interrupt(message *UNUSED(m_ptr)) if (n <= 0) panic("kbd_interrupt: bad n: %d", n); kbdp->req_size= 0; - r= sys_safecopyto(kbdp->incaller, kbdp->req_grant, 0, + r= sys_safecopyto(kbdp->req_caller, kbdp->req_grant, 0, (vir_bytes)&kbdp->buf[kbdp->offset], n); if (r == OK) { @@ -478,14 +539,12 @@ void kbd_interrupt(message *UNUSED(m_ptr)) r= n; } else printf("copy in revive kbd failed: %d\n", r); - tty_reply(DEV_REVIVE, kbdp->incaller, kbdp->req_proc, - kbdp->req_grant, r); - kbdp->req_grant = GRANT_INVALID; + chardriver_reply_task(kbdp->req_caller, kbdp->req_id, r); + kbdp->req_caller = NONE; } /* Only satisfy pending select if characters weren't just read. */ if (kbdp->avail && (kbdp->select_ops & SEL_RD)) { - assert(kbdp->select_minor == kbdp->minor); - select_reply(DEV_SEL_REPL2, kbdp->select_proc, kbdp->minor, + chardriver_reply_select(kbdp->select_proc, kbdp->minor, SEL_RD); kbdp->select_ops &= ~SEL_RD; } @@ -1024,12 +1083,10 @@ void kb_init_once(void) /*===========================================================================* * kbd_loadmap * *===========================================================================*/ -int kbd_loadmap(m) -message *m; +int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant) { /* Load a new keymap. */ - return sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT, - 0, (vir_bytes) keymap, (vir_bytes) sizeof(keymap)); + return sys_safecopyfrom(endpt, grant, 0, (vir_bytes) keymap, sizeof(keymap)); } /*===========================================================================* diff --git a/drivers/tty/arch/i386/rs232.c b/drivers/tty/arch/i386/rs232.c index 21821627d..9fe52d2ab 100644 --- a/drivers/tty/arch/i386/rs232.c +++ b/drivers/tty/arch/i386/rs232.c @@ -246,10 +246,11 @@ static int rs_write(register tty_t *tp, int try) /* Copy from user space to the RS232 output buffer. */ if (tp->tty_outcaller == KERNEL) { /* We're trying to print on kernel's behalf */ - memcpy(rs->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset, count); + memcpy(rs->ohead, (char *) tp->tty_outgrant + tp->tty_outcum, + count); } else { if ((r = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant, - tp->tty_outoffset, (vir_bytes) rs->ohead, count)) != OK) + tp->tty_outcum, (vir_bytes) rs->ohead, count)) != OK) printf("TTY: sys_safecopyfrom() failed: %d", r); } @@ -265,22 +266,20 @@ static int rs_write(register tty_t *tp, int try) rs_ostart(rs); if ((rs->ohead += ocount) >= bufend(rs->obuf)) rs->ohead -= buflen(rs->obuf); - tp->tty_outoffset += count; tp->tty_outcum += count; if ((tp->tty_outleft -= count) == 0) { /* Output is finished, reply to the writer. */ - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, tp->tty_outcum); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, + tp->tty_outcum); tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } } if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) { /* Oops, the line has hung up. */ - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, EIO); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO); tp->tty_outleft = tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } return 1; diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 8b6bc30ef..f59de6374 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -9,20 +9,16 @@ * This file takes care of copying data between the tty/pty device pairs and * the open/read/write/close calls on the pty devices. The TTY task takes * care of the input and output processing (interrupt, backspace, raw I/O, - * etc.) using the pty_read() and pty_write() functions as the "keyboard" and - * "screen" functions of the ttypX devices. + * etc.) using the pty_slave_read() and pty_slave_write() functions as the + * "keyboard" and "screen" functions of the ttypX devices. * Be careful when reading this code, the terms "reading" and "writing" are - * used both for the tty and the pty end of the pseudo tty. Writes to one - * end are to be read at the other end and vice-versa. + * used both for the tty (slave) and the pty (master) end of the pseudo tty. + * Writes to one end are to be read at the other end and vice-versa. */ #include -#include #include #include -#include -#include -#include #include "tty.h" #if NR_PTYS > 0 @@ -32,21 +28,19 @@ typedef struct pty { tty_t *tty; /* associated TTY structure */ char state; /* flags: busy, closed, ... */ - /* Read call on /dev/ptypX. */ - int rdcaller; /* process making the call (usually FS) */ - int rdproc; /* process that wants to read from the pty */ - cp_grant_id_t rdgrant; /* grant for readers address space */ - vir_bytes rdoffset; /* offset in above grant */ - int rdleft; /* # bytes yet to be read */ - int rdcum; /* # bytes written so far */ - - /* Write call to /dev/ptypX. */ - int wrcaller; /* process making the call (usually FS) */ - int wrproc; /* process that wants to write to the pty */ - cp_grant_id_t wrgrant; /* grant for writers address space */ - vir_bytes wroffset; /* offset in above grant */ - int wrleft; /* # bytes yet to be written */ - int wrcum; /* # bytes written so far */ + /* Read call on master (/dev/ptypX). */ + endpoint_t rdcaller; /* process making the call, or NONE if none */ + cdev_id_t rdid; /* ID of suspended read request */ + cp_grant_id_t rdgrant; /* grant for reader's address space */ + size_t rdleft; /* # bytes yet to be read */ + size_t rdcum; /* # bytes written so far */ + + /* Write call to master (/dev/ptypX). */ + endpoint_t wrcaller; /* process making the call, or NONE if none*/ + cdev_id_t wrid; /* ID of suspended write request */ + cp_grant_id_t wrgrant; /* grant for writer's address space */ + size_t wrleft; /* # bytes yet to be written */ + size_t wrcum; /* # bytes written so far */ /* Output buffer. */ int ocount; /* # characters in the buffer */ @@ -54,9 +48,8 @@ typedef struct pty { char obuf[2048]; /* buffer for bytes going to the pty reader */ /* select() data. */ - int select_ops; /* Which operations do we want to know about? */ - int select_proc; /* Who wants to know about it? */ - dev_t select_minor; /* sanity check only, can be removed */ + unsigned int select_ops; /* Which operations do we want to know about? */ + endpoint_t select_proc; /* Who wants to know about it? */ } pty_t; #define TTY_ACTIVE 0x01 /* tty is open/active */ @@ -66,159 +59,288 @@ typedef struct pty { static pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */ -static int pty_write(tty_t *tp, int try); -static void pty_echo(tty_t *tp, int c); static void pty_start(pty_t *pp); static void pty_finish(pty_t *pp); -static int pty_read(tty_t *tp, int try); -static int pty_close(tty_t *tp, int try); -static int pty_icancel(tty_t *tp, int try); -static int pty_ocancel(tty_t *tp, int try); -static void pty_select(tty_t *tp, message *m); + +static int pty_master_open(devminor_t minor, int access, + endpoint_t user_endpt); +static int pty_master_close(devminor_t minor); +static ssize_t pty_master_read(devminor_t minor, u64_t position, + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id); +static ssize_t pty_master_write(devminor_t minor, u64_t position, + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id); +static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id); +static int pty_master_select(devminor_t minor, unsigned int ops, + endpoint_t endpt); + +static struct chardriver pty_master_tab = { + .cdr_open = pty_master_open, + .cdr_close = pty_master_close, + .cdr_read = pty_master_read, + .cdr_write = pty_master_write, + .cdr_cancel = pty_master_cancel, + .cdr_select = pty_master_select +}; /*===========================================================================* - * do_pty * + * pty_master_open * *===========================================================================*/ -void do_pty(tty_t *tp, message *m_ptr) +static int pty_master_open(devminor_t minor, int UNUSED(access), + endpoint_t UNUSED(user_endpt)) { -/* Perform an open/close/read/write call on a /dev/ptypX device. */ - pty_t *pp = tp->tty_priv; + tty_t *tp; + pty_t *pp; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; + + if (pp->state & PTY_ACTIVE) + return EIO; + + pp->state |= PTY_ACTIVE; + pp->rdcum = 0; + pp->wrcum = 0; + + return OK; +} + +/*===========================================================================* + * pty_master_close * + *===========================================================================*/ +static int pty_master_close(devminor_t minor) +{ + tty_t *tp; + pty_t *pp; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; + + if ((pp->state & (TTY_ACTIVE | TTY_CLOSED)) != TTY_ACTIVE) { + pp->state = 0; + } else { + pp->state |= PTY_CLOSED; + sigchar(tp, SIGHUP, 1); + } + + return OK; +} + +/*===========================================================================* + * pty_master_read * + *===========================================================================*/ +static ssize_t pty_master_read(devminor_t minor, u64_t UNUSED(position), + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id) +{ + tty_t *tp; + pty_t *pp; + ssize_t r; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; + + /* Check, store information on the reader, do I/O. */ + if (pp->state & TTY_CLOSED) + return 0; /* EOF */ + + if (pp->rdcaller != NONE || pp->rdleft != 0 || pp->rdcum != 0) + return EIO; + + if (size <= 0) + return EINVAL; + + pp->rdcaller = endpt; + pp->rdid = id; + pp->rdgrant = grant; + pp->rdleft = size; + pty_start(pp); + + handle_events(tp); + + if (pp->rdleft == 0) { + pp->rdcaller = NONE; + return EDONTREPLY; /* already done */ + } + + if (flags & FLG_OP_NONBLOCK) { + r = pp->rdcum > 0 ? pp->rdcum : EAGAIN; + pp->rdleft = pp->rdcum = 0; + pp->rdcaller = NONE; + return r; + } + + return EDONTREPLY; /* do suspend */ +} + +/*===========================================================================* + * pty_master_write * + *===========================================================================*/ +static ssize_t pty_master_write(devminor_t minor, u64_t UNUSED(position), + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id) +{ + tty_t *tp; + pty_t *pp; + ssize_t r; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; + + /* Check, store information on the writer, do I/O. */ + if (pp->state & TTY_CLOSED) + return EIO; + + if (pp->wrcaller != NONE || pp->wrleft != 0 || pp->wrcum != 0) + return EIO; + + if (size <= 0) + return EINVAL; + + pp->wrcaller = endpt; + pp->wrid = id; + pp->wrgrant = grant; + pp->wrleft = size; + + handle_events(tp); + + if (pp->wrleft == 0) { + pp->wrcaller = NONE; + return EDONTREPLY; /* already done */ + } + + if (flags & FLG_OP_NONBLOCK) { + r = pp->wrcum > 0 ? pp->wrcum : EAGAIN; + pp->wrleft = pp->wrcum = 0; + pp->wrcaller = NONE; + return r; + } + + return EDONTREPLY; /* do suspend */ +} + +/*===========================================================================* + * pty_master_cancel * + *===========================================================================*/ +static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) +{ + tty_t *tp; + pty_t *pp; int r; - switch (m_ptr->m_type) { - case DEV_READ_S: - /* Check, store information on the reader, do I/O. */ - if (pp->state & TTY_CLOSED) { - r = 0; - break; - } - if (pp->rdleft != 0 || pp->rdcum != 0) { - r = EIO; - break; - } - if (m_ptr->COUNT <= 0) { - r = EINVAL; - break; - } - if (pp->rdgrant != GRANT_INVALID) { - r = ENOBUFS; - break; - } - pp->rdcaller = m_ptr->m_source; - pp->rdproc = m_ptr->USER_ENDPT; - pp->rdgrant = (cp_grant_id_t) m_ptr->IO_GRANT; - pp->rdoffset = 0; - pp->rdleft = m_ptr->COUNT; - pty_start(pp); - handle_events(tp); - if (pp->rdleft == 0) { - pp->rdgrant = GRANT_INVALID; - return; /* already done */ - } + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; - if (m_ptr->FLAGS & FLG_OP_NONBLOCK) { - r = pp->rdcum > 0 ? pp->rdcum : EAGAIN; - pp->rdleft = pp->rdcum = 0; - pp->rdgrant = GRANT_INVALID; - } else { - return; /* do suspend */ - } - break; + if (pp->rdcaller == endpt && pp->rdid == id) { + /* Cancel a read from a PTY. */ + r = pp->rdcum > 0 ? pp->rdcum : EINTR; + pp->rdleft = pp->rdcum = 0; + pp->rdcaller = NONE; + return r; + } - case DEV_WRITE_S: - /* Check, store information on the writer, do I/O. */ - if (pp->state & TTY_CLOSED) { - r = EIO; - break; - } - if (pp->wrleft != 0 || pp->wrcum != 0) { - r = EIO; - break; - } - if (m_ptr->COUNT <= 0) { - r = EINVAL; - break; - } - if (pp->wrgrant != GRANT_INVALID) { - r = ENOBUFS; - break; - } - pp->wrcaller = m_ptr->m_source; - pp->wrproc = m_ptr->USER_ENDPT; - pp->wrgrant = (cp_grant_id_t) m_ptr->IO_GRANT; - pp->wroffset = 0; - pp->wrleft = m_ptr->COUNT; - handle_events(tp); - if (pp->wrleft == 0) { - pp->wrgrant = GRANT_INVALID; - return; /* already done */ - } + if (pp->wrcaller == endpt && pp->wrid == id) { + /* Cancel a write to a PTY. */ + r = pp->wrcum > 0 ? pp->wrcum : EINTR; + pp->wrleft = pp->wrcum = 0; + pp->wrcaller = NONE; + return r; + } - if (m_ptr->FLAGS & FLG_OP_NONBLOCK) { - r = pp->wrcum > 0 ? pp->wrcum : EAGAIN; - pp->wrleft = pp->wrcum = 0; - pp->wrgrant = GRANT_INVALID; - r = EAGAIN; - } else { - return; /* do suspend */ - } - break; + /* Request not found. */ + return EDONTREPLY; +} - case DEV_OPEN: - if (!(pp->state & PTY_ACTIVE)) { - pp->state |= PTY_ACTIVE; - pp->rdcum = 0; - pp->wrcum = 0; - r = OK; - } else { - r = EIO; - } - tty_reply(DEV_OPEN_REPL, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); - return; +/*===========================================================================* + * select_try_pty * + *===========================================================================*/ +static int select_try_pty(tty_t *tp, int ops) +{ + pty_t *pp = tp->tty_priv; + int r = 0; - case DEV_CLOSE: - if ((pp->state & (TTY_ACTIVE | TTY_CLOSED)) != TTY_ACTIVE) { - pp->state = 0; - } else { - pp->state |= PTY_CLOSED; - sigchar(tp, SIGHUP, 1); - } - tty_reply(DEV_CLOSE_REPL, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, OK); - return; - - case DEV_SELECT: - pty_select(tp, m_ptr); - return; - - case CANCEL: - r = EINTR; - if (m_ptr->USER_ENDPT == pp->rdproc) { - /* Cancel a read from a PTY. */ - r = pp->rdcum > 0 ? pp->rdcum : EAGAIN; - pp->rdleft = pp->rdcum = 0; - pp->rdgrant = GRANT_INVALID; - } - if (m_ptr->USER_ENDPT == pp->wrproc) { - /* Cancel a write to a PTY. */ - r = pp->wrcum > 0 ? pp->wrcum : EAGAIN; - pp->wrleft = pp->wrcum = 0; - pp->wrgrant = GRANT_INVALID; - } - break; + if (ops & SEL_WR) { + /* Write won't block on error. */ + if (pp->state & TTY_CLOSED) r |= SEL_WR; + else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR; + else if (tp->tty_inleft > 0) r |= SEL_WR; /* There's a reader. */ + } - default: - r = EINVAL; + if (ops & SEL_RD) { + /* Read won't block on error. */ + if (pp->state & TTY_CLOSED) r |= SEL_RD; + else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD; + else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */ } - tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); + + return r; } /*===========================================================================* - * pty_write * + * select_retry_pty * *===========================================================================*/ -static int pty_write(tty_t *tp, int try) +void select_retry_pty(tty_t *tp) +{ + pty_t *pp = tp->tty_priv; + devminor_t minor; + int r; + + /* See if the pty side of a pty is ready to return a select. */ + if (pp->select_ops && (r = select_try_pty(tp, pp->select_ops))) { + minor = PTYPX_MINOR + (int) (pp - pty_table); + chardriver_reply_select(pp->select_proc, minor, r); + pp->select_ops &= ~r; + } +} + +/*===========================================================================* + * pty_master_select * + *===========================================================================*/ +static int pty_master_select(devminor_t minor, unsigned int ops, + endpoint_t endpt) +{ + tty_t *tp; + pty_t *pp; + int ready_ops, watch; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + pp = tp->tty_priv; + + watch = (ops & SEL_NOTIFY); + ops &= (SEL_RD | SEL_WR | SEL_ERR); + + ready_ops = select_try_pty(tp, ops); + + ops &= ~ready_ops; + if (ops && watch) { + pp->select_ops |= ops; + pp->select_proc = endpt; + } + + return ready_ops; +} + +/*===========================================================================* + * do_pty * + *===========================================================================*/ +void do_pty(message *m_ptr, int ipc_status) +{ +/* Process a request for a PTY master (/dev/ptypX) device. */ + + chardriver_process(&pty_master_tab, m_ptr, ipc_status); +} + +/*===========================================================================* + * pty_slave_write * + *===========================================================================*/ +static int pty_slave_write(tty_t *tp, int try) { /* (*dev_write)() routine for PTYs. Transfer bytes from the writer on * /dev/ttypX to the output buffer. @@ -226,15 +348,13 @@ static int pty_write(tty_t *tp, int try) pty_t *pp = tp->tty_priv; int count, ocount, s; - /* PTY closed down? */ if (pp->state & PTY_CLOSED) { if (try) return 1; if (tp->tty_outleft > 0) { - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, EIO); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO); tp->tty_outleft = tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } return 0; } @@ -252,11 +372,11 @@ static int pty_write(tty_t *tp, int try) /* Copy from user space to the PTY output buffer. */ if (tp->tty_outcaller == KERNEL) { /* We're trying to print on kernel's behalf */ - memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset, + memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outcum, count); } else { if ((s = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant, - tp->tty_outoffset, (vir_bytes) pp->ohead, + tp->tty_outcum, (vir_bytes) pp->ohead, count)) != OK) { break; } @@ -275,15 +395,13 @@ static int pty_write(tty_t *tp, int try) pp->ohead -= buflen(pp->obuf); pty_start(pp); - tp->tty_outoffset += count; - tp->tty_outcum += count; if ((tp->tty_outleft -= count) == 0) { /* Output is finished, reply to the writer. */ - tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc, - tp->tty_outgrant, tp->tty_outcum); + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, + tp->tty_outcum); tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; + tp->tty_outcaller = NONE; } } pty_finish(pp); @@ -291,9 +409,9 @@ static int pty_write(tty_t *tp, int try) } /*===========================================================================* - * pty_echo * + * pty_slave_echo * *===========================================================================*/ -static void pty_echo(tty_t *tp, int c) +static void pty_slave_echo(tty_t *tp, int c) { /* Echo one character. (Like pty_write, but only one character, optionally.) */ @@ -330,11 +448,10 @@ static void pty_start(pty_t *pp) if (count == 0) break; /* Copy from the output buffer to the readers address space. */ - if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, - pp->rdoffset, (vir_bytes) pp->otail, count)) != OK) { + if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum, + (vir_bytes) pp->otail, count)) != OK) { break; } - pp->rdoffset += count; /* Bookkeeping. */ pp->ocount -= count; @@ -352,19 +469,18 @@ static void pty_finish(pty_t *pp) /* Finish the read request of a PTY reader if there is at least one byte * transferred. */ + if (pp->rdcum > 0) { - tty_reply(DEV_REVIVE, pp->rdcaller, pp->rdproc, pp->rdgrant, - pp->rdcum); + chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum); pp->rdleft = pp->rdcum = 0; - pp->rdgrant = GRANT_INVALID; + pp->rdcaller = NONE; } - } /*===========================================================================* - * pty_read * + * pty_slave_read * *===========================================================================*/ -static int pty_read(tty_t *tp, int try) +static int pty_slave_read(tty_t *tp, int try) { /* Offer bytes from the PTY writer for input on the TTY. (Do it one byte at * a time, 99% of the writes will be for one byte, so no sense in being smart.) @@ -375,10 +491,10 @@ static int pty_read(tty_t *tp, int try) if (pp->state & PTY_CLOSED) { if (try) return 1; if (tp->tty_inleft > 0) { - tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc, - tp->tty_ingrant, tp->tty_incum); + chardriver_reply_task(tp->tty_incaller, tp->tty_inid, + tp->tty_incum); tp->tty_inleft = tp->tty_incum = 0; - tp->tty_ingrant = GRANT_INVALID; + tp->tty_incaller = NONE; } return 1; } @@ -393,12 +509,11 @@ static int pty_read(tty_t *tp, int try) int s; /* Transfer one character to 'c'. */ - if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wroffset, + if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wrcum, (vir_bytes) &c, 1)) != OK) { printf("pty: safecopy failed (error %d)\n", s); break; } - pp->wroffset++; /* Input processing. */ if (in_process(tp, &c, 1, -1) == 0) break; @@ -406,10 +521,9 @@ static int pty_read(tty_t *tp, int try) /* PTY writer bookkeeping. */ pp->wrcum++; if (--pp->wrleft == 0) { - tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant, - pp->wrcum); + chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum); pp->wrcum = 0; - pp->wrgrant = GRANT_INVALID; + pp->wrcaller = NONE; } } @@ -417,9 +531,9 @@ static int pty_read(tty_t *tp, int try) } /*===========================================================================* - * pty_open * + * pty_slave_open * *===========================================================================*/ -static int pty_open(tty_t *tp, int UNUSED(try)) +static int pty_slave_open(tty_t *tp, int UNUSED(try)) { /* The tty side has been opened. */ pty_t *pp = tp->tty_priv; @@ -435,9 +549,9 @@ static int pty_open(tty_t *tp, int UNUSED(try)) } /*===========================================================================* - * pty_close * + * pty_slave_close * *===========================================================================*/ -static int pty_close(tty_t *tp, int UNUSED(try)) +static int pty_slave_close(tty_t *tp, int UNUSED(try)) { /* The tty side has closed, so shut down the pty side. */ pty_t *pp = tp->tty_priv; @@ -445,17 +559,15 @@ static int pty_close(tty_t *tp, int UNUSED(try)) if (!(pp->state & PTY_ACTIVE)) return 0; if (pp->rdleft > 0) { - tty_reply(DEV_REVIVE, pp->rdcaller, pp->rdproc, pp->rdgrant, - pp->rdcum); + chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum); pp->rdleft = pp->rdcum = 0; - pp->rdgrant = GRANT_INVALID; + pp->rdcaller = NONE; } if (pp->wrleft > 0) { - tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant, - pp->wrcum); - pp->wrcum = 0; - pp->wrgrant = GRANT_INVALID; + chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum); + pp->wrleft = pp->wrcum = 0; + pp->wrcaller = NONE; } if (pp->state & PTY_CLOSED) pp->state = 0; @@ -465,27 +577,26 @@ static int pty_close(tty_t *tp, int UNUSED(try)) } /*===========================================================================* - * pty_icancel * + * pty_slave_icancel * *===========================================================================*/ -static int pty_icancel(tty_t *tp, int UNUSED(try)) +static int pty_slave_icancel(tty_t *tp, int UNUSED(try)) { /* Discard waiting input. */ pty_t *pp = tp->tty_priv; if (pp->wrleft > 0) { - tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant, - pp->wrcum + pp->wrleft); + chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum + pp->wrleft); pp->wrcum = pp->wrleft = 0; - pp->wrgrant = GRANT_INVALID; + pp->wrcaller = NONE; } return 0; } /*===========================================================================* - * pty_ocancel * + * pty_slave_ocancel * *===========================================================================*/ -static int pty_ocancel(tty_t *tp, int UNUSED(try)) +static int pty_slave_ocancel(tty_t *tp, int UNUSED(try)) { /* Drain the output buffer. */ pty_t *pp = tp->tty_priv; @@ -509,86 +620,21 @@ void pty_init(tty_t *tp) pp = tp->tty_priv = &pty_table[line]; pp->tty = tp; pp->select_ops = 0; - pp->rdgrant = GRANT_INVALID; - pp->wrgrant = GRANT_INVALID; + pp->rdcaller = NONE; + pp->wrcaller = NONE; /* Set up output queue. */ pp->ohead = pp->otail = pp->obuf; /* Fill in TTY function hooks. */ - tp->tty_devread = pty_read; - tp->tty_devwrite = pty_write; - tp->tty_echo = pty_echo; - tp->tty_icancel = pty_icancel; - tp->tty_ocancel = pty_ocancel; - tp->tty_open = pty_open; - tp->tty_close = pty_close; + tp->tty_devread = pty_slave_read; + tp->tty_devwrite = pty_slave_write; + tp->tty_echo = pty_slave_echo; + tp->tty_icancel = pty_slave_icancel; + tp->tty_ocancel = pty_slave_ocancel; + tp->tty_open = pty_slave_open; + tp->tty_close = pty_slave_close; tp->tty_select_ops = 0; } -/*===========================================================================* - * select_try_pty * - *===========================================================================*/ -static int select_try_pty(tty_t *tp, int ops) -{ - pty_t *pp = tp->tty_priv; - int r = 0; - - if (ops & SEL_WR) { - /* Write won't block on error. */ - if (pp->state & TTY_CLOSED) r |= SEL_WR; - else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR; - else r |= SEL_WR; - } - - if (ops & SEL_RD) { - /* Read won't block on error. */ - if (pp->state & TTY_CLOSED) r |= SEL_RD; - else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD; - else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */ - } - - return r; -} - -/*===========================================================================* - * select_retry_pty * - *===========================================================================*/ -void select_retry_pty(tty_t *tp) -{ - pty_t *pp = tp->tty_priv; - dev_t minor; - int r; - - /* See if the pty side of a pty is ready to return a select. */ - if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) { - minor = PTYPX_MINOR + (int) (pp - pty_table); - assert(minor == pp->select_minor); - select_reply(DEV_SEL_REPL2, pp->select_proc, minor, r); - pp->select_ops &= ~r; - } -} - -/*===========================================================================* - * pty_select * - *===========================================================================*/ -static void pty_select(tty_t *tp, message *m) -{ - pty_t *pp = tp->tty_priv; - int ops, ready_ops = 0, watch; - - ops = m->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR); - watch = (m->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0; - - ready_ops = select_try_pty(tp, ops); - - if (!ready_ops && ops && watch) { - pp->select_ops |= ops; - pp->select_proc = m->m_source; - pp->select_minor = m->DEV_MINOR; - } - - select_reply(DEV_SEL_REPL1, m->m_source, m->DEV_MINOR, ready_ops); -} - #endif /* NR_PTYS > 0 */ diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c index 387a2a6e4..e1f55dad0 100644 --- a/drivers/tty/tty.c +++ b/drivers/tty/tty.c @@ -60,11 +60,7 @@ #include #include #include -#include -#include -#include #include -#include #include "tty.h" #include @@ -101,13 +97,6 @@ struct kmessages kmess; static void tty_timed_out(timer_t *tp); static void settimer(tty_t *tty_ptr, int enable); -static void do_cancel(tty_t *tp, message *m_ptr); -static void do_ioctl(tty_t *tp, message *m_ptr); -static void do_open(tty_t *tp, message *m_ptr); -static void do_close(tty_t *tp, message *m_ptr); -static void do_read(tty_t *tp, message *m_ptr); -static void do_write(tty_t *tp, message *m_ptr); -static void do_select(tty_t *tp, message *m_ptr); static void in_transfer(tty_t *tp); static int tty_echo(tty_t *tp, int ch); static void rawecho(tty_t *tp, int ch); @@ -118,12 +107,32 @@ static void setattr(tty_t *tp); static void tty_icancel(tty_t *tp); static void tty_init(void); static void do_new_kmess(void); -static tty_t * line2tty(int line); static void set_console_line(char term[CONS_ARG]); static void set_kernel_color(char color[CONS_ARG]); static void set_color(tty_t *tp, int color); static void reset_color(tty_t *tp); +static int do_open(devminor_t minor, int access, endpoint_t user_endpt); +static int do_close(devminor_t minor); +static ssize_t do_read(devminor_t minor, u64_t position, endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); +static ssize_t do_write(devminor_t minor, u64_t position, endpoint_t endpt, + cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); +static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, + cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id); +static int do_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id); +static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt); + +static struct chardriver tty_tab = { + .cdr_open = do_open, + .cdr_close = do_close, + .cdr_read = do_read, + .cdr_write = do_write, + .cdr_ioctl = do_ioctl, + .cdr_cancel = do_cancel, + .cdr_select = do_select +}; + /* Default attributes. */ static struct termios termios_defaults = { TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, @@ -160,7 +169,7 @@ int main(void) message tty_mess; /* buffer for all incoming messages */ int ipc_status; unsigned line; - int r, code; + int r; register tty_t *tp; /* SEF local startup. */ @@ -217,7 +226,6 @@ int main(void) switch (tty_mess.m_type) { case TTY_FKEY_CONTROL: /* (un)register a fkey observer */ - case OLD_FKEY_CONTROL: /* old number */ do_fkey_ctl(&tty_mess); continue; case INPUT_EVENT: @@ -227,76 +235,34 @@ int main(void) ; /* do nothing; end switch */ } + if (!IS_DEV_RQ(tty_mess.m_type)) { + chardriver_process(&tty_tab, &tty_mess, ipc_status); + continue; + } + /* Only device requests should get to this point. * All requests have a minor device number. */ line = tty_mess.DEVICE; - if (line == CONS_MINOR || line == LOG_MINOR) { - /* /dev/log output goes to /dev/console */ - if (consoleline != CONS_MINOR) { - /* Console output must redirected */ - line = consoleline; - tty_mess.DEVICE = line; - } - } - if (line == KBD_MINOR) { - do_kbd(&tty_mess); - continue; - } else if (line == KBDAUX_MINOR) { - do_kbdaux(&tty_mess); + if (line == KBD_MINOR || line == KBDAUX_MINOR) { + do_kbd(&tty_mess, ipc_status); continue; } else if (line == VIDEO_MINOR) { - do_video(&tty_mess); + do_video(&tty_mess, ipc_status); continue; - } else { - tp = line2tty(line); - + } else if (line - PTYPX_MINOR < NR_PTYS && + tty_mess.m_type != DEV_IOCTL_S) { /* Terminals and pseudo terminals belong together. We can only * make a distinction between the two based on position in the * tty_table and not on minor number (i.e., use ispty macro). * Hence this special case. */ - if (line - PTYPX_MINOR < NR_PTYS && - tty_mess.m_type != DEV_IOCTL_S){ - do_pty(tp, &tty_mess); - continue; - } - } - - /* If the device doesn't exist or is not configured return ENXIO. */ - if (tp == NULL || ! tty_active(tp)) { - if (tty_mess.m_source == LOG_PROC_NR) - continue; - - /* Can all of these occur? Probably not. We're by far most - * likely to see DEV_OPEN, but better safe than sorry.. - */ - switch (tty_mess.m_type) { - case DEV_OPEN: code = DEV_OPEN_REPL; break; - case DEV_CLOSE: code = DEV_CLOSE_REPL; break; - default: code = DEV_REVIVE; break; - } - - tty_reply(code, tty_mess.m_source, tty_mess.USER_ENDPT, - (cp_grant_id_t) tty_mess.IO_GRANT, ENXIO); + do_pty(&tty_mess, ipc_status); continue; } /* Execute the requested device driver function. */ - switch (tty_mess.m_type) { - case DEV_READ_S: do_read(tp, &tty_mess); break; - case DEV_WRITE_S: do_write(tp, &tty_mess); break; - case DEV_IOCTL_S: do_ioctl(tp, &tty_mess); 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; - case CANCEL: do_cancel(tp, &tty_mess); break; - default: - printf("Warning, TTY got unexpected request %d from %d\n", - tty_mess.m_type, tty_mess.m_source); - tty_reply(DEV_REVIVE, tty_mess.m_source, tty_mess.USER_ENDPT, - (cp_grant_id_t) tty_mess.IO_GRANT, EINVAL); - } + chardriver_process(&tty_tab, &tty_mess, ipc_status); } return 0; @@ -305,47 +271,41 @@ int main(void) static void set_color(tty_t *tp, int color) { - message msg; char buf[8]; buf[0] = '\033'; snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color); - memset(&msg, 0, sizeof(msg)); - msg.m_source = KERNEL; - msg.IO_GRANT = buf; - msg.COUNT = sizeof(buf); - do_write(tp, &msg); + do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf), + FLG_OP_NONBLOCK, 0); } static void reset_color(tty_t *tp) { - message msg; char buf[8]; #define SGR_COLOR_RESET 39 buf[0] = '\033'; snprintf(&buf[1], sizeof(buf) - 1, "[0;%dm", SGR_COLOR_RESET); - memset(&msg, 0, sizeof(msg)); - msg.m_source = KERNEL; - msg.IO_GRANT = buf; - msg.COUNT = sizeof(buf); - do_write(tp, &msg); + do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf), + FLG_OP_NONBLOCK, 0); } -static tty_t * -line2tty(int line) +tty_t * +line2tty(devminor_t line) { /* Convert a terminal line to tty_table pointer */ tty_t* tp; + /* /dev/log goes to /dev/console, and both may be redirected. */ + if (line == CONS_MINOR || line == LOG_MINOR) + line = consoleline; + if (line == KBD_MINOR || line == KBDAUX_MINOR || line == VIDEO_MINOR) { return(NULL); } else if ((line - CONS_MINOR) < NR_CONS) { tp = tty_addr(line - CONS_MINOR); - } else if (line == LOG_MINOR) { - tp = tty_addr(consoleline); } else if ((line - RS232_MINOR) < NR_RS_LINES) { tp = tty_addr(line - RS232_MINOR + NR_CONS); } else if ((line - TTYPX_MINOR) < NR_PTYS) { @@ -356,6 +316,9 @@ line2tty(int line) tp = NULL; } + if (tp != NULL && !tty_active(tp)) + tp = NULL; + return(tp); } @@ -430,7 +393,7 @@ set_console_line(char term[CONS_ARG]) } /* Serial lines */ - assert(NR_RS_LINES <= 9);/* bellow assumes this is the case */ + assert(NR_RS_LINES <= 9);/* below assumes this is the case */ for (i = 0; i < NR_RS_LINES; i++) { char sercons[6]; strlcpy(sercons, "tty00", sizeof(sercons)); @@ -465,7 +428,6 @@ do_new_kmess(void) static int prev_next = 0; int next, bytes, copy, restore = 0; tty_t *tp, rtp; - message print_kmsg; assert(_minix_kerninfo); kmess_ptr = _minix_kerninfo->kmessages; @@ -491,7 +453,7 @@ do_new_kmess(void) } tp = line2tty(consoleline); - if (tp == NULL || !tty_active(tp)) + if (tp == NULL) panic("Don't know where to send kernel messages"); if (tp->tty_outleft > 0) { /* Terminal is already printing */ @@ -502,11 +464,9 @@ do_new_kmess(void) if (kernel_msg_color != 0) set_color(tp, kernel_msg_color); - memset(&print_kmsg, 0, sizeof(print_kmsg)); - print_kmsg.m_source = KERNEL; - print_kmsg.IO_GRANT = kernel_buf_copy; - print_kmsg.COUNT = bytes; - do_write(tp, &print_kmsg); + do_write(tp->tty_minor, 0, KERNEL, + (cp_grant_id_t) kernel_buf_copy, bytes, + FLG_OP_NONBLOCK, 0); if (kernel_msg_color != 0) reset_color(tp); if (restore) { @@ -541,141 +501,138 @@ static void sef_cb_signal_handler(int signo) /*===========================================================================* * do_read * *===========================================================================*/ -static void do_read(tp, m_ptr) -register tty_t *tp; /* pointer to tty struct */ -register message *m_ptr; /* pointer to message sent to the task */ +static ssize_t do_read(devminor_t minor, u64_t UNUSED(position), + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id) { /* A process wants to read from a terminal. */ + tty_t *tp; int r; + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + /* 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) { - r = EIO; - } else - if (m_ptr->COUNT <= 0) { - r = EINVAL; - } else if (tp->tty_ingrant != GRANT_INVALID) { - /* This is actually a fundamental problem with TTY; it can handle - * only one reader per minor device. If we don't return an error, - * we'll overwrite the previous reader and that process will get - * stuck forever. */ - r = ENOBUFS; - } else { - /* Copy information from the message to the tty struct. */ - tp->tty_incaller = m_ptr->m_source; - tp->tty_inproc = m_ptr->USER_ENDPT; - tp->tty_ingrant = (cp_grant_id_t) m_ptr->IO_GRANT; - tp->tty_inoffset = 0; - tp->tty_inleft = m_ptr->COUNT; - - if (!(tp->tty_termios.c_lflag & ICANON) - && tp->tty_termios.c_cc[VTIME] > 0) { - if (tp->tty_termios.c_cc[VMIN] == 0) { - /* MIN & TIME specify a read timer that finishes the - * read in TIME/10 seconds if no bytes are available. - */ - settimer(tp, TRUE); - tp->tty_min = 1; - } else { - /* MIN & TIME specify an inter-byte timer that may - * have to be cancelled if there are no bytes yet. - */ - if (tp->tty_eotct == 0) { - settimer(tp, FALSE); - tp->tty_min = tp->tty_termios.c_cc[VMIN]; - } + if (tp->tty_incaller != NONE || tp->tty_inleft > 0) + return EIO; + if (size <= 0) + return EINVAL; + + /* Copy information from the message to the tty struct. */ + tp->tty_incaller = endpt; + tp->tty_inid = id; + tp->tty_ingrant = grant; + assert(tp->tty_incum == 0); + tp->tty_inleft = size; + + if (!(tp->tty_termios.c_lflag & ICANON) && tp->tty_termios.c_cc[VTIME] > 0) { + if (tp->tty_termios.c_cc[VMIN] == 0) { + /* MIN & TIME specify a read timer that finishes the + * read in TIME/10 seconds if no bytes are available. + */ + settimer(tp, TRUE); + tp->tty_min = 1; + } else { + /* MIN & TIME specify an inter-byte timer that may + * have to be cancelled if there are no bytes yet. + */ + if (tp->tty_eotct == 0) { + settimer(tp, FALSE); + tp->tty_min = tp->tty_termios.c_cc[VMIN]; } } + } - /* Anything waiting in the input buffer? Clear it out... */ - in_transfer(tp); - /* ...then go back for more. */ - handle_events(tp); - if (tp->tty_inleft == 0) { - return; /* already done */ - } + /* Anything waiting in the input buffer? Clear it out... */ + in_transfer(tp); + /* ...then go back for more. */ + handle_events(tp); + if (tp->tty_inleft == 0) + return EDONTREPLY; /* already done */ - /* There were no bytes in the input queue available. */ - if (m_ptr->FLAGS & FLG_OP_NONBLOCK) { - tty_icancel(tp); - r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN; - tp->tty_inleft = tp->tty_incum = 0; - tp->tty_ingrant = GRANT_INVALID; - } else { - return; /* suspend the caller */ - } + /* There were no bytes in the input queue available. */ + if (flags & FLG_OP_NONBLOCK) { + tty_icancel(tp); + r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN; + tp->tty_inleft = tp->tty_incum = 0; + tp->tty_incaller = NONE; + return r; } - tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); + if (tp->tty_select_ops) - select_retry(tp); + select_retry(tp); + + return EDONTREPLY; /* suspend the caller */ } /*===========================================================================* * do_write * *===========================================================================*/ -static void do_write(tp, m_ptr) -register tty_t *tp; -register message *m_ptr; /* pointer to message sent to the task */ +static ssize_t do_write(devminor_t minor, u64_t UNUSED(position), + endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags, + cdev_id_t id) { /* A process wants to write on a terminal. */ + tty_t *tp; int r; + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + /* Check if there is already a process hanging in a write, check if the * parameters are correct, do I/O. */ - if (tp->tty_outleft > 0) { - r = EIO; - } else - if (m_ptr->COUNT <= 0) { - r = EINVAL; - } else { - /* Copy message parameters to the tty structure. */ - tp->tty_outcaller = m_ptr->m_source; - tp->tty_outproc = m_ptr->USER_ENDPT; - tp->tty_outgrant = (cp_grant_id_t) m_ptr->IO_GRANT; - tp->tty_outoffset = 0; - tp->tty_outleft = m_ptr->COUNT; - - /* Try to write. */ - handle_events(tp); - if (tp->tty_outleft == 0) - return; /* already done */ - - /* None or not all the bytes could be written. */ - if (m_ptr->FLAGS & FLG_OP_NONBLOCK) { - r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN; - tp->tty_outleft = tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; - } else { - return; /* suspend the caller */ - } + if (tp->tty_outcaller != NONE || tp->tty_outleft > 0) + return EIO; + if (size <= 0) + return EINVAL; + + /* Copy message parameters to the tty structure. */ + tp->tty_outcaller = endpt; + tp->tty_outid = id; + tp->tty_outgrant = grant; + assert(tp->tty_outcum == 0); + tp->tty_outleft = size; + + /* Try to write. */ + handle_events(tp); + if (tp->tty_outleft == 0) + return EDONTREPLY; /* already done */ + + /* None or not all the bytes could be written. */ + if (flags & FLG_OP_NONBLOCK) { + r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN; + tp->tty_outleft = tp->tty_outcum = 0; + tp->tty_outcaller = NONE; + return r; } - tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); + + if (tp->tty_select_ops) + select_retry(tp); + + return EDONTREPLY; /* suspend the caller */ } /*===========================================================================* * do_ioctl * *===========================================================================*/ -static void do_ioctl(tp, m_ptr) -register tty_t *tp; -message *m_ptr; /* pointer to message sent to task */ +static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, + cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id) { -/* Perform an IOCTL on this terminal. Posix termios calls are handled - * by the IOCTL system call +/* Perform an IOCTL on this terminal. POSIX termios calls are handled + * by the IOCTL system call. */ - - int r; - union { - int i; - } param; + tty_t *tp; + int i, r; size_t size; + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + /* Size of the ioctl parameter. */ - switch (m_ptr->REQUEST) { + switch (request) { case TCGETS: /* Posix tcgetattr function */ case TCSETS: /* Posix tcsetattr function, TCSANOW option */ case TCSETSW: /* Posix tcsetattr function, TCSADRAIN option */ @@ -709,60 +666,55 @@ message *m_ptr; /* pointer to message sent to task */ } r = OK; - switch (m_ptr->REQUEST) { + switch (request) { case TCGETS: /* Get the termios attributes. */ - r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, 0, - (vir_bytes) &tp->tty_termios, (vir_bytes) size); + r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &tp->tty_termios, + size); break; case TCSETSW: case TCSETSF: case TCDRAIN: if (tp->tty_outleft > 0) { - if (m_ptr->FLAGS & FLG_OP_NONBLOCK) { - r = EAGAIN; - } else { - /* Wait for all ongoing output processing to finish. */ - tp->tty_iocaller = m_ptr->m_source; - tp->tty_ioproc = m_ptr->USER_ENDPT; - tp->tty_ioreq = m_ptr->REQUEST; - tp->tty_iogrant = (cp_grant_id_t) m_ptr->IO_GRANT; - return; - } - break; + if (flags & FLG_OP_NONBLOCK) + return EAGAIN; + /* Wait for all ongoing output processing to finish. */ + tp->tty_iocaller = endpt; + tp->tty_ioid = id; + tp->tty_ioreq = request; + tp->tty_iogrant = grant; + return EDONTREPLY; /* suspend the caller */ } - if (m_ptr->REQUEST == TCDRAIN) break; - if (m_ptr->REQUEST == TCSETSF) tty_icancel(tp); + if (request == TCDRAIN) break; + if (request == TCSETSF) tty_icancel(tp); /*FALL THROUGH*/ case TCSETS: /* Set the termios attributes. */ - r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, - 0, (vir_bytes) &tp->tty_termios, (vir_bytes) size); + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &tp->tty_termios, + size); if (r != OK) break; setattr(tp); break; case TCFLSH: - r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, - 0, (vir_bytes) ¶m.i, (vir_bytes) size); + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i, size); if (r != OK) break; - switch (param.i) { - case TCIFLUSH: tty_icancel(tp); break; - case TCOFLUSH: (*tp->tty_ocancel)(tp, 0); break; - case TCIOFLUSH: tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break; - default: r = EINVAL; + switch (i) { + case TCIFLUSH: tty_icancel(tp); break; + case TCOFLUSH: (*tp->tty_ocancel)(tp, 0); break; + case TCIOFLUSH: tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break; + default: r = EINVAL; } break; case TCFLOW: - r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, - 0, (vir_bytes) ¶m.i, (vir_bytes) size); + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i, size); if (r != OK) break; - switch (param.i) { + switch (i) { case TCOOFF: case TCOON: - tp->tty_inhibited = (param.i == TCOOFF); + tp->tty_inhibited = (i == TCOOFF); tp->tty_events = 1; break; case TCIOFF: @@ -781,27 +733,24 @@ message *m_ptr; /* pointer to message sent to task */ break; case TIOCGWINSZ: - r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, 0, - (vir_bytes) &tp->tty_winsize, (vir_bytes) size); + r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &tp->tty_winsize, + size); break; case TIOCSWINSZ: - r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, - 0, (vir_bytes) &tp->tty_winsize, (vir_bytes) size); + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &tp->tty_winsize, + size); sigchar(tp, SIGWINCH, 0); break; case KIOCSMAP: /* Load a new keymap (only /dev/console). */ - if (isconsole(tp)) r = kbd_loadmap(m_ptr); + if (isconsole(tp)) r = kbd_loadmap(endpt, grant); break; - case TIOCSFON_OLD: - printf("TTY: old TIOCSFON ignored.\n"); - break; case TIOCSFON: /* Load a font into an EGA or VGA card (hs@hck.hr) */ - if (isconsole(tp)) r = con_loadfont(m_ptr); + if (isconsole(tp)) r = con_loadfont(endpt, grant); break; /* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is @@ -813,30 +762,30 @@ message *m_ptr; /* pointer to message sent to task */ r = ENOTTY; } - /* Send the reply. */ - tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); + return r; } /*===========================================================================* * do_open * *===========================================================================*/ -static void do_open(tp, m_ptr) -register tty_t *tp; -message *m_ptr; /* pointer to message sent to task */ +static int do_open(devminor_t minor, int access, endpoint_t user_endpt) { /* A tty line has been opened. Make it the callers controlling tty if * O_NOCTTY is *not* set and it is not the log device. 1 is returned if * the tty is made the controlling tty, otherwise OK or an error code. */ + tty_t *tp; int r = OK; - if (m_ptr->DEVICE == LOG_MINOR) { + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + + if (minor == LOG_MINOR) { /* The log device is a write-only diagnostics device. */ - if (m_ptr->COUNT & R_BIT) r = EACCES; + if (access & R_BIT) return EACCES; } else { - if (!(m_ptr->COUNT & O_NOCTTY)) { - tp->tty_pgrp = m_ptr->USER_ENDPT; + if (!(access & O_NOCTTY)) { + tp->tty_pgrp = user_endpt; r = 1; } tp->tty_openct++; @@ -845,20 +794,22 @@ message *m_ptr; /* pointer to message sent to task */ (*tp->tty_open)(tp, 0); } } - tty_reply(DEV_OPEN_REPL, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, r); + + return r; } /*===========================================================================* * do_close * *===========================================================================*/ -static void do_close(tp, m_ptr) -register tty_t *tp; -message *m_ptr; /* pointer to message sent to task */ +static int do_close(devminor_t minor) { /* A tty line has been closed. Clean up the line if it is the last close. */ + tty_t *tp; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; - if (m_ptr->DEVICE != LOG_MINOR && --tp->tty_openct == 0) { + if (minor != LOG_MINOR && --tp->tty_openct == 0) { tp->tty_pgrp = 0; tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); @@ -867,53 +818,49 @@ message *m_ptr; /* pointer to message sent to task */ tp->tty_winsize = winsize_defaults; setattr(tp); } - tty_reply(DEV_CLOSE_REPL, m_ptr->m_source, m_ptr->USER_ENDPT, - (cp_grant_id_t) m_ptr->IO_GRANT, OK); + + return OK; } /*===========================================================================* * do_cancel * *===========================================================================*/ -static void do_cancel(tp, m_ptr) -register tty_t *tp; -message *m_ptr; /* pointer to message sent to task */ +static int do_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) { /* A signal has been sent to a process that is hanging trying to read or write. * The pending read or write must be finished off immediately. */ - endpoint_t proc_nr; - cp_grant_id_t grant; - int mode; - int r = EDONTREPLY; + tty_t *tp; + int r; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; /* Check the parameters carefully, to avoid cancelling twice. */ - proc_nr = m_ptr->USER_ENDPT; - grant = (cp_grant_id_t) m_ptr->IO_GRANT; - mode = m_ptr->COUNT; - if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc && - tp->tty_ingrant == grant) { + r = EDONTREPLY; + if (tp->tty_inleft != 0 && endpt == tp->tty_incaller && id == tp->tty_inid) { /* Process was reading when killed. Clean up input. */ tty_icancel(tp); r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN; tp->tty_inleft = tp->tty_incum = 0; - tp->tty_ingrant = GRANT_INVALID; - } - if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc && - tp->tty_outgrant == grant) { + tp->tty_incaller = NONE; + } else if (tp->tty_outleft != 0 && endpt == tp->tty_outcaller && + id == tp->tty_outid) { /* Process was writing when killed. Clean up output. */ r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN; tp->tty_outleft = tp->tty_outcum = 0; - tp->tty_outgrant = GRANT_INVALID; - } - if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) { + tp->tty_outcaller = NONE; + } else if (tp->tty_ioreq != 0 && endpt == tp->tty_iocaller && + id == tp->tty_ioid) { /* Process was waiting for output to drain. */ - tp->tty_ioreq = 0; r = EINTR; + tp->tty_ioreq = 0; + tp->tty_iocaller = NONE; } - tp->tty_events = 1; - /* Only reply if we found a matching request. */ if (r != EDONTREPLY) - tty_reply(DEV_REVIVE, m_ptr->m_source, proc_nr, grant, r); + tp->tty_events = 1; + /* Only reply if we found a matching request. */ + return r; } int select_try(struct tty *tp, int ops) @@ -955,14 +902,43 @@ int select_retry(struct tty *tp) int ops; if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) { - assert(tp->tty_select_minor == tp->tty_minor); - select_reply(DEV_SEL_REPL2, tp->tty_select_proc, tp->tty_minor, + chardriver_reply_select(tp->tty_select_proc, tp->tty_minor, ops); tp->tty_select_ops &= ~ops; } return OK; } +/*===========================================================================* + * do_select * + *===========================================================================*/ +static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt) +{ + tty_t *tp; + int ready_ops, watch; + + if ((tp = line2tty(minor)) == NULL) + return ENXIO; + + /* Translated minor numbers are a problem when sending late replies. */ + if (tp->tty_minor != minor) + return EBADF; + + watch = (ops & SEL_NOTIFY); + ops &= (SEL_RD | SEL_WR | SEL_ERR); + + ready_ops = select_try(tp, ops); + + ops &= ~ready_ops; + if (ops && watch) { + tp->tty_select_ops |= ops; + tp->tty_select_proc = endpt; + } + + assert(tp->tty_minor == minor); + return ready_ops; +} + /*===========================================================================* * handle_events * *===========================================================================*/ @@ -979,8 +955,8 @@ tty_t *tp; /* TTY to check for events. */ * to avoid swamping the TTY task. Messages may be overwritten when the * lines are fast or when there are races between different lines, input * and output, because MINIX only provides single buffering for interrupt - * messages (in proc.c). This is handled by explicitly checking each line - * for fresh input and completed output on each interrupt. + * messages. This is handled by explicitly checking each line for fresh input + * and completed output on each interrupt. */ do { @@ -1001,10 +977,9 @@ 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) { - tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc, - tp->tty_ingrant, tp->tty_incum); + chardriver_reply_task(tp->tty_incaller, tp->tty_inid, tp->tty_incum); tp->tty_inleft = tp->tty_incum = 0; - tp->tty_ingrant = GRANT_INVALID; + tp->tty_incaller = NONE; } if (tp->tty_select_ops) { @@ -1045,10 +1020,8 @@ register tty_t *tp; /* pointer to terminal to read from */ if (++bp == bufend(buf)) { /* Temp buffer full, copy to user space. */ sys_safecopyto(tp->tty_incaller, - tp->tty_ingrant, tp->tty_inoffset, - (vir_bytes) buf, - (vir_bytes) buflen(buf)); - tp->tty_inoffset += buflen(buf); + tp->tty_ingrant, tp->tty_incum, + (vir_bytes) buf, (vir_bytes) buflen(buf)); tp->tty_incum += buflen(buf); bp = buf; } @@ -1068,19 +1041,16 @@ register tty_t *tp; /* pointer to terminal to read from */ if (bp > buf) { /* Leftover characters in the buffer. */ count = bp - buf; - sys_safecopyto(tp->tty_incaller, - tp->tty_ingrant, tp->tty_inoffset, + sys_safecopyto(tp->tty_incaller, tp->tty_ingrant, tp->tty_incum, (vir_bytes) buf, (vir_bytes) count); - tp->tty_inoffset += count; tp->tty_incum += count; } /* Usually reply to the reader, possibly even if incum == 0 (EOF). */ if (tp->tty_inleft == 0) { - tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc, - tp->tty_ingrant, tp->tty_incum); + chardriver_reply_task(tp->tty_incaller, tp->tty_inid, tp->tty_incum); tp->tty_inleft = tp->tty_incum = 0; - tp->tty_ingrant = GRANT_INVALID; + tp->tty_incaller = NONE; } } @@ -1510,9 +1480,8 @@ tty_t *tp; if (result == OK) setattr(tp); } tp->tty_ioreq = 0; - tty_reply(DEV_REVIVE, tp->tty_iocaller, tp->tty_ioproc, tp->tty_iogrant, - result); - tp->tty_iogrant = GRANT_INVALID; + chardriver_reply_task(tp->tty_iocaller, tp->tty_ioid, result); + tp->tty_iocaller = NONE; } /*===========================================================================* @@ -1571,57 +1540,6 @@ tty_t *tp; (*tp->tty_ioctl)(tp, 0); } -/*===========================================================================* - * tty_reply * - *===========================================================================*/ -void -tty_reply_f( -file, line, code, replyee, proc_nr, grant, status) -char *file; -int line; -int code; /* DEV_OPEN_REPL, DEV_CLOSE_REPL, DEV_REVIVE */ -endpoint_t replyee; /* destination address for the reply */ -endpoint_t proc_nr; /* to whom should the reply go? */ -cp_grant_id_t grant; /* which grant was involved? */ -int status; /* reply code */ -{ - message m; - - assert(code == DEV_OPEN_REPL || code == DEV_CLOSE_REPL || code == DEV_REVIVE); - - /* Don't reply to KERNEL (kernel messages) */ - if (replyee == KERNEL) return; - - memset(&m, 0, sizeof(m)); - - m.REP_ENDPT = proc_nr; - m.REP_IO_GRANT = grant; - m.REP_STATUS = status; - - status = _sendcall(replyee, code, &m); - if (status != OK) - printf("tty`tty_reply: send to %d failed: %d\n", replyee, status); -} - -/*===========================================================================* - * select_reply * - *===========================================================================*/ -void select_reply(int code, endpoint_t replyee, dev_t minor, int ops) -{ - message m; - int status; - - memset(&m, 0, sizeof(m)); - - m.DEV_MINOR = minor; - m.DEV_SEL_OPS = ops; - - status = _sendcall(replyee, code, &m); - if (status != OK) - printf("tty`select_reply: send to %d failed: %d\n", replyee, status); -} - - /*===========================================================================* * sigchar * *===========================================================================*/ @@ -1696,7 +1614,7 @@ static void tty_init() tp->tty_intail = tp->tty_inhead = tp->tty_inbuf; tp->tty_min = 1; - tp->tty_ingrant = tp->tty_outgrant = tp->tty_iogrant = GRANT_INVALID; + tp->tty_incaller = tp->tty_outcaller = tp->tty_iocaller = NONE; tp->tty_termios = termios_defaults; tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close = tp->tty_open = tty_devnop; @@ -1750,27 +1668,3 @@ int enable; /* set timer if true, otherwise unset */ cancel_timer(&tty_ptr->tty_tmr); } } - -/*===========================================================================* - * do_select * - *===========================================================================*/ -static void do_select(tp, m_ptr) -register tty_t *tp; /* pointer to tty struct */ -register message *m_ptr; /* pointer to message sent to the task */ -{ - int ops, ready_ops = 0, watch; - - ops = m_ptr->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR); - watch = (m_ptr->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0; - - ready_ops = select_try(tp, ops); - - if (!ready_ops && ops && watch) { - tp->tty_select_ops |= ops; - tp->tty_select_proc = m_ptr->m_source; - tp->tty_select_minor = m_ptr->DEV_MINOR; - } - - assert(tp->tty_minor == m_ptr->DEV_MINOR); - select_reply(DEV_SEL_REPL1, m_ptr->m_source, tp->tty_minor, ready_ops); -} diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h index 1933692df..baca8dcc3 100644 --- a/drivers/tty/tty.h +++ b/drivers/tty/tty.h @@ -1,5 +1,6 @@ /* tty.h - Terminals */ +#include #include #undef lock @@ -34,7 +35,7 @@ typedef void(*devfunarg_t) (struct tty *tp, int c); typedef struct tty { int tty_events; /* set when TTY should inspect this line */ int tty_index; /* index into TTY table */ - int tty_minor; /* device minor number */ + devminor_t tty_minor; /* device minor number */ /* Input queue. Typed characters are stored here until read by a program. */ u16_t *tty_inhead; /* pointer to place where next char goes */ @@ -61,27 +62,24 @@ typedef struct tty { char tty_openct; /* count of number of opens of this tty */ /* Information about incomplete I/O requests is stored here. */ - endpoint_t tty_incaller; /* process that made the call (usually VFS) */ - endpoint_t tty_inproc; /* process that wants to read from tty */ + endpoint_t tty_incaller; /* process that made the call, or NONE */ + cdev_id_t tty_inid; /* ID of suspended read request */ cp_grant_id_t tty_ingrant; /* grant where data is to go */ - vir_bytes tty_inoffset; /* offset into grant */ - int tty_inleft; /* how many chars are still needed */ - int tty_incum; /* # chars input so far */ - endpoint_t tty_outcaller; /* process that made the call (usually VFS) */ - endpoint_t tty_outproc; /* process that wants to write to tty */ + size_t tty_inleft; /* how many chars are still needed */ + size_t tty_incum; /* # chars input so far */ + endpoint_t tty_outcaller; /* process that made the call, or NONE */ + cdev_id_t tty_outid; /* ID of suspended write request */ cp_grant_id_t tty_outgrant; /* grant where data comes from */ - vir_bytes tty_outoffset; /* offset into grant */ - int tty_outleft; /* # chars yet to be output */ - int tty_outcum; /* # chars output so far */ - endpoint_t tty_iocaller; /* process that made the call (usually VFS) */ - endpoint_t tty_ioproc; /* process that wants to do an ioctl */ - int tty_ioreq; /* ioctl request code */ + size_t tty_outleft; /* # chars yet to be output */ + size_t tty_outcum; /* # chars output so far */ + endpoint_t tty_iocaller; /* process that made the call, or NONE */ + cdev_id_t tty_ioid; /* ID of suspended ioctl request */ + unsigned int tty_ioreq; /* ioctl request code */ cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */ /* select() data */ int tty_select_ops; /* which operations are interesting */ endpoint_t tty_select_proc; /* which process wants notification */ - dev_t tty_select_minor; /* sanity check only, can be removed */ /* Miscellaneous. */ devfun_t tty_ioctl; /* set line speed, etc. at the device level */ @@ -135,14 +133,11 @@ extern struct kmessages kmess; void handle_events(struct tty *tp); void sigchar(struct tty *tp, int sig, int mayflush); void tty_task(void); +tty_t *line2tty(devminor_t minor); int in_process(struct tty *tp, char *buf, int count, int scode); void out_process(struct tty *tp, char *bstart, char *bpos, char *bend, int *icount, int *ocount); void tty_wakeup(clock_t now); -#define tty_reply(c, r, p, g, s) tty_reply_f(__FILE__, __LINE__, (c), (r), (p), (g), (s)) -void tty_reply_f(char *f, int l, int code, endpoint_t replyee, - endpoint_t proc_nr, cp_grant_id_t grant, int status); -void select_reply(int code, endpoint_t replyee, dev_t minor, int ops); int select_try(struct tty *tp, int ops); int select_retry(struct tty *tp); @@ -155,22 +150,21 @@ void kputc(int c); void cons_stop(void); void scr_init(struct tty *tp); void toggle_scroll(void); -int con_loadfont(message *m); +int con_loadfont(endpoint_t endpt, cp_grant_id_t grant); void select_console(int cons_line); void beep_x( unsigned freq, clock_t dur); -void do_video(message *m); +void do_video(message *m, int ipc_status); /* keyboard.c */ void kb_init(struct tty *tp); void kb_init_once(void); -int kbd_loadmap(message *m); +int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant); void do_fkey_ctl(message *m); void kbd_interrupt(message *m); -void do_kbd(message *m); +void do_kbd(message *m, int ipc_status); void do_kb_inject(message *m); -void do_kbdaux(message *m); /* pty.c */ -void do_pty(struct tty *tp, message *m_ptr); +void do_pty(message *m_ptr, int ipc_status); void pty_init(struct tty *tp); void select_retry_pty(struct tty *tp); diff --git a/include/minix/Makefile b/include/minix/Makefile index b8a3273bc..030ebc387 100644 --- a/include/minix/Makefile +++ b/include/minix/Makefile @@ -18,7 +18,7 @@ INCS+= acpi.h audio_fw.h bitmap.h \ reboot.h rs.h safecopies.h sched.h sef.h sffs.h \ sound.h spin.h sys_config.h sysinfo.h \ syslib.h sysutil.h termios.h timers.h type.h \ - tty.h u64.h usb.h usb_ch9.h vbox.h \ + u64.h usb.h usb_ch9.h vbox.h \ vboxfs.h vboxif.h vboxtype.h vm.h \ vfsif.h vtreefs.h libminixfs.h netsock.h \ virtio.h diff --git a/include/minix/com.h b/include/minix/com.h index 60ae42ef7..7f9fee92b 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -1275,7 +1275,6 @@ #define TTY_FKEY_CONTROL (TTY_RQ_BASE + 1) /* control an F-key at TTY */ -#define OLD_FKEY_CONTROL 98 /* previously used for TTY_FKEY_CONTROL */ # define FKEY_REQUEST m2_i1 /* request to perform at TTY */ # define FKEY_MAP 10 /* observe function key */ # define FKEY_UNMAP 11 /* stop observing function key */ diff --git a/include/minix/tty.h b/include/minix/tty.h deleted file mode 100644 index fcf8d2f97..000000000 --- a/include/minix/tty.h +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef _MINIX_TTY_H -#define _MINIX_TTY_H - -#include - -#define TTYMAGIC 0xb105 - -/* A struct that the tty driver can use to pass values to the boot monitor. - * Currently only the value of the origin of the first vty (console), so the - * boot monitor can properly display it when panicing (tty isn't scheduled - * to switch to the first vty). It's written at the end of video memory - * (video memory base + video memory size - sizeof(struct boot_tty_info). - */ - -struct boot_tty_info { - u16_t reserved[30]; /* reserved, set to 0 */ - u16_t consorigin; /* origin in video memory of console */ - u16_t conscursor; /* position of cursor of console */ - u16_t flags; /* flags indicating which fields are valid */ - u16_t magic; /* magic number indicating struct is valid */ -}; - -#define BTIF_CONSORIGIN 0x01 /* consorigin is set */ -#define BTIF_CONSCURSOR 0x02 /* conscursor is set */ - -#endif - diff --git a/include/sys/ioc_tty.h b/include/sys/ioc_tty.h index ff42c13a5..c51361f75 100644 --- a/include/sys/ioc_tty.h +++ b/include/sys/ioc_tty.h @@ -22,7 +22,6 @@ #define TIOCSWINSZ _IOW('T', 17, struct winsize) #define TIOCGPGRP _IOW('T', 18, int) #define TIOCSPGRP _IOW('T', 19, int) -#define TIOCSFON_OLD _IOW('T', 20, u8_t [8192]) #define TIOCSFON _IOW_BIG(1, u8_t [8192]) /* Keyboard ioctls. */ -- 2.44.0