diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /drivers/char/vc_screen.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'drivers/char/vc_screen.c')
-rw-r--r-- | drivers/char/vc_screen.c | 164 |
1 files changed, 102 insertions, 62 deletions
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index b03118f78..71f4e2f84 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -14,24 +14,54 @@ * administrator can control access using file system permissions. * * aeb@cwi.nl - efter Friedas begravelse - 950211 + * + * machek@k332.feld.cvut.cz - modified not to send characters to wrong console + * - fixed some fatal of-by-one bugs (0-- no longer == -1 -> looping and looping and looping...) + * - making it working with multiple monitor patches + * - making it shorter - scr_readw are macros which expand in PRETTY long code */ +#include <linux/config.h> + #include <linux/kernel.h> #include <linux/major.h> #include <linux/errno.h> #include <linux/tty.h> #include <linux/sched.h> +#include <linux/interrupt.h> #include <linux/mm.h> +#include <linux/init.h> #include <asm/uaccess.h> #include "vt_kern.h" #include "selection.h" +#undef attr +#undef org +#undef addr #define HEADER_SIZE 4 -static inline int +static unsigned short +func_scr_readw(unsigned short *org) +{ +return scr_readw( org ); +} + +static void +func_scr_writew(unsigned short val, unsigned short *org) +{ +scr_writew( val, org ); +} + +static int vcs_size(struct inode *inode) { - int size = video_num_lines * video_num_columns; + int size; +#ifdef CONFIG_MULTIMON + int currcons = MINOR(inode->i_rdev) & 127; + /* Multimon patch */ + if (!vc_cons[currcons].d) return 0; +#endif + size= video_num_lines * video_num_columns; if (MINOR(inode->i_rdev) & 128) size = 2*size + HEADER_SIZE; return size; @@ -40,7 +70,8 @@ vcs_size(struct inode *inode) static long long vcs_lseek(struct inode *inode, struct file *file, long long offset, int orig) { - int size = vcs_size(inode); + int size; + size = vcs_size(inode); switch (orig) { case 0: @@ -56,145 +87,154 @@ vcs_lseek(struct inode *inode, struct file *file, long long offset, int orig) return -EINVAL; } if (file->f_pos < 0 || file->f_pos > size) - return -EINVAL; + { file->f_pos = 0; return -EINVAL; } return file->f_pos; } +#define RETURN( x ) { enable_bh( CONSOLE_BH ); return x; } static long vcs_read(struct inode *inode, struct file *file, char *buf, unsigned long count) { - unsigned long p = file->f_pos; - unsigned int cons = MINOR(inode->i_rdev); + int p = file->f_pos; + unsigned int currcons = MINOR(inode->i_rdev); int viewed, attr, size, read; char *buf0; - unsigned short *org; + unsigned short *org = NULL; - attr = (cons & 128); - cons = (cons & 127); - if (cons == 0) { - cons = fg_console; + attr = (currcons & 128); + currcons = (currcons & 127); + disable_bh( CONSOLE_BH ); + if (currcons == 0) { + currcons = fg_console; viewed = 1; } else { - cons--; + currcons--; viewed = 0; } - if (!vc_cons_allocated(cons)) - return -ENXIO; + if (!vc_cons_allocated(currcons)) + RETURN( -ENXIO ); size = vcs_size(inode); - if (p > size) - return -EINVAL; + if (p < 0 || p > size) + RETURN( -EINVAL ); if (count > size - p) count = size - p; buf0 = buf; if (!attr) { - org = screen_pos(cons, p, viewed); + org = screen_pos(currcons, p, viewed); while (count-- > 0) - put_user(scr_readw(org++) & 0xff, buf++); + put_user(func_scr_readw(org++) & 0xff, buf++); } else { if (p < HEADER_SIZE) { char header[HEADER_SIZE]; header[0] = (char) video_num_lines; header[1] = (char) video_num_columns; - getconsxy(cons, header+2); - while (p < HEADER_SIZE && count-- > 0) - put_user(header[p++], buf++); + getconsxy(currcons, header+2); + while (p < HEADER_SIZE && count > 0) + { count--; put_user(header[p++], buf++); } + } + if (count > 0) { + p -= HEADER_SIZE; + org = screen_pos(currcons, p/2, viewed); + if ((p & 1) && count > 0) + { count--; put_user(func_scr_readw(org++) >> 8, buf++); } } - p -= HEADER_SIZE; - org = screen_pos(cons, p/2, viewed); - if ((p & 1) && count-- > 0) - put_user(scr_readw(org++) >> 8, buf++); while (count > 1) { - put_user(scr_readw(org++), (unsigned short *) buf); + put_user(func_scr_readw(org++), (unsigned short *) buf); buf += 2; count -= 2; } if (count > 0) - put_user(scr_readw(org) & 0xff, buf++); + put_user(func_scr_readw(org) & 0xff, buf++); } read = buf - buf0; file->f_pos += read; - return read; + RETURN( read ); } static long vcs_write(struct inode *inode, struct file *file, const char *buf, unsigned long count) { - unsigned long p = file->f_pos; - unsigned int cons = MINOR(inode->i_rdev); + int p = file->f_pos; + unsigned int currcons = MINOR(inode->i_rdev); int viewed, attr, size, written; const char *buf0; - unsigned short *org; + unsigned short *org = NULL; - attr = (cons & 128); - cons = (cons & 127); - if (cons == 0) { - cons = fg_console; + attr = (currcons & 128); + currcons = (currcons & 127); + disable_bh( CONSOLE_BH ); + if (currcons == 0) { + currcons = fg_console; viewed = 1; } else { - cons--; + currcons--; viewed = 0; } - if (!vc_cons_allocated(cons)) - return -ENXIO; + if (!vc_cons_allocated(currcons)) + RETURN( -ENXIO ); size = vcs_size(inode); - if (p > size) - return -EINVAL; + if (p < 0 || p > size) + RETURN( -EINVAL ); if (count > size - p) count = size - p; buf0 = buf; if (!attr) { - org = screen_pos(cons, p, viewed); - while (count-- > 0) { + org = screen_pos(currcons, p, viewed); + while (count > 0) { unsigned char c; + count--; get_user(c, (const unsigned char*)buf++); - scr_writew((scr_readw(org) & 0xff00) | c, org); + func_scr_writew((func_scr_readw(org) & 0xff00) | c, org); org++; } } else { if (p < HEADER_SIZE) { char header[HEADER_SIZE]; - getconsxy(cons, header+2); - while (p < HEADER_SIZE && count-- > 0) - get_user(header[p++], buf++); + getconsxy(currcons, header+2); + while (p < HEADER_SIZE && count > 0) + { count--; get_user(header[p++], buf++); } if (!viewed) - putconsxy(cons, header+2); + putconsxy(currcons, header+2); } - p -= HEADER_SIZE; - org = screen_pos(cons, p/2, viewed); - if ((p & 1) && count-- > 0) { - char c; - get_user(c,buf++); - scr_writew((c << 8) | - (scr_readw(org) & 0xff), org); - org++; + if (count > 0) { + p -= HEADER_SIZE; + org = screen_pos(currcons, p/2, viewed); + if ((p & 1) && count > 0) { + char c; + count--; + get_user(c,buf++); + func_scr_writew((c << 8) | + (func_scr_readw(org) & 0xff), org); + org++; + } } while (count > 1) { unsigned short w; get_user(w, (const unsigned short *) buf); - scr_writew(w, org++); + func_scr_writew(w, org++); buf += 2; count -= 2; } if (count > 0) { unsigned char c; get_user(c, (const unsigned char*)buf++); - scr_writew((scr_readw(org) & 0xff00) | c, org); + func_scr_writew((func_scr_readw(org) & 0xff00) | c, org); } } written = buf - buf0; file->f_pos += written; - return written; + RETURN( written ); } static int vcs_open(struct inode *inode, struct file *filp) { - unsigned int cons = (MINOR(inode->i_rdev) & 127); - if(cons && !vc_cons_allocated(cons-1)) + unsigned int currcons = (MINOR(inode->i_rdev) & 127); + if(currcons && !vc_cons_allocated(currcons-1)) return -ENXIO; return 0; } @@ -204,7 +244,7 @@ static struct file_operations vcs_fops = { vcs_read, /* read */ vcs_write, /* write */ NULL, /* readdir */ - NULL, /* select */ + NULL, /* poll */ NULL, /* ioctl */ NULL, /* mmap */ vcs_open, /* open */ @@ -212,7 +252,7 @@ static struct file_operations vcs_fops = { NULL /* fsync */ }; -int vcs_init(void) +__initfunc(int vcs_init(void)) { int error; |