From 057f54fbba73632587ea428953d2a4a6d26e0b57 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:41 -0500 Subject: [PATCH] Import 1.1.54 --- Makefile | 2 +- arch/i386/config.in | 1 + drivers/block/cdu31a.c | 10 +- drivers/block/floppy.c | 1 + drivers/block/hd.c | 97 +++-- drivers/char/ChangeLog | 84 ++++ drivers/char/Makefile | 4 +- drivers/char/console.c | 783 +++++++++++++++++++++++++----------- drivers/char/defkeymap.c | 451 ++++++++------------- drivers/char/defkeymap.map | 85 ++-- drivers/char/kbd_kern.h | 81 ++-- drivers/char/keyboard.c | 458 ++++++++++++++++----- drivers/char/mem.c | 2 +- drivers/char/mouse.c | 2 +- drivers/char/psaux.c | 2 +- drivers/char/pty.c | 2 +- drivers/char/serial.c | 78 ++-- drivers/char/tty_io.c | 164 +++++--- drivers/char/tty_ioctl.c | 16 +- drivers/char/uni_to_437.c | 169 ++++++++ drivers/char/vt.c | 342 +++++++++++----- drivers/char/vt_kern.h | 6 +- drivers/net/Makefile | 10 +- drivers/net/depca.c | 105 +++-- drivers/scsi/53c7,8xx.c | 3 +- drivers/scsi/buslogic.h | 9 +- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi.h | 6 +- drivers/scsi/sd.c | 14 +- drivers/scsi/sr.c | 20 +- drivers/scsi/ultrastor.c | 2 +- drivers/sound/ad1848.c | 3 +- drivers/sound/sb16_midi.c | 1 - fs/Makefile | 20 +- fs/binfmt_elf.c | 791 +++++++++++++++++++++++++++++++++++++ fs/exec.c | 9 +- fs/nfs/file.c | 12 +- fs/nfs/proc.c | 4 +- fs/nfs/symlink.c | 2 +- fs/proc/inode.c | 6 +- fs/proc/link.c | 100 ++++- include/asm-i386/unistd.h | 38 +- include/linux/elf.h | 24 +- include/linux/kd.h | 22 +- include/linux/keyboard.h | 332 ++++++++++++++-- include/linux/tty.h | 10 +- include/linux/vt.h | 8 + net/inet/ip.c | 6 +- net/inet/ipx.c | 22 +- 49 files changed, 3312 insertions(+), 1109 deletions(-) create mode 100644 drivers/char/ChangeLog create mode 100644 drivers/char/uni_to_437.c create mode 100644 fs/binfmt_elf.c diff --git a/Makefile b/Makefile index be288e78e330..b96bd98725d0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 53 +SUBLEVEL = 54 ARCH = i386 diff --git a/arch/i386/config.in b/arch/i386/config.in index 62dfaa605462..60670b14110d 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -11,6 +11,7 @@ bool 'XT harddisk support' CONFIG_BLK_DEV_XD n bool 'Networking support' CONFIG_NET y bool 'Limit memory to low 16MB' CONFIG_MAX_16M n bool 'System V IPC' CONFIG_SYSVIPC y +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y if [ "$CONFIG_NET" = "y" ]; then diff --git a/drivers/block/cdu31a.c b/drivers/block/cdu31a.c index 1e3fb841e421..f6d9bdecb639 100644 --- a/drivers/block/cdu31a.c +++ b/drivers/block/cdu31a.c @@ -1135,7 +1135,7 @@ do_cdu31a_request(void) unsigned int dev; int nsect; unsigned char params[10]; - unsigned char res_reg[2]; + unsigned char res_reg[12]; unsigned int res_size; int copyoff; int spin_up_retry; @@ -1263,6 +1263,14 @@ try_read_again: * next block to read. */ copyoff = (block - sony_first_block) * 512; + /* + * Bugfix: get_data calls handle_sony_cd_attention + * there the buffer may be declared invalid + * if the CD ist changed by setting sony_first_block = -1 + * This would cause a segfault in memcpy + */ + if(sony_first_block <0) goto cdu31a_request_startover; + memcpy(CURRENT->buffer, sony_buffer+copyoff, 512); block += 1; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 70032aaf287c..378369209b7b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1745,6 +1745,7 @@ static void redo_format(void) raw_cmd.track = format_req.track << floppy->stretch; buffer_track = -1; setup_format_params(); + clear_bit(current_drive, &changed_floppies); floppy_start(); #ifdef DEBUGT debugt("queue format request"); diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 679c9cc67a1c..13a61030462f 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -132,6 +132,45 @@ void hd_setup(char *str, int *ints) NR_HD = hdind+1; } +static void dump_status (char *msg, unsigned int stat) +{ + unsigned long flags; + char dev; + + dev = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?'; + save_flags (flags); + sti(); + printk("hd%c: %s: status=0x%02x { ", dev, msg, stat & 0xff); + if (stat & BUSY_STAT) printk("Busy "); + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("WriteFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + printk("}\n"); + if (stat & ERR_STAT) { + unsigned int err = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x { ", dev, msg, err & 0xff); + if (err & BBD_ERR) printk("BadSector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { + if (CURRENT) + printk(", sector=%ld", CURRENT->sector); + printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), + inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); + } + printk("\n"); + } + restore_flags (flags); +} + static int win_result(void) { int i=inb_p(HD_STATUS); @@ -141,11 +180,7 @@ static int win_result(void) hd_error = 0; return 0; /* ok */ } - printk("HD: win_result: status = 0x%02x\n",i); - if (i&1) { - hd_error = inb(HD_ERROR); - printk("HD: win_result: error = 0x%02x\n",hd_error); - } + dump_status("win_result", i); return 1; } @@ -280,7 +315,7 @@ static void identify_intr(void) if (unmask_intr[dev]) sti(); if (stat & (BUSY_STAT|ERR_STAT)) { - printk (" hd%c: non-IDE device, CHS=%d%d%d\n", dev+'a', + printk (" hd%c: non-IDE device, CHS=%d/%d/%d\n", dev+'a', hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect); if (id != NULL) { hd_ident_info[dev] = NULL; @@ -331,7 +366,7 @@ static void set_multmode_intr(void) sti(); if (stat & (BUSY_STAT|ERR_STAT)) { mult_req[dev] = mult_count[dev] = 0; - printk (" hd%c: set multiple mode failed\n", dev+'a'); + dump_status("set multiple mode failed", stat); } else { if ((mult_count[dev] = mult_req[dev])) printk (" hd%c: enabled %d-sector multiple mode\n", @@ -357,7 +392,7 @@ static int drive_busy(void) if (c == (READY_STAT | SEEK_STAT)) return 0; } - printk("HD controller times out, status = 0x%02x\n",c); + dump_status("reset timed out", c); return 1; } @@ -409,16 +444,24 @@ repeat: hd_request(); } + /* * Ok, don't know what to do with the unexpected interrupts: on some machines * doing a reset and a retry seems to result in an eternal loop. Right now I * ignore it, and just set the timeout. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the + * drive enters "idle", "standby", or "sleep" mode, so if the status looks + * "good", we just ignore the interrupt completely. */ void unexpected_hd_interrupt(void) { - sti(); - printk(KERN_DEBUG "Unexpected HD interrupt\n"); - SET_TIMER; + unsigned int stat = inb_p(HD_STATUS); + + if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { + dump_status ("unexpected interrupt", stat); + SET_TIMER; + } } /* @@ -445,11 +488,12 @@ static void bad_rw_intr(void) static inline int wait_DRQ(void) { - int retries = 100000; + int retries = 100000, stat; while (--retries > 0) - if (inb_p(HD_STATUS) & DRQ_STAT) + if ((stat = inb_p(HD_STATUS)) & DRQ_STAT) return 0; + dump_status("wait_DRQ", stat); return -1; } @@ -472,14 +516,8 @@ static void read_intr(void) if (i & DRQ_STAT) goto ok_to_read; } while (--retries > 0); - sti(); - printk("hd%c: read_intr: status = 0x%02x\n",dev+'a',i); - if (i & ERR_STAT) { - hd_error = (unsigned) inb(HD_ERROR); - printk("hd%c: read_intr: error = 0x%02x\n",dev+'a',hd_error); - } + dump_status("read_intr", i); bad_rw_intr(); - cli(); hd_request(); return; ok_to_read: @@ -565,14 +603,8 @@ static void multwrite_intr(void) } } } - sti(); - printk("hd%c: multwrite_intr: status = 0x%02x\n",dev+'a',i); - if (i & ERR_STAT) { - hd_error = (unsigned) inb(HD_ERROR); - printk("hd:%c multwrite_intr: error = 0x%02x\n",dev+'a',hd_error); - } + dump_status("multwrite_intr", i); bad_rw_intr(); - cli(); hd_request(); } @@ -592,14 +624,8 @@ static void write_intr(void) if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) goto ok_to_write; } while (--retries > 0); - sti(); - printk("HD: write_intr: status = 0x%02x\n",i); - if (i & ERR_STAT) { - hd_error = (unsigned) inb(HD_ERROR); - printk("HD: write_intr: error = 0x%02x\n",hd_error); - } + dump_status("write_intr", i); bad_rw_intr(); - cli(); hd_request(); return; ok_to_write: @@ -644,13 +670,13 @@ static void hd_times_out(void) return; reset = 1; printk(KERN_DEBUG "HD timeout\n"); - cli(); if (++CURRENT->errors >= MAX_ERRORS) { #ifdef DEBUG printk("hd : too many errors.\n"); #endif end_request(0); } + cli(); hd_request(); } @@ -763,7 +789,6 @@ repeat: CURRENT->sector+nsect-1, (long) CURRENT->buffer); #endif if (wait_DRQ()) { - printk("hd%c: hd_request: no DRQ\n", dev+'a'); bad_rw_intr(); goto repeat; } diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog new file mode 100644 index 000000000000..e82c70ba1b18 --- /dev/null +++ b/drivers/char/ChangeLog @@ -0,0 +1,84 @@ +Sun Oct 9 23:46:03 1994 Theodore Y. Ts'o (tytso@rt-11) + + * tty_io.c (do_tty_hangup): If the tty driver flags + TTY_DRIVER_RESET_TERMIOS is set, then reset the termios + settings back to the driver's initial configuration. This + allows the termios settings to be reset even if a process + has hung up file descriptors keeping a pty's termios from + being freed and reset. + + * tty_io.c (release_dev): Fix memory leak. The pty's other + termios structure should also be freed. + + * serial.c (rs_close, shutdown): Change how we wait for the + transmitter to completely drain before shutting down the + serial port. We now do it by scheduling in another + process instead of busy looping with the interrupts turned + on. This may eliminate some race condition problems that + some people seem to be reporting. + +Sun Sep 25 14:18:14 1994 Theodore Y. Ts'o (tytso@rt-11) + + * tty_io.c (release_dev): When freeing a tty make sure that both + the tty and the o_tty (if present) aren't a process's + controlling tty. (Previously, we only checked the tty.) + + * serial.c (change_speed): Only enable the Modem Status + Interrupt for a port if CLOCAL is not set or CRTSCTS + is set. If we're not checking the carrier detect and + CTS line, there's no point in enabling the modem + status interrupt. This will save spurious interrupts + from slowing down systems who have terminals that + don't support either line. (Of course, if you want + only one of CD and CTS support, you will need a + properly wired serial cable.) + +Thu Sep 22 08:32:48 1994 Theodore Y. Ts'o (tytso@rt-11) + + * tty_io.c (do_SAK): Return if tty is null. + + * tty_io.c (_tty_name): Return "NULL tty" if the passed in tty is + NULL. + +Sat Sep 17 13:19:25 1994 Theodore Y. Ts'o (tytso@rt-11) + + * tty_ioctl.c (n_tty_ioctl): Fix TIOCGLCKTRMIOS and + TIOCSLCKTRMIOS, which were totally broken. Remove + extra indirection from argument; it should be a struct + termios *, not a struct termios **. + &real_tty->termios_locked should have been + real_tty->termios_locked. This caused us to be + reading and writing the termios_locked structure to + random places in kernel memory. + + * tty_io.c (release_dev): Oops! Forgot to delete a critical kfree + of the locked_termios. This leaves the locked_termios + structure pointed at a freed object. + +Fri Sep 16 08:13:25 1994 Theodore Y. Ts'o (tytso@rt-11) + + * tty_io.c (tty_open): Don't check for an exclusive open until + after the device specific open routine has been called. + Otherwise, the serial device ref counting will be screwed + up. + + * serial.c (rs_open, block_til_ready): Don't set termios structure + until after block_til_ready has returned successfully. + Modify block_til_ready to check the normal_termios + structure directly, so it doesn't rely on termios being + set before its called. + +Thu Sep 15 23:34:01 1994 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_close): Turn off interrupts during rs_close() to + prevent a race condition with the hangup code (which + runs during a software interrupt). + + * tty_io.c (release_dev): Don't free the locked_termios structure; + its state must be retained across device opens. + + + * tty_io.c (tty_unregister_driver): Added function to unregister a + tty driver. (For loadable device drivers.) + + diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ab8d226a72a3..ec8430aac7cd 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -18,11 +18,11 @@ OBJS = tty_io.o n_tty.o console.o keyboard.o serial.o \ tty_ioctl.o pty.o vt.o mem.o \ - defkeymap.o + defkeymap.o uni_to_437.o SRCS = tty_io.c n_tty.c console.c keyboard.c serial.c \ tty_ioctl.c pty.c vt.c mem.c \ - defkeymap.c + defkeymap.c uni_to_437.c ifdef CONFIG_ATIXL_BUSMOUSE diff --git a/drivers/char/console.c b/drivers/char/console.c index 5f4b56742a72..9f900f0ace70 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -1,5 +1,5 @@ /* - * linux/kernel/console.c + * linux/drivers/char/console.c * * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -9,16 +9,35 @@ * * This module exports the console io functions: * - * 'long con_init(long)' - * 'int con_open(struct tty_struct *tty, struct file * filp)' - * 'void update_screen(int new_console)' - * 'void blank_screen(void)' - * 'void unblank_screen(void)' + * 'void do_keyboard_interrupt(void)' * - * 'int con_get_font(char *)' - * 'int con_set_font(char *)' - * 'int con_get_trans(char *)' - * 'int con_set_trans(char *)' + * 'int vc_allocate(unsigned int console)' + * 'int vc_cons_allocated(unsigned int console)' + * 'int vc_resize(unsigned long lines, unsigned long cols)' + * 'void vc_disallocate(unsigned int currcons)' + * + * 'long con_init(long)' + * 'int con_open(struct tty_struct *tty, struct file * filp)' + * 'void con_write(struct tty_struct * tty)' + * 'void console_print(const char * b)' + * 'void update_screen(int new_console)' + * + * 'void blank_screen(void)' + * 'void unblank_screen(void)' + * 'void poke_blanked_console(void)' + * 'void scrollback(int lines)' + * 'void scrollfront(int lines)' + * 'int do_screendump(int arg)' + * + * 'int con_get_font(char *)' + * 'int con_set_font(char *)' + * 'int con_get_trans(char *)' + * 'int con_set_trans(char *)' + * + * 'int set_selection(const int arg)' + * 'int paste_selection(struct tty_struct *tty)' + * 'int sel_loadlut(const int arg)' + * 'int mouse_reporting(void)' * * Hopefully this will be a rather complete VT102 implementation. * @@ -35,11 +54,18 @@ * Code to check for different video-cards mostly by Galen Hunt, * * + * Rudimentary ISO 10646/Unicode/UTF-8 character set support by + * Markus Kuhn, . + * + * Dynamic allocation of consoles, aeb@cwi.nl, May 1994 + * Resizing of consoles, aeb, 940926 + * * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94 * * */ +#define BLANK 0x0020 #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ /* @@ -59,6 +85,7 @@ #include #include #include +#include #include #include @@ -75,9 +102,9 @@ struct tty_driver console_driver; static int console_refcount; -static struct tty_struct *console_table[NR_CONSOLES]; -static struct termios *console_termios[NR_CONSOLES]; -static struct termios *console_termios_locked[NR_CONSOLES]; +static struct tty_struct *console_table[MAX_NR_CONSOLES]; +static struct termios *console_termios[MAX_NR_CONSOLES]; +static struct termios *console_termios_locked[MAX_NR_CONSOLES]; #ifdef CONFIG_SELECTION #include @@ -90,7 +117,7 @@ static void highlight_pointer(const int currcons, const int where); /* Variables for selection control. */ #define SEL_BUFFER_SIZE 4096 -static int sel_cons; +static int sel_cons = 0; static int sel_start = -1; static int sel_end; static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' }; @@ -98,24 +125,44 @@ static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' }; #define NPAR 16 +static void con_setsize(unsigned long rows, unsigned long cols); +static void vc_init(unsigned int console, unsigned long rows, unsigned long cols, + int do_clear); +static void get_scrmem(int currcons); +static void set_scrmem(int currcons, long offset); +static void set_origin(int currcons); +static void gotoxy(int currcons, int new_x, int new_y); +static void save_cur(int currcons); +static inline void set_cursor(int currcons); +static void reset_terminal(int currcons, int do_clear); +extern void reset_vc(unsigned int new_console); extern void vt_init(void); extern void register_console(void (*proc)(const char *)); extern void compute_shiftstate(void); +extern int conv_uni_to_pc(unsigned long ucs); -unsigned long video_num_columns; /* Number of text columns */ -unsigned long video_num_lines; /* Number of text lines */ - +/* Description of the hardware situation */ static unsigned char video_type; /* Type of display being used */ static unsigned long video_mem_base; /* Base of video memory */ static unsigned long video_mem_term; /* End of video memory */ -static unsigned long video_size_row; /* Bytes per row */ -static unsigned char video_page; /* Initial video page */ +static unsigned char video_page; /* Initial video page (unused) */ static unsigned short video_port_reg; /* Video register select port */ static unsigned short video_port_val; /* Video register value port */ +static unsigned long video_num_columns; /* Number of text columns */ +static unsigned long video_num_lines; /* Number of text lines */ +static unsigned long video_size_row; +static unsigned long video_screen_size; static int can_do_color = 0; -static int printable = 0; +static int printable = 0; /* Is console ready for printing? */ + +static unsigned short *vc_scrbuf[MAX_NR_CONSOLES]; + +static int console_blanked = 0; +static int blankinterval = 10*60*HZ; +static long blank_origin, blank__origin, unblank_origin; -static struct { +struct vc_data { + unsigned long vc_screenbuf_size; unsigned short vc_video_erase_char; /* Background erase character */ unsigned char vc_attr; /* Current attributes */ unsigned char vc_def_color; /* Default colors */ @@ -144,6 +191,7 @@ static struct { unsigned long vc_decawm : 1; /* Autowrap Mode */ unsigned long vc_deccm : 1; /* Cursor Visible */ unsigned long vc_decim : 1; /* Insert Mode */ + unsigned long vc_deccolm : 1; /* 80/132 Column Mode */ /* attribute flags */ unsigned long vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */ unsigned long vc_underline : 1; @@ -156,7 +204,12 @@ static struct { /* misc */ unsigned long vc_ques : 1; unsigned long vc_need_wrap : 1; + unsigned long vc_has_scrolled : 1; /* Info for unblank_screen */ + unsigned long vc_kmalloced : 1; /* kfree_s() needed */ unsigned long vc_report_mouse : 2; + unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ + unsigned char vc_utf_count; + unsigned long vc_utf_char; unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */ unsigned char * vc_translate; unsigned char * vc_G0_charset; @@ -164,65 +217,237 @@ static struct { unsigned char * vc_saved_G0; unsigned char * vc_saved_G1; /* additional information is in vt_kern.h */ -} vc_cons [NR_CONSOLES]; - -unsigned short *vc_scrbuf[NR_CONSOLES]; -static unsigned short * vc_scrmembuf; -static int console_blanked = 0; +}; -#define origin (vc_cons[currcons].vc_origin) -#define scr_end (vc_cons[currcons].vc_scr_end) -#define pos (vc_cons[currcons].vc_pos) -#define top (vc_cons[currcons].vc_top) -#define bottom (vc_cons[currcons].vc_bottom) -#define x (vc_cons[currcons].vc_x) -#define y (vc_cons[currcons].vc_y) -#define vc_state (vc_cons[currcons].vc_state) -#define npar (vc_cons[currcons].vc_npar) -#define par (vc_cons[currcons].vc_par) -#define ques (vc_cons[currcons].vc_ques) -#define attr (vc_cons[currcons].vc_attr) -#define saved_x (vc_cons[currcons].vc_saved_x) -#define saved_y (vc_cons[currcons].vc_saved_y) -#define translate (vc_cons[currcons].vc_translate) -#define G0_charset (vc_cons[currcons].vc_G0_charset) -#define G1_charset (vc_cons[currcons].vc_G1_charset) -#define saved_G0 (vc_cons[currcons].vc_saved_G0) -#define saved_G1 (vc_cons[currcons].vc_saved_G1) -#define video_mem_start (vc_cons[currcons].vc_video_mem_start) -#define video_mem_end (vc_cons[currcons].vc_video_mem_end) -#define video_erase_char (vc_cons[currcons].vc_video_erase_char) -#define disp_ctrl (vc_cons[currcons].vc_disp_ctrl) -#define toggle_meta (vc_cons[currcons].vc_toggle_meta) -#define decscnm (vc_cons[currcons].vc_decscnm) -#define decom (vc_cons[currcons].vc_decom) -#define decawm (vc_cons[currcons].vc_decawm) -#define deccm (vc_cons[currcons].vc_deccm) -#define decim (vc_cons[currcons].vc_decim) -#define need_wrap (vc_cons[currcons].vc_need_wrap) -#define report_mouse (vc_cons[currcons].vc_report_mouse) -#define color (vc_cons[currcons].vc_color) -#define s_color (vc_cons[currcons].vc_s_color) -#define def_color (vc_cons[currcons].vc_def_color) +static struct vc { + struct vc_data *d; + + /* might add scrmem, vt_struct, kbd at some time, + to have everything in one place - the disadvantage + would be that vc_cons etc can no longer be static */ +} vc_cons [MAX_NR_CONSOLES]; + +#define screenbuf_size (vc_cons[currcons].d->vc_screenbuf_size) +#define origin (vc_cons[currcons].d->vc_origin) +#define scr_end (vc_cons[currcons].d->vc_scr_end) +#define pos (vc_cons[currcons].d->vc_pos) +#define top (vc_cons[currcons].d->vc_top) +#define bottom (vc_cons[currcons].d->vc_bottom) +#define x (vc_cons[currcons].d->vc_x) +#define y (vc_cons[currcons].d->vc_y) +#define vc_state (vc_cons[currcons].d->vc_state) +#define npar (vc_cons[currcons].d->vc_npar) +#define par (vc_cons[currcons].d->vc_par) +#define ques (vc_cons[currcons].d->vc_ques) +#define attr (vc_cons[currcons].d->vc_attr) +#define saved_x (vc_cons[currcons].d->vc_saved_x) +#define saved_y (vc_cons[currcons].d->vc_saved_y) +#define translate (vc_cons[currcons].d->vc_translate) +#define G0_charset (vc_cons[currcons].d->vc_G0_charset) +#define G1_charset (vc_cons[currcons].d->vc_G1_charset) +#define saved_G0 (vc_cons[currcons].d->vc_saved_G0) +#define saved_G1 (vc_cons[currcons].d->vc_saved_G1) +#define utf (vc_cons[currcons].d->vc_utf) +#define utf_count (vc_cons[currcons].d->vc_utf_count) +#define utf_char (vc_cons[currcons].d->vc_utf_char) +#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start) +#define video_mem_end (vc_cons[currcons].d->vc_video_mem_end) +#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char) +#define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl) +#define toggle_meta (vc_cons[currcons].d->vc_toggle_meta) +#define decscnm (vc_cons[currcons].d->vc_decscnm) +#define decom (vc_cons[currcons].d->vc_decom) +#define decawm (vc_cons[currcons].d->vc_decawm) +#define deccm (vc_cons[currcons].d->vc_deccm) +#define decim (vc_cons[currcons].d->vc_decim) +#define deccolm (vc_cons[currcons].d->vc_deccolm) +#define need_wrap (vc_cons[currcons].d->vc_need_wrap) +#define has_scrolled (vc_cons[currcons].d->vc_has_scrolled) +#define kmalloced (vc_cons[currcons].d->vc_kmalloced) +#define report_mouse (vc_cons[currcons].d->vc_report_mouse) +#define color (vc_cons[currcons].d->vc_color) +#define s_color (vc_cons[currcons].d->vc_s_color) +#define def_color (vc_cons[currcons].d->vc_def_color) #define foreground (color & 0x0f) #define background (color & 0xf0) -#define charset (vc_cons[currcons].vc_charset) -#define s_charset (vc_cons[currcons].vc_s_charset) -#define intensity (vc_cons[currcons].vc_intensity) -#define underline (vc_cons[currcons].vc_underline) -#define blink (vc_cons[currcons].vc_blink) -#define reverse (vc_cons[currcons].vc_reverse) -#define s_intensity (vc_cons[currcons].vc_s_intensity) -#define s_underline (vc_cons[currcons].vc_s_underline) -#define s_blink (vc_cons[currcons].vc_s_blink) -#define s_reverse (vc_cons[currcons].vc_s_reverse) -#define ulcolor (vc_cons[currcons].vc_ulcolor) -#define halfcolor (vc_cons[currcons].vc_halfcolor) -#define tab_stop (vc_cons[currcons].vc_tab_stop) -#define vcmode (vt_cons[currcons].vc_mode) -#define vtmode (vt_cons[currcons].vt_mode) -#define vtpid (vt_cons[currcons].vt_pid) -#define vtnewvt (vt_cons[currcons].vt_newvt) +#define charset (vc_cons[currcons].d->vc_charset) +#define s_charset (vc_cons[currcons].d->vc_s_charset) +#define intensity (vc_cons[currcons].d->vc_intensity) +#define underline (vc_cons[currcons].d->vc_underline) +#define blink (vc_cons[currcons].d->vc_blink) +#define reverse (vc_cons[currcons].d->vc_reverse) +#define s_intensity (vc_cons[currcons].d->vc_s_intensity) +#define s_underline (vc_cons[currcons].d->vc_s_underline) +#define s_blink (vc_cons[currcons].d->vc_s_blink) +#define s_reverse (vc_cons[currcons].d->vc_s_reverse) +#define ulcolor (vc_cons[currcons].d->vc_ulcolor) +#define halfcolor (vc_cons[currcons].d->vc_halfcolor) +#define tab_stop (vc_cons[currcons].d->vc_tab_stop) + +#define vcmode (vt_cons[currcons]->vc_mode) +#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct)) + +static void * memsetw(void * s, unsigned short c, unsigned int count) +{ +__asm__("cld\n\t" + "rep\n\t" + "stosw" + : /* no output */ + :"a" (c),"D" (s),"c" (count/2) + :"cx","di"); +return s; +} + +int vc_cons_allocated(unsigned int i) +{ + return (i < MAX_NR_CONSOLES && vc_cons[i].d); +} + +int vc_allocate(unsigned int i) /* return 0 on success */ +{ + if (i >= MAX_NR_CONSOLES) + return -ENODEV; + if (!vc_cons[i].d) { + long p, q; + + /* prevent users from taking too much memory */ + if (i >= MAX_NR_USER_CONSOLES && !suser()) + return -EPERM; + + /* due to the granularity of kmalloc, we waste some memory here */ + /* the alloc is done in two steps, to optimize the common situation + of a 25x80 console (structsize=216, video_screen_size=4000) */ + q = (long) kmalloc(video_screen_size, GFP_KERNEL); + if (!q) + return -ENOMEM; + p = (long) kmalloc(structsize, GFP_KERNEL); + if (!p) { + kfree_s((char *) q, video_screen_size); + return -ENOMEM; + } + + vc_cons[i].d = (struct vc_data *) p; + p += sizeof(struct vc_data); + vt_cons[i] = (struct vt_struct *) p; + vc_scrbuf[i] = (unsigned short *) q; + vc_cons[i].d->vc_kmalloced = 1; + vc_cons[i].d->vc_screenbuf_size = video_screen_size; + vc_init (i, video_num_lines, video_num_columns, 1); + } + return 0; +} + +/* + * Change # of rows and columns (0 means unchanged) + * [this is to be used together with some user program + * like resize that changes the hardware videomode] + */ +int vc_resize(unsigned long lines, unsigned long cols) +{ + unsigned long cc, ll, ss, sr; + unsigned long occ, oll, oss, osr; + unsigned short *p; + unsigned int currcons, i; + unsigned short *newscreens[MAX_NR_CONSOLES]; + long ol, nl, rlth, rrem; + + cc = (cols ? cols : video_num_columns); + ll = (lines ? lines : video_num_lines); + sr = cc << 1; + ss = sr * ll; + + if (ss > video_mem_term - video_mem_base) + return -ENOMEM; + + /* + * Some earlier version had all consoles of potentially + * different sizes, but that was really messy. + * So now we only change if there is room for all consoles + * of the same size. + */ + for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) { + if (!vc_cons_allocated(currcons)) + newscreens[currcons] = 0; + else { + p = (unsigned short *) kmalloc(ss, GFP_USER); + if (!p) { + for (i = 0; i< currcons; i++) + if (newscreens[i]) + kfree_s(newscreens[i], ss); + return -ENOMEM; + } + newscreens[currcons] = p; + } + } + + get_scrmem(fg_console); + + oll = video_num_lines; + occ = video_num_columns; + osr = video_size_row; + oss = video_screen_size; + + video_num_lines = ll; + video_num_columns = cc; + video_size_row = sr; + video_screen_size = ss; + + for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) { + if (!vc_cons_allocated(currcons)) + continue; + + rlth = MIN(osr, sr); + rrem = sr - rlth; + ol = origin; + nl = (long) newscreens[currcons]; + if (ll < oll) + ol += (oll - ll) * osr; + + while (ol < scr_end) { + memcpy((void *) nl, (void *) ol, rlth); + if (rrem) + memsetw((void *)(nl + rlth), video_erase_char, rrem); + ol += osr; + nl += sr; + } + + if (kmalloced) + kfree_s(vc_scrbuf[currcons], screenbuf_size); + vc_scrbuf[currcons] = newscreens[currcons]; + kmalloced = 1; + screenbuf_size = ss; + + origin = video_mem_start = (long) vc_scrbuf[currcons]; + scr_end = video_mem_end = video_mem_start + ss; + + if (scr_end > nl) + memsetw((void *) nl, video_erase_char, scr_end - nl); + + /* do part of a reset_terminal() */ + top = 0; + bottom = video_num_lines; + gotoxy(currcons, x, y); + save_cur(currcons); + } + + set_scrmem(fg_console, 0); + set_origin(fg_console); + set_cursor(fg_console); + + return 0; +} + +void vc_disallocate(unsigned int currcons) +{ + if (vc_cons_allocated(currcons)) { + if (kmalloced) + kfree_s(vc_scrbuf[currcons], screenbuf_size); + if (currcons >= MIN_NR_CONSOLES) + kfree_s(vc_cons[currcons].d, structsize); + vc_cons[currcons].d = 0; + } +} + #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x) #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x) @@ -231,12 +456,8 @@ static int console_blanked = 0; #define decarm VC_REPEAT #define decckm VC_CKMODE #define kbdapplic VC_APPLIC -#define kbdraw VC_RAW #define lnm VC_CRLF -int blankinterval = 10*60*HZ; -static int screen_size = 0; - /* * this is what the terminal answers to a ESC-Z or csi0c query. */ @@ -357,7 +578,7 @@ static void gotoxy(int currcons, int new_x, int new_y) * *Very* limited hardware scrollback support.. */ static unsigned short __real_origin; -static unsigned short __origin; +static unsigned short __origin; /* offset of currently displayed screen */ static inline void __set_origin(unsigned short offset) { @@ -427,7 +648,7 @@ static inline void set_cursor(int currcons) if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) return; if (__real_origin != __origin) - set_origin(__real_origin); + __set_origin(__real_origin); save_flags(flags); cli(); if (deccm) { outb_p(14, video_port_reg); @@ -469,6 +690,7 @@ static void scrup(int currcons, unsigned int t, unsigned int b) scr_end -= origin-video_mem_start; pos -= origin-video_mem_start; origin = video_mem_start; + has_scrolled = 1; } else { __asm__("cld\n\t" "rep\n\t" @@ -514,6 +736,7 @@ static void scrdown(int currcons, unsigned int t, unsigned int b) "D" (origin+video_size_row*b-4), "S" (origin+video_size_row*(b-1)-4) :"ax","cx","di","si"); + has_scrolled = 1; } static void lf(int currcons) @@ -555,16 +778,7 @@ static inline void bs(int currcons) static inline void del(int currcons) { -#if 0 - if (x) { - if (!need_wrap) { /* this is not the right condition */ - pos -= 2; - x--; - } - *(unsigned short *)pos = video_erase_char; - need_wrap = 0; - } -#endif + /* ignored */ } static void csi_J(int currcons, int vpar) @@ -629,13 +843,13 @@ static void csi_K(int currcons, int vpar) need_wrap = 0; } -static void csi_X(int currcons, int vpar) -{ +static void csi_X(int currcons, int vpar) /* erase the following vpar positions */ +{ /* not vt100? */ long count; long start; if (!vpar) - vpar++; + vpar++; start=pos; count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; @@ -650,9 +864,6 @@ static void csi_X(int currcons, int vpar) need_wrap = 0; } -/* - * I hope this works. The monochrome part is untested. - */ static void update_attr(int currcons) { attr = color; @@ -847,8 +1058,12 @@ static void set_mode(int currcons, int on_off) clr_kbd(decckm); break; case 3: /* 80/132 mode switch unimplemented */ - csi_J(currcons,2); - gotoxy(currcons,0,0); + deccolm = on_off; +#if 0 + (void) vc_resize(video_num_lines, deccolm ? 132 : 80); + /* this alone does not suffice; some user mode + utility has to change the hardware regs */ +#endif break; case 5: /* Inverted screen on/off */ if (decscnm != on_off) { @@ -1032,13 +1247,13 @@ static void restore_cur(int currcons) } enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, - EShash, ESsetG0, ESsetG1, ESignore }; + EShash, ESsetG0, ESsetG1, ESpercent, ESignore }; static void reset_terminal(int currcons, int do_clear) { top = 0; bottom = video_num_lines; - vc_state = ESnormal; + vc_state = ESnormal; ques = 0; translate = NORM_TRANS; G0_charset = NORM_TRANS; @@ -1046,6 +1261,8 @@ static void reset_terminal(int currcons, int do_clear) charset = 0; need_wrap = 0; report_mouse = 0; + utf = 0; + utf_count = 0; disp_ctrl = 0; toggle_meta = 0; @@ -1061,7 +1278,8 @@ static void reset_terminal(int currcons, int do_clear) clr_kbd(kbdapplic); clr_kbd(lnm); kbd_table[currcons].lockstate = 0; - kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate; + kbd_table[currcons].ledmode = LED_SHOW_FLAGS; + kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate; set_leds(); default_attr(currcons); @@ -1073,11 +1291,10 @@ static void reset_terminal(int currcons, int do_clear) tab_stop[3] = tab_stop[4] = 0x01010101; - if (do_clear) { - gotoxy(currcons,0,0); - csi_J(currcons,2); - save_cur(currcons); - } + gotoxy(currcons,0,0); + save_cur(currcons); + if (do_clear) + csi_J(currcons,2); } /* @@ -1089,7 +1306,7 @@ static void con_stop(struct tty_struct *tty) if (!tty) return; console_num = MINOR(tty->device) - (tty->driver.minor_start); - if (console_num < 0 || console_num >= NR_CONSOLES) + if (!vc_cons_allocated(console_num)) return; set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); set_leds(); @@ -1104,7 +1321,7 @@ static void con_start(struct tty_struct *tty) if (!tty) return; console_num = MINOR(tty->device) - (tty->driver.minor_start); - if (console_num < 0 || console_num >= NR_CONSOLES) + if (!vc_cons_allocated(console_num)) return; clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); set_leds(); @@ -1113,14 +1330,19 @@ static void con_start(struct tty_struct *tty) static int con_write(struct tty_struct * tty, int from_user, unsigned char *buf, int count) { - int c, n = 0; + int c, tc, ok, n = 0; unsigned int currcons; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; currcons = vt->vc_num; - if (currcons >= NR_CONSOLES) { - printk("con_write: illegal vc index (%d)\n", currcons); - return 0; + if (!vc_cons_allocated(currcons)) { + /* could this happen? */ + static int error = 0; + if (!error) { + error = 1; + printk("con_write: tty %d not allocated\n", currcons+1); + } + return 0; } #ifdef CONFIG_SELECTION /* clear the selection */ @@ -1131,19 +1353,63 @@ static int con_write(struct tty_struct * tty, int from_user, while (!tty->stopped && count) { c = from_user ? get_fs_byte(buf) : *buf; buf++; n++; count--; - if (vc_state == ESnormal - && (c >= 32 || (disp_ctrl && (c&0x7f) != 27)) - && (toggle_meta ? translate[c|0x80] : translate[c])) { - if (toggle_meta) - c |= 0x80; + + if (utf) { + /* Combine UTF-8 into Unicode */ + /* Incomplete characters silently ignored */ + if(c > 0x7f) { + /* UTF-8 to Latin-1 decoding */ + if (utf_count > 0 && (c & 0xc0) == 0x80) { + utf_char = (utf_char << 6) | (c & 0x3f); + utf_count--; + if (utf_count == 0) + c = utf_char; + else continue; + } else { + if ((c & 0xe0) == 0xc0) { + utf_count = 1; + utf_char = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + utf_count = 2; + utf_char = (c & 0x0f); + } else + utf_count = 0; + continue; + } + } else + utf_count = 0; + + /* Now try to find out how to display it */ + if (c > 0xff) { + tc = conv_uni_to_pc(c); + if (tc == -2) + continue; + vc_state = ESnormal; + if (tc == -1) + tc = 0376; /* small square: symbol not found */ + ok = 1; + } else { + tc = NORM_TRANS[c]; + ok = 0; + } + } else { /* no utf */ + tc = translate[toggle_meta ? (c|0x80) : c]; + ok = 0; + } + + /* Can print ibm (even if 0), and latin1 provided + it is a printing char or control chars are printed ^@ */ + if (!ok && tc && (c >= 32 || (disp_ctrl && (c&0x7f) != 27))) + ok = 1; + + if (vc_state == ESnormal && ok) { if (need_wrap) { cr(currcons); lf(currcons); } if (decim) insert_char(currcons); - c = translate[c]; - *(unsigned short *) pos = (attr << 8) + c; + *(unsigned short *) pos = (attr << 8) + tc; if (x == video_num_columns - 1) need_wrap = decawm; else { @@ -1208,6 +1474,9 @@ static int con_write(struct tty_struct * tty, int from_user, case '[': vc_state = ESsquare; continue; + case '%': + vc_state = ESpercent; + continue; case 'E': cr(currcons); lf(currcons); @@ -1363,6 +1632,12 @@ static int con_write(struct tty_struct * tty, int from_user, case 'm': csi_m(currcons); continue; + case 'q': /* DECLL - but only 3 leds */ + /* map 0,1,2,3 to 0,1,2,4 */ + if (par[0] < 4) + setledstate(kbd_table + currcons, + (par[0] < 3) ? par[0] : 4); + continue; case 'r': if (!par[0]) par[0]++; @@ -1393,6 +1668,21 @@ static int con_write(struct tty_struct * tty, int from_user, continue; } continue; + case ESpercent: + vc_state = ESnormal; + switch (c) { + case '@': /* defined in ISO 2022 */ + utf = 0; + continue; + case '8': + /* ISO/ECMA hasn't yet registered an + official ESC sequence for UTF-8, + so this one (ESC %8) will likely + change in the future. */ + utf = 1; + continue; + } + continue; case ESfunckey: vc_state = ESnormal; continue; @@ -1458,7 +1748,7 @@ static int con_chars_in_buffer(struct tty_struct *tty) void poke_blanked_console(void) { timer_active &= ~(1<vc_mode == KD_GRAPHICS) return; if (console_blanked) { timer_table[BLANK_TIMER].expires = 0; @@ -1469,24 +1759,20 @@ void poke_blanked_console(void) } } -void * memsetw(void * s, unsigned short c, unsigned int count) -{ -__asm__("cld\n\t" - "rep\n\t" - "stosw" - : /* no output */ - :"a" (c),"D" (s),"c" (count/2) - :"cx","di"); -return s; -} - void console_print(const char * b) { int currcons = fg_console; unsigned char c; - if (!printable || currcons<0 || currcons>=NR_CONSOLES) + if (!printable) + return; /* console not yet initialized */ + + if (!vc_cons_allocated(currcons)) { + /* impossible */ + printk("console_print: tty %d not allocated ??\n", currcons+1); return; + } + while ((c = *(b++)) != 0) { if (c == 10 || c == 13 || need_wrap) { if (c != 13) @@ -1504,7 +1790,7 @@ void console_print(const char * b) pos+=2; } set_cursor(currcons); - if (vt_cons[fg_console].vc_mode == KD_GRAPHICS) + if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; timer_active &= ~(1<paste_wait); } +static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear) +{ + long base = (long) vc_scrbuf[currcons]; + + video_num_columns = cols; + video_num_lines = rows; + video_size_row = cols<<1; + video_screen_size = video_num_lines * video_size_row; + + pos = origin = video_mem_start = base; + scr_end = base + video_screen_size; + video_mem_end = base + video_screen_size; + reset_vc(currcons); + def_color = 0x07; /* white */ + ulcolor = 0x0f; /* bold white */ + halfcolor = 0x08; /* grey */ + vt_cons[currcons]->paste_wait = 0; + reset_terminal(currcons, do_clear); +} + +static void con_setsize(unsigned long rows, unsigned long cols) +{ + video_num_lines = rows; + video_num_columns = cols; + video_size_row = 2 * cols; + video_screen_size = video_num_lines * video_size_row; +} + /* * long con_init(long); * @@ -1546,7 +1860,6 @@ long con_init(long kmem_start) { char *display_desc = "????"; int currcons = 0; - long base; int orig_x = ORIG_X; int orig_y = ORIG_Y; @@ -1556,7 +1869,7 @@ long con_init(long kmem_start) console_driver.name_base = 1; console_driver.major = TTY_MAJOR; console_driver.minor_start = 1; - console_driver.num = NR_CONSOLES; + console_driver.num = MAX_NR_CONSOLES; console_driver.type = TTY_DRIVER_TYPE_CONSOLE; console_driver.init_termios = tty_std_termios; console_driver.flags = TTY_DRIVER_REAL_RAW; @@ -1578,13 +1891,9 @@ long con_init(long kmem_start) if (tty_register_driver(&console_driver)) panic("Couldn't register console driver\n"); - vc_scrmembuf = (unsigned short *) kmem_start; - video_num_columns = ORIG_VIDEO_COLS; - video_size_row = video_num_columns * 2; - video_num_lines = ORIG_VIDEO_LINES; - video_page = ORIG_VIDEO_PAGE; - screen_size = (video_num_lines * video_size_row); - kmem_start += NR_CONSOLES * screen_size; + con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS); + video_page = ORIG_VIDEO_PAGE; /* never used */ + timer_table[BLANK_TIMER].fn = blank_screen; timer_table[BLANK_TIMER].expires = 0; if (blankinterval) { @@ -1632,64 +1941,46 @@ long con_init(long kmem_start) /* Initialize the variables used for scrolling (mostly EGA/VGA) */ - base = (long)vc_scrmembuf; - for (currcons = 0; currconsNR_CONSOLES)) + currcons = (currcons ? currcons-1 : fg_console); + if (!vc_cons_allocated(currcons)) return -EIO; - put_fs_byte((char)(video_num_lines),buf++); + l = verify_area(VERIFY_WRITE, buf, 2+video_num_columns*video_num_lines); + if (l) + return l; + put_fs_byte((char)(video_num_lines),buf++); put_fs_byte((char)(video_num_columns),buf++); - currcons = (currcons ? currcons-1 : fg_console); sptr = (char *) origin; for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++) put_fs_byte(*sptr++,buf++); @@ -1800,19 +2141,21 @@ int do_screendump(int arg) } /* - * Later on maybe we'll dynamically allocate the console screen - * memory. + * Allocate the console screen memory. */ int con_open(struct tty_struct *tty, struct file * filp) { - int idx; + unsigned int idx; + int i; idx = MINOR(tty->device) - tty->driver.minor_start; - if (idx > NR_CONSOLES) - return -ENODEV; - vt_cons[idx].vc_num = idx; - tty->driver_data = &vt_cons[idx]; + i = vc_allocate(idx); + if (i) + return i; + + vt_cons[idx]->vc_num = idx; + tty->driver_data = vt_cons[idx]; if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = video_num_lines; @@ -1845,20 +2188,20 @@ static void highlight(const int currcons, const int s, const int e) /* use complementary color to show the pointer */ static void highlight_pointer(const int currcons, const int where) { - unsigned char *p; + unsigned char *p; static unsigned char *prev=NULL; if (where==-1) /* remove the pointer */ { - if (prev) + if (prev) { *prev ^= 0x77; prev=NULL; } - } + } else { - p = (unsigned char *)origin - hwscroll_offset + where + 1; + p = (unsigned char *)origin - hwscroll_offset + where + 1; *p ^= 0x77; if (prev) *prev ^= 0x77; /* remove the previous one */ prev=p; @@ -1976,16 +2319,16 @@ int set_selection(const int arg, struct tty_struct *tty) new_sel_end = pe + video_size_row - pe % video_size_row - 2; break; - case 3: /* pointer highlight */ - if (sel_cons != currcons) - { + case 3: /* pointer highlight */ + if (sel_cons != currcons) + { highlight_pointer(sel_cons,-1); - clear_selection(); - sel_cons = currcons; - } + clear_selection(); + sel_cons = currcons; + } highlight_pointer(sel_cons,pe); return 0; /* nothing more */ - default: + default: return -EINVAL; } /* select to end of line if on trailing space */ @@ -2090,7 +2433,7 @@ int paste_selection(struct tty_struct *tty) the selection. */ static void clear_selection() { - highlight_pointer(sel_cons, -1); /* hide the pointer */ + highlight_pointer(sel_cons, -1); /* hide the pointer */ if (sel_start != -1) { highlight(sel_cons, sel_start, sel_end); @@ -2140,7 +2483,7 @@ static int set_get_font(char * arg, int set) i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz); if (i) - return i; + return i; cli(); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ @@ -2218,7 +2561,7 @@ int con_set_trans(char * arg) i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ); if (i) - return i; + return i; for (i=0; i defkeymap.c */ #include #include #include -u_short key_map[NR_KEYMAPS][NR_KEYS] = { - { - 0x0200, 0x001b, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, - 0x0037, 0x0038, 0x0039, 0x0030, 0x002d, 0x003d, 0x007f, 0x0009, - 0x0b71, 0x0b77, 0x0b65, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, - 0x0b6f, 0x0b70, 0x005b, 0x005d, 0x0201, 0x0702, 0x0b61, 0x0b73, - 0x0b64, 0x0b66, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x003b, - 0x0027, 0x0060, 0x0700, 0x005c, 0x0b7a, 0x0b78, 0x0b63, 0x0b76, - 0x0b62, 0x0b6e, 0x0b6d, 0x002c, 0x002e, 0x002f, 0x0700, 0x030c, - 0x0703, 0x0020, 0x0207, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, - 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0208, 0x0209, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x003c, 0x010a, - 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x001c, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x001b, 0x0021, 0x0040, 0x0023, 0x0024, 0x0025, 0x005e, - 0x0026, 0x002a, 0x0028, 0x0029, 0x005f, 0x002b, 0x007f, 0x0009, - 0x0b51, 0x0b57, 0x0b45, 0x0b52, 0x0b54, 0x0b59, 0x0b55, 0x0b49, - 0x0b4f, 0x0b50, 0x007b, 0x007d, 0x0201, 0x0702, 0x0b41, 0x0b53, - 0x0b44, 0x0b46, 0x0b47, 0x0b48, 0x0b4a, 0x0b4b, 0x0b4c, 0x003a, - 0x0022, 0x007e, 0x0700, 0x007c, 0x0b5a, 0x0b58, 0x0b43, 0x0b56, - 0x0b42, 0x0b4e, 0x0b4d, 0x003c, 0x003e, 0x003f, 0x0700, 0x030c, - 0x0703, 0x0020, 0x0207, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, - 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0208, 0x0203, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x003e, 0x010a, - 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x020b, 0x0601, 0x0602, 0x0117, 0x0600, 0x020a, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0040, 0x0200, 0x0024, 0x0200, 0x0200, - 0x007b, 0x005b, 0x005d, 0x007d, 0x005c, 0x0200, 0x0200, 0x0200, - 0x0b71, 0x0b77, 0x0b65, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, - 0x0b6f, 0x0b70, 0x0200, 0x007e, 0x0201, 0x0702, 0x0b61, 0x0b73, - 0x0b64, 0x0b66, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x0b7a, 0x0b78, 0x0b63, 0x0b76, - 0x0b62, 0x0b6e, 0x0b6d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x050c, 0x050d, 0x050e, 0x050f, 0x0510, - 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0208, 0x0202, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x007c, 0x0516, - 0x0517, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0b51, 0x0b57, 0x0b45, 0x0b52, 0x0b54, 0x0b59, 0x0b55, 0x0b49, - 0x0b4f, 0x0b50, 0x0200, 0x0200, 0x0201, 0x0702, 0x0b41, 0x0b53, - 0x0b44, 0x0b46, 0x0b47, 0x0b48, 0x0b4a, 0x0b4b, 0x0b4c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x0b5a, 0x0b58, 0x0b43, 0x0b56, - 0x0b42, 0x0b4e, 0x0b4d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0000, 0x001b, 0x001c, 0x001d, 0x001e, - 0x001f, 0x007f, 0x0200, 0x0200, 0x001f, 0x0200, 0x0200, 0x0200, - 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, - 0x000f, 0x0010, 0x001b, 0x001d, 0x0201, 0x0702, 0x0001, 0x0013, - 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0200, - 0x0007, 0x0000, 0x0700, 0x001c, 0x001a, 0x0018, 0x0003, 0x0016, - 0x0002, 0x000e, 0x000d, 0x0200, 0x020e, 0x007f, 0x0700, 0x030c, - 0x0703, 0x0000, 0x0207, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, - 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0208, 0x0204, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x010a, - 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x001c, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x001f, 0x0200, 0x0200, 0x0200, - 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, - 0x000f, 0x0010, 0x0200, 0x0200, 0x0201, 0x0702, 0x0001, 0x0013, - 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x001a, 0x0018, 0x0003, 0x0016, - 0x0002, 0x000e, 0x000d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, - 0x000f, 0x0010, 0x0200, 0x0200, 0x0201, 0x0702, 0x0001, 0x0013, - 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x001a, 0x0018, 0x0003, 0x0016, - 0x0002, 0x000e, 0x000d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x020c, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x020c, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, - 0x000f, 0x0010, 0x0200, 0x0200, 0x0201, 0x0702, 0x0001, 0x0013, - 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x001a, 0x0018, 0x0003, 0x0016, - 0x0002, 0x000e, 0x000d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x081b, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, - 0x0837, 0x0838, 0x0839, 0x0830, 0x082d, 0x083d, 0x087f, 0x0809, - 0x0871, 0x0877, 0x0865, 0x0872, 0x0874, 0x0879, 0x0875, 0x0869, - 0x086f, 0x0870, 0x085b, 0x085d, 0x080d, 0x0702, 0x0861, 0x0873, - 0x0864, 0x0866, 0x0867, 0x0868, 0x086a, 0x086b, 0x086c, 0x083b, - 0x0827, 0x0860, 0x0700, 0x085c, 0x087a, 0x0878, 0x0863, 0x0876, - 0x0862, 0x086e, 0x086d, 0x082c, 0x082e, 0x082f, 0x0700, 0x030c, - 0x0703, 0x0820, 0x0207, 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, - 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x0208, 0x0209, 0x0907, - 0x0908, 0x0909, 0x030b, 0x0904, 0x0905, 0x0906, 0x030a, 0x0901, - 0x0902, 0x0903, 0x0900, 0x0310, 0x0206, 0x0200, 0x083c, 0x050a, - 0x050b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x001c, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0851, 0x0857, 0x0845, 0x0852, 0x0854, 0x0859, 0x0855, 0x0849, - 0x084f, 0x0850, 0x0200, 0x0200, 0x0201, 0x0702, 0x0841, 0x0853, - 0x0844, 0x0846, 0x0847, 0x0848, 0x084a, 0x084b, 0x084c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x085a, 0x0858, 0x0843, 0x0856, - 0x0842, 0x084e, 0x084d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0871, 0x0877, 0x0865, 0x0872, 0x0874, 0x0879, 0x0875, 0x0869, - 0x086f, 0x0870, 0x0200, 0x0200, 0x0201, 0x0702, 0x0861, 0x0873, - 0x0864, 0x0866, 0x0867, 0x0868, 0x086a, 0x086b, 0x086c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x087a, 0x0878, 0x0863, 0x0876, - 0x0862, 0x086e, 0x086d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0851, 0x0857, 0x0845, 0x0852, 0x0854, 0x0859, 0x0855, 0x0849, - 0x084f, 0x0850, 0x0200, 0x0200, 0x0201, 0x0702, 0x0841, 0x0853, - 0x0844, 0x0846, 0x0847, 0x0848, 0x084a, 0x084b, 0x084c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x085a, 0x0858, 0x0843, 0x0856, - 0x0842, 0x084e, 0x084d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0811, 0x0817, 0x0805, 0x0812, 0x0814, 0x0819, 0x0815, 0x0809, - 0x080f, 0x0810, 0x0200, 0x0200, 0x0201, 0x0702, 0x0801, 0x0813, - 0x0804, 0x0806, 0x0807, 0x0808, 0x080a, 0x080b, 0x080c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x081a, 0x0818, 0x0803, 0x0816, - 0x0802, 0x080e, 0x080d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x020c, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x020c, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0811, 0x0817, 0x0805, 0x0812, 0x0814, 0x0819, 0x0815, 0x0809, - 0x080f, 0x0810, 0x0200, 0x0200, 0x0201, 0x0702, 0x0801, 0x0813, - 0x0804, 0x0806, 0x0807, 0x0808, 0x080a, 0x080b, 0x080c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x081a, 0x0818, 0x0803, 0x0816, - 0x0802, 0x080e, 0x080d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0811, 0x0817, 0x0805, 0x0812, 0x0814, 0x0819, 0x0815, 0x0809, - 0x080f, 0x0810, 0x0200, 0x0200, 0x0201, 0x0702, 0x0801, 0x0813, - 0x0804, 0x0806, 0x0807, 0x0808, 0x080a, 0x080b, 0x080c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x081a, 0x0818, 0x0803, 0x0816, - 0x0802, 0x080e, 0x080d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, { - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0811, 0x0817, 0x0805, 0x0812, 0x0814, 0x0819, 0x0815, 0x0809, - 0x080f, 0x0810, 0x0200, 0x0200, 0x0201, 0x0702, 0x0801, 0x0813, - 0x0804, 0x0806, 0x0807, 0x0808, 0x080a, 0x080b, 0x080c, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, 0x081a, 0x0818, 0x0803, 0x0816, - 0x0802, 0x080e, 0x080d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, - 0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, - 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, - 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, - 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, - 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - }, +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, }; -char func_buf[FUNC_BUFSIZE] = { +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53, + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf208, 0xf203, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, + 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73, + 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76, + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911, + 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b, + 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516, + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873, + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b, + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876, + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c, + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907, + 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901, + 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { '\033', '[', '[', 'A', 0, '\033', '[', '[', 'B', 0, '\033', '[', '[', 'C', 0, @@ -309,18 +181,14 @@ char func_buf[FUNC_BUFSIZE] = { '\033', '[', '5', '~', 0, '\033', '[', '6', '~', 0, '\033', '[', 'M', 0, - 0, - 0, '\033', '[', 'P', 0, - 0, - 0, - 0, - 0, - 0, - 0, }; -char *func_table[NR_FUNC] = { +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { func_buf + 0, func_buf + 5, func_buf + 10, @@ -348,15 +216,10 @@ char *func_table[NR_FUNC] = { func_buf + 135, func_buf + 140, func_buf + 145, + 0, + 0, func_buf + 149, - func_buf + 150, - func_buf + 151, - func_buf + 155, - func_buf + 156, - func_buf + 157, - func_buf + 158, - func_buf + 159, - func_buf + 160, + 0, }; struct kbdiacr accent_table[MAX_DIACR] = { diff --git a/drivers/char/defkeymap.map b/drivers/char/defkeymap.map index 47d39abbdce6..5e07265576c8 100644 --- a/drivers/char/defkeymap.map +++ b/drivers/char/defkeymap.map @@ -1,12 +1,24 @@ -keycode 0 = +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# keycode 1 = Escape Escape alt keycode 1 = Meta_Escape keycode 2 = one exclam alt keycode 2 = Meta_one keycode 3 = two at at - control keycode 3 = nul - shift control keycode 3 = nul - alt keycode 3 = Meta_two + control keycode 3 = nul + shift control keycode 3 = nul + alt keycode 3 = Meta_two keycode 4 = three numbersign control keycode 4 = Escape alt keycode 4 = Meta_three @@ -30,18 +42,20 @@ keycode 10 = nine parenleft bracketright keycode 11 = zero parenright braceright alt keycode 11 = Meta_zero keycode 12 = minus underscore backslash - control keycode 12 = Control_underscore - shift control keycode 12 = Control_underscore - alt keycode 12 = Meta_minus + control keycode 12 = Control_underscore + shift control keycode 12 = Control_underscore + alt keycode 12 = Meta_minus keycode 13 = equal plus alt keycode 13 = Meta_equal keycode 14 = Delete Delete + control keycode 14 = BackSpace alt keycode 14 = Meta_Delete keycode 15 = Tab Tab alt keycode 15 = Meta_Tab keycode 16 = q keycode 17 = w -keycode 18 = e +keycode 18 = e + altgr keycode 18 = Hex_E keycode 19 = r keycode 20 = t keycode 21 = y @@ -58,10 +72,13 @@ keycode 27 = bracketright braceright asciitilde keycode 28 = Return alt keycode 28 = Meta_Control_m keycode 29 = Control -keycode 30 = a +keycode 30 = a + altgr keycode 30 = Hex_A keycode 31 = s -keycode 32 = d -keycode 33 = f +keycode 32 = d + altgr keycode 32 = Hex_D +keycode 33 = f + altgr keycode 33 = Hex_F keycode 34 = g keycode 35 = h keycode 36 = j @@ -81,15 +98,17 @@ keycode 43 = backslash bar alt keycode 43 = Meta_backslash keycode 44 = z keycode 45 = x -keycode 46 = c +keycode 46 = c + altgr keycode 46 = Hex_C keycode 47 = v -keycode 48 = b +keycode 48 = b + altgr keycode 48 = Hex_B keycode 49 = n keycode 50 = m keycode 51 = comma less alt keycode 51 = Meta_comma keycode 52 = period greater - control keycode 52 = Compose + control keycode 52 = Compose alt keycode 52 = Meta_period keycode 53 = slash question control keycode 53 = Delete @@ -104,61 +123,81 @@ keycode 58 = Caps_Lock keycode 59 = F1 F11 Console_13 control keycode 59 = F1 alt keycode 59 = Console_1 + control alt keycode 59 = Console_1 keycode 60 = F2 F12 Console_14 control keycode 60 = F2 alt keycode 60 = Console_2 + control alt keycode 60 = Console_2 keycode 61 = F3 F13 Console_15 control keycode 61 = F3 alt keycode 61 = Console_3 + control alt keycode 61 = Console_3 keycode 62 = F4 F14 Console_16 control keycode 62 = F4 alt keycode 62 = Console_4 + control alt keycode 62 = Console_4 keycode 63 = F5 F15 Console_17 control keycode 63 = F5 alt keycode 63 = Console_5 + control alt keycode 63 = Console_5 keycode 64 = F6 F16 Console_18 control keycode 64 = F6 alt keycode 64 = Console_6 + control alt keycode 64 = Console_6 keycode 65 = F7 F17 Console_19 control keycode 65 = F7 alt keycode 65 = Console_7 + control alt keycode 65 = Console_7 keycode 66 = F8 F18 Console_20 control keycode 66 = F8 alt keycode 66 = Console_8 + control alt keycode 66 = Console_8 keycode 67 = F9 F19 Console_21 control keycode 67 = F9 alt keycode 67 = Console_9 + control alt keycode 67 = Console_9 keycode 68 = F10 F20 Console_22 control keycode 68 = F10 alt keycode 68 = Console_10 + control alt keycode 68 = Console_10 keycode 69 = Num_Lock keycode 70 = Scroll_Lock Show_Memory Show_Registers control keycode 70 = Show_State alt keycode 70 = Scroll_Lock keycode 71 = KP_7 alt keycode 71 = Ascii_7 + altgr keycode 71 = Hex_7 keycode 72 = KP_8 alt keycode 72 = Ascii_8 + altgr keycode 72 = Hex_8 keycode 73 = KP_9 alt keycode 73 = Ascii_9 + altgr keycode 73 = Hex_9 keycode 74 = KP_Subtract keycode 75 = KP_4 alt keycode 75 = Ascii_4 + altgr keycode 75 = Hex_4 keycode 76 = KP_5 alt keycode 76 = Ascii_5 + altgr keycode 76 = Hex_5 keycode 77 = KP_6 alt keycode 77 = Ascii_6 + altgr keycode 77 = Hex_6 keycode 78 = KP_Add keycode 79 = KP_1 alt keycode 79 = Ascii_1 + altgr keycode 79 = Hex_1 keycode 80 = KP_2 alt keycode 80 = Ascii_2 + altgr keycode 80 = Hex_2 keycode 81 = KP_3 alt keycode 81 = Ascii_3 + altgr keycode 81 = Hex_3 keycode 82 = KP_0 alt keycode 82 = Ascii_0 + altgr keycode 82 = Hex_0 keycode 83 = KP_Period - altgr control keycode 83 = Boot +# altgr control keycode 83 = Boot control alt keycode 83 = Boot keycode 84 = Last_Console keycode 85 = @@ -167,9 +206,11 @@ keycode 86 = less greater bar keycode 87 = F11 F11 Console_23 control keycode 87 = F11 alt keycode 87 = Console_11 + control alt keycode 87 = Console_11 keycode 88 = F12 F12 Console_24 control keycode 88 = F12 alt keycode 88 = Console_12 + control alt keycode 88 = Console_12 keycode 89 = keycode 90 = keycode 91 = @@ -190,14 +231,16 @@ keycode 103 = Up keycode 104 = Prior shift keycode 104 = Scroll_Backward keycode 105 = Left + alt keycode 105 = Decr_Console keycode 106 = Right + alt keycode 106 = Incr_Console keycode 107 = Select keycode 108 = Down keycode 109 = Next shift keycode 109 = Scroll_Forward keycode 110 = Insert keycode 111 = Remove - altgr control keycode 111 = Boot +# altgr control keycode 111 = Boot control alt keycode 111 = Boot keycode 112 = Macro keycode 113 = F13 @@ -206,7 +249,7 @@ keycode 115 = Help keycode 116 = Do keycode 117 = F17 keycode 118 = KP_MinPlus -keycode 119 = Pause +keycode 119 = Pause keycode 120 = keycode 121 = keycode 122 = @@ -241,16 +284,8 @@ string Remove = "\033[3~" string Select = "\033[4~" string Prior = "\033[5~" string Next = "\033[6~" -string Help = "" -string Do = "" string Macro = "\033[M" string Pause = "\033[P" -string F21 = "" -string F22 = "" -string F23 = "" -string F24 = "" -string F25 = "" -string F26 = "" compose '`' 'A' to 'À' compose '`' 'a' to 'à' compose '\'' 'A' to 'Á' diff --git a/drivers/char/kbd_kern.h b/drivers/char/kbd_kern.h index 4f852725c602..440b0d5bb5eb 100644 --- a/drivers/char/kbd_kern.h +++ b/drivers/char/kbd_kern.h @@ -6,6 +6,11 @@ #include +extern char *func_table[MAX_NR_FUNC]; +extern char func_buf[]; +extern char *funcbufptr; +extern int funcbufsize, funcbufleft; + /* * kbd->xxx contains the VC-local things (flag settings etc..) * @@ -16,57 +21,59 @@ * Note: lockstate is used as index in the array key_map. */ struct kbd_struct { - unsigned char ledstate; /* 3 bits */ - unsigned char default_ledstate; -#define VC_SCROLLOCK 0 /* scroll-lock mode */ -#define VC_NUMLOCK 1 /* numeric lock mode */ -#define VC_CAPSLOCK 2 /* capslock mode */ - unsigned char lockstate; /* 4 bits - must be in 0..15 */ + unsigned char lockstate; +/* 8 modifiers - the names do not have any meaning at all; + they can be associated to arbitrarily chosen keys */ #define VC_SHIFTLOCK KG_SHIFT /* shift lock mode */ #define VC_ALTGRLOCK KG_ALTGR /* altgr lock mode */ #define VC_CTRLLOCK KG_CTRL /* control lock mode */ #define VC_ALTLOCK KG_ALT /* alt lock mode */ +#define VC_SHIFTLLOCK KG_SHIFTL /* shiftl lock mode */ +#define VC_SHIFTRLOCK KG_SHIFTR /* shiftr lock mode */ +#define VC_CTRLLLOCK KG_CTRLL /* ctrll lock mode */ +#define VC_CTRLRLOCK KG_CTRLR /* ctrlr lock mode */ + + unsigned char ledmode:2; /* one 2-bit value */ +#define LED_SHOW_FLAGS 0 /* traditional state */ +#define LED_SHOW_IOCTL 1 /* only change leds upon ioctl */ +#define LED_SHOW_MEM 2 /* `heartbeat': peek into memory */ + + unsigned char ledflagstate:3; /* flags, not lights */ + unsigned char default_ledflagstate:3; +#define VC_SCROLLOCK 0 /* scroll-lock mode */ +#define VC_NUMLOCK 1 /* numeric lock mode */ +#define VC_CAPSLOCK 2 /* capslock mode */ + + unsigned char kbdmode:2; /* one 2-bit value */ +#define VC_XLATE 0 /* translate keycodes using keymap */ +#define VC_MEDIUMRAW 1 /* medium raw (keycode) mode */ +#define VC_RAW 2 /* raw (scancode) mode */ +#define VC_UNICODE 3 /* Unicode mode */ - unsigned char modeflags; + unsigned char modeflags:5; #define VC_APPLIC 0 /* application key mode */ #define VC_CKMODE 1 /* cursor key mode */ #define VC_REPEAT 2 /* keyboard repeat */ #define VC_CRLF 3 /* 0 - enter sends CR, 1 - enter sends CRLF */ #define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */ -#define VC_PAUSE 5 /* pause key pressed - unused */ -#define VC_RAW 6 /* raw (scancode) mode */ -#define VC_MEDIUMRAW 7 /* medium raw (keycode) mode */ }; extern struct kbd_struct kbd_table[]; - extern unsigned long kbd_init(unsigned long); -extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - return ((kbd->ledstate >> flag) & 1); -} - -extern inline int vc_kbd_lock(struct kbd_struct * kbd, int flag) -{ - return ((kbd->lockstate >> flag) & 1); -} +extern unsigned char getledstate(void); +extern void setledstate(struct kbd_struct *kbd, unsigned int led); extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag) { return ((kbd->modeflags >> flag) & 1); } -extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - kbd->ledstate |= 1 << flag; -} - -extern inline void set_vc_kbd_lock(struct kbd_struct * kbd, int flag) +extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag) { - kbd->lockstate |= 1 << flag; + return ((kbd->ledflagstate >> flag) & 1); } extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag) @@ -74,14 +81,9 @@ extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag) kbd->modeflags |= 1 << flag; } -extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - kbd->ledstate &= ~(1 << flag); -} - -extern inline void clr_vc_kbd_lock(struct kbd_struct * kbd, int flag) +extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag) { - kbd->lockstate &= ~(1 << flag); + kbd->ledflagstate |= 1 << flag; } extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag) @@ -89,9 +91,9 @@ extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag) kbd->modeflags &= ~(1 << flag); } -extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) +extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag) { - kbd->ledstate ^= 1 << flag; + kbd->ledflagstate &= ~(1 << flag); } extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag) @@ -104,4 +106,11 @@ extern inline void chg_vc_kbd_mode(struct kbd_struct * kbd, int flag) kbd->modeflags ^= 1 << flag; } +extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) +{ + kbd->ledflagstate ^= 1 << flag; +} + +#define U(x) ((x) ^ 0xf000) + #endif diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 698ed92cd9f8..ef4a94763b32 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1,5 +1,5 @@ /* - * linux/kernel/chr_drv/keyboard.c + * linux/drivers/char/keyboard.c * * Keyboard driver for Linux v0.99 using Latin-1. * @@ -7,8 +7,13 @@ * the assembly version by Linus (with diacriticals added) * * Some additional features added by Christoph Niemann (ChN), March 1993 + * * Loadable keymaps by Risto Kankkunen, May 1993 + * * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 + * Added decr/incr_console, dynamic keymaps, Unicode support, + * dynamic function/string keys, led setting, Sept 1994 + * */ #define KEYBOARD_IRQ 1 @@ -33,6 +38,7 @@ #define KBD_REPORT_ERR #define KBD_REPORT_UNKN +/* #define KBD_IS_FOCUS_9000 */ #ifndef KBD_DEFMODE #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META)) @@ -63,9 +69,11 @@ extern void poke_blanked_console(void); extern void ctrl_alt_del(void); +extern void reset_vc(unsigned int new_console); extern void change_console(unsigned int new_console); extern void scrollback(int); extern void scrollfront(int); +extern int vc_cons_allocated(unsigned int); #define fake_keyboard_interrupt() \ __asm__ __volatile__("int $0x21") @@ -88,19 +96,20 @@ static int last_console = 0; /* last used VC */ static int dead_key_next = 0; /* * In order to retrieve the shift_state (for the mouse server), either - * the variable must be global, or a new procedure must be create to + * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. */ /*static*/ int shift_state = 0; static int npadch = -1; /* -1 or number assembled on pad */ static unsigned char diacr = 0; static char rep = 0; /* flag telling character repeat */ -struct kbd_struct kbd_table[NR_CONSOLES]; +struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct tty_struct **ttytab; static struct kbd_struct * kbd = kbd_table; static struct tty_struct * tty = NULL; /* used only by send_data - set by keyboard_interrupt */ +static volatile unsigned char reply_expected = 0; static volatile unsigned char acknowledge = 0; static volatile unsigned char resend = 0; @@ -109,24 +118,40 @@ typedef void (k_handfn)(unsigned char value, char up_flag); static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase; + do_meta, do_ascii, do_lock, do_lowercase, do_ignore; -static k_hand key_handler[] = { +static k_hand key_handler[16] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase + do_meta, do_ascii, do_lock, do_lowercase, + do_ignore, do_ignore, do_ignore, do_ignore +}; + +typedef void (*void_fnp)(void); +typedef void (void_fn)(void); + +static void_fn enter, show_ptregs, send_intr, lastcons, caps_toggle, + num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, + SAK, decr_console, incr_console; + +static void_fnp spec_fn_table[] = { + NULL, enter, show_ptregs, show_mem, + show_state, send_intr, lastcons, caps_toggle, + num, hold, scroll_forw, scroll_back, + boot_it, caps_on, compose, SAK, + decr_console, incr_console }; /* maximum values each key_handler can handle */ const int max_vals[] = { - 255, NR_FUNC - 1, 15, 17, 4, 255, 3, NR_SHIFT, - 255, 9, 3, 255 + 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, + NR_DEAD - 1, 255, 3, NR_SHIFT - 1, + 255, NR_ASCII - 1, NR_LOCK - 1, 255 }; const int NR_TYPES = SIZE(max_vals); static void put_queue(int); static unsigned char handle_diacr(unsigned char); -static void SAK(void); /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ static struct pt_regs * pt_regs; @@ -146,6 +171,27 @@ static inline void send_cmd(unsigned char c) outb(c,0x64); } +/* + * Many other routines do put_queue, but I think either + * they produce ASCII, or they produce some user-assigned + * string, and in both cases we might assume that it is + * in utf-8 already. + */ +void to_utf8(ushort c) { + if (c < 0x80) + put_queue(c); /* 0******* */ + else if (c < 0x800) { + put_queue(0xc0 | (c >> 6)); /* 110***** 10****** */ + put_queue(0x80 | (c & 0x3f)); + } else { + put_queue(0xe0 | (c >> 12)); /* 1110**** 10****** 10****** */ + put_queue(0x80 | ((c >> 6) & 0x3f)); + put_queue(0x80 | (c & 0x3f)); + } + /* uft-8 is defined for words of up to 36 bits, + but we need only 16 bits here */ +} + /* * Translation of escaped scancodes to keysyms. * This should be user-settable. @@ -178,7 +224,7 @@ static inline void send_cmd(unsigned char c) #define E0_F17 (E0_BASE+21) #define E0_KPMINPLUS (E0_BASE+22) -#define E1_PAUSE (E0_BASE+23) +#define E1_PAUSE (E0_BASE+23) /* 119 */ static unsigned char e0_keys[128] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ @@ -199,9 +245,42 @@ static unsigned char e0_keys[128] = { 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ }; +/* kludge to stay below 128 - next time someone comes with a strange + keyboard, key codes will have to become 2 (or 4) bytes. */ +/* Owners of a FOCUS 9000 can assign F1,F2-F8,F9-F12 to 85,89-95,120-123 */ +/* Owners of a certain Japanese keyboard can use 89 and 124 */ +/* Owners of a certain Brazilian keyboard can use 89 and 121 */ +/* Note: MEDIUMRAW mode will change, and all keycodes above 89 will change; + this is only a temporary solution */ + +#define SC_LIM 89 + +#define FOCUS_PF1 85 /* actual code! */ +#define FOCUS_PF2 89 +#define FOCUS_PF3 90 +#define FOCUS_PF4 91 +#define FOCUS_PF5 92 +#define FOCUS_PF6 93 +#define FOCUS_PF7 94 +#define FOCUS_PF8 95 +#define FOCUS_PF9 (E1_PAUSE + 1) +#define FOCUS_PF10 (E1_PAUSE + 2) +#define FOCUS_PF11 (E1_PAUSE + 3) +#define FOCUS_PF12 (E1_PAUSE + 4) /* 123 */ +#define JAP_86 (E1_PAUSE + 5) /* 124 */ + +static unsigned char high_keys[128 - SC_LIM] = { + 0, 0, 0, 0, 0, 0, 0, /* 0x59-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ +}; + static void keyboard_interrupt(int int_pt_regs) { - unsigned char scancode; + unsigned char scancode, keycode; static unsigned int prev_scancode = 0; /* remember E0, E1 */ char up_flag; /* 0 or 0200 */ char raw_mode; @@ -213,27 +292,44 @@ static void keyboard_interrupt(int int_pt_regs) goto end_kbd_intr; scancode = inb(0x60); mark_bh(KEYBOARD_BH); - if (scancode == 0xfa) { - acknowledge = 1; - goto end_kbd_intr; - } else if (scancode == 0xfe) { - resend = 1; - goto end_kbd_intr; - } else if (scancode == 0) { + if (reply_expected) { + /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */ + /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */ + reply_expected = 0; + if (scancode == 0xfa) { + acknowledge = 1; + goto end_kbd_intr; + } else if (scancode == 0xfe) { + resend = 1; + goto end_kbd_intr; + } + /* strange ... */ + reply_expected = 1; +#ifdef KBD_REPORT_ERR + printk("keyboard reply expected - got %02x\n", scancode); +#endif + } + if (scancode == 0) { #ifdef KBD_REPORT_ERR printk("keyboard buffer overflow\n"); #endif + prev_scancode = 0; goto end_kbd_intr; - } else if (scancode == 0xff) { + } + if (scancode == 0xff) { + /* the calculator keys on a FOCUS 9000 generate 0xff */ +#ifndef KBD_IS_FOCUS_9000 #ifdef KBD_REPORT_ERR printk("keyboard error\n"); +#endif #endif prev_scancode = 0; goto end_kbd_intr; } + tty = ttytab[fg_console]; kbd = kbd_table + fg_console; - if ((raw_mode = vc_kbd_mode(kbd,VC_RAW))) { + if ((raw_mode = (kbd->kbdmode == VC_RAW))) { put_queue(scancode); /* we do not return yet, because we want to maintain the key_down array, so that we have the correct @@ -245,7 +341,7 @@ static void keyboard_interrupt(int int_pt_regs) } /* - * Convert scancode to keysym, using prev_scancode. + * Convert scancode to keycode, using prev_scancode. */ up_flag = (scancode & 0200); scancode &= 0x7f; @@ -260,10 +356,12 @@ static void keyboard_interrupt(int int_pt_regs) prev_scancode = 0x100; goto end_kbd_intr; } else if (prev_scancode == 0x100 && scancode == 0x45) { - scancode = E1_PAUSE; + keycode = E1_PAUSE; prev_scancode = 0; } else { +#ifdef KBD_REPORT_UNKN printk("keyboard: unknown e1 escape sequence\n"); +#endif prev_scancode = 0; goto end_kbd_intr; } @@ -286,50 +384,75 @@ static void keyboard_interrupt(int int_pt_regs) goto end_kbd_intr; if (e0_keys[scancode]) - scancode = e0_keys[scancode]; - else if (!raw_mode) { + keycode = e0_keys[scancode]; + else { #ifdef KBD_REPORT_UNKN - printk("keyboard: unknown scancode e0 %02x\n", scancode); + if (!raw_mode) + printk("keyboard: unknown scancode e0 %02x\n", scancode); #endif goto end_kbd_intr; } } - } else if (scancode >= E0_BASE && !raw_mode) { + } else if (scancode >= SC_LIM) { + /* This happens with the FOCUS 9000 keyboard + Its keys PF1..PF12 are reported to generate + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f + Moreover, unless repeated, they do not generate + key-down events, so we have to zero up_flag below */ + /* Also, Japanese 86/106 keyboards are reported to + generate 0x73 and 0x7d for \ - and \ | respectively. */ + /* Also, some Brazilian keyboard is reported to produce + 0x73 and 0x7e for \ ? and KP-dot, respectively. */ + + keycode = high_keys[scancode - SC_LIM]; + + if (!keycode) { + if (!raw_mode) { #ifdef KBD_REPORT_UNKN - printk("keyboard: scancode (%02x) not in range 00 - %2x\n", - scancode, E0_BASE - 1); + printk("keyboard: unrecognized scancode (%02x) - ignored\n" + , scancode); #endif - goto end_kbd_intr; - } + } + goto end_kbd_intr; + } + } else + keycode = scancode; /* - * At this point the variable `scancode' contains the keysym. + * At this point the variable `keycode' contains the keycode. + * Note: the keycode must not be 0. * We keep track of the up/down status of the key, and - * return the keysym if in MEDIUMRAW mode. - * (Note: earlier kernels had a bug and did not pass the up/down - * bit to applications.) + * return the keycode if in MEDIUMRAW mode. */ if (up_flag) { - clear_bit(scancode, key_down); rep = 0; + if(!clear_bit(keycode, key_down)) { + /* unexpected, but this can happen: + maybe this was a key release for a FOCUS 9000 + PF key; if we want to see it, we have to clear + up_flag */ + if (keycode >= SC_LIM || keycode == 85) + up_flag = 0; + } } else - rep = set_bit(scancode, key_down); + rep = set_bit(keycode, key_down); if (raw_mode) goto end_kbd_intr; - if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) { - put_queue(scancode + up_flag); + if (kbd->kbdmode == VC_MEDIUMRAW) { + /* soon keycodes will require more than one byte */ + put_queue(keycode + up_flag); goto end_kbd_intr; } /* * Small change in philosophy: earlier we defined repetition by - * rep = scancode == prev_keysym; - * prev_keysym = scancode; + * rep = keycode == prev_keycode; + * prev_keycode = keycode; * but now by the fact that the depressed key was down already. - * Does this ever make a difference? + * Does this ever make a difference? Yes. */ /* @@ -340,21 +463,45 @@ static void keyboard_interrupt(int int_pt_regs) if (!rep || (vc_kbd_mode(kbd,VC_REPEAT) && tty && (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) { - u_short key_code; + u_short keysym; u_char type; /* the XOR below used to be an OR */ int shift_final = shift_state ^ kbd->lockstate; - - key_code = key_map[shift_final][scancode]; - type = KTYP(key_code); - - if (type == KT_LETTER) { - type = KT_LATIN; - if (vc_kbd_led(kbd,VC_CAPSLOCK)) - key_code = key_map[shift_final ^ (1<= 0xf0) { + type -= 0xf0; + if (type == KT_LETTER) { + type = KT_LATIN; + if (vc_kbd_led(kbd, VC_CAPSLOCK)) { + key_map = key_maps[shift_final ^ (1<kbdmode == VC_UNICODE) ? */ + if (!up_flag) + to_utf8(keysym); + } + } else { + /* maybe beep? */ + /* we have at least to update shift_state */ +#if 0 /* how? two almost equivalent choices follow */ + compute_shiftstate(); +#else + keysym = U(plain_map[keycode]); + type = KTYP(keysym); + if (type == KT_SHIFT) + (*key_handler[type])(keysym & 0xff, up_flag); +#endif } - (*key_handler[type])(key_code & 0xff, up_flag); } end_kbd_intr: @@ -403,14 +550,14 @@ static void caps_toggle(void) { if (rep) return; - chg_vc_kbd_led(kbd,VC_CAPSLOCK); + chg_vc_kbd_led(kbd, VC_CAPSLOCK); } static void caps_on(void) { if (rep) return; - set_vc_kbd_led(kbd,VC_CAPSLOCK); + set_vc_kbd_led(kbd, VC_CAPSLOCK); } static void show_ptregs(void) @@ -439,7 +586,7 @@ static void hold(void) /* * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty); * these routines are also activated by ^S/^Q. - * (And SCROLLOCK can also be set by the ioctl KDSETLED.) + * (And SCROLLOCK can also be set by the ioctl KDSKBLED.) */ if (tty->stopped) start_tty(tty); @@ -447,14 +594,6 @@ static void hold(void) stop_tty(tty); } -#if 0 -/* unused at present - and the VC_PAUSE bit is not used anywhere either */ -static void pause(void) -{ - chg_vc_kbd_mode(kbd,VC_PAUSE); -} -#endif - static void num(void) { if (vc_kbd_mode(kbd,VC_APPLIC)) { @@ -467,10 +606,36 @@ static void num(void) static void lastcons(void) { - /* pressing alt-printscreen switches to the last used console, ChN */ + /* switch to the last used console, ChN */ want_console = last_console; } +static void decr_console(void) +{ + int i; + + for (i = fg_console-1; i != fg_console; i--) { + if (i == -1) + i = MAX_NR_CONSOLES-1; + if (vc_cons_allocated(i)) + break; + } + want_console = i; +} + +static void incr_console(void) +{ + int i; + + for (i = fg_console+1; i != fg_console; i++) { + if (i == MAX_NR_CONSOLES) + i = 0; + if (vc_cons_allocated(i)) + break; + } + want_console = i; +} + static void send_intr(void) { if (!tty || (tty->termios && I_IGNBRK(tty))) @@ -478,12 +643,12 @@ static void send_intr(void) tty_insert_flip_char(tty, 0, TTY_BREAK); } -static void scrll_forw(void) +static void scroll_forw(void) { scrollfront(0); } -static void scrll_back(void) +static void scroll_back(void) { scrollback(0); } @@ -511,37 +676,24 @@ static void SAK(void) * attention key is that it should be guaranteed to always * work. */ - clr_vc_kbd_flag(kbd, VC_RAW); - clr_vc_kbd_flag(kbd, VC_MEDIUMRAW); - vt_cons[fg_console].vc_mode = KD_TEXT; - vt_cons[fg_console].vt_mode.mode = VT_AUTO; - vt_cons[fg_console].vt_mode.waitv = 0; - vt_cons[fg_console].vt_mode.relsig = 0; - vt_cons[fg_console].vt_mode.acqsig = 0; - vt_cons[fg_console].vt_mode.frsig = 0; - vt_cons[fg_console].vt_pid = -1; - vt_cons[fg_console].vt_newvt = -1; - unblank_screen(); + reset_vc(fg_console); + unblank_screen(); /* not in interrupt routine? */ #endif } -static void do_spec(unsigned char value, char up_flag) +static void do_ignore(unsigned char value, char up_flag) { - typedef void (*fnp)(void); - fnp fn_table[] = { - NULL, enter, show_ptregs, show_mem, - show_state, send_intr, lastcons, caps_toggle, - num, hold, scrll_forw, scrll_back, - boot_it, caps_on, compose, SAK - }; +} +static void do_spec(unsigned char value, char up_flag) +{ if (up_flag) return; - if (value >= SIZE(fn_table)) + if (value >= SIZE(spec_fn_table)) return; - if (!fn_table[value]) + if (!spec_fn_table[value]) return; - fn_table[value](); + spec_fn_table[value](); } static void do_lowercase(unsigned char value, char up_flag) @@ -624,9 +776,10 @@ static void do_fn(unsigned char value, char up_flag) { if (up_flag) return; - if (value < SIZE(func_table)) - puts_queue(func_table[value]); - else + if (value < SIZE(func_table)) { + if (func_table[value]) + puts_queue(func_table[value]); + } else printk("do_fn called with value=%d\n", value); } @@ -703,7 +856,8 @@ static void do_shift(unsigned char value, char up_flag) if (rep) return; - /* kludge... */ + /* Mimic typewriter: + a CapsShift key acts like Shift but undoes CapsLock */ if (value == KVAL(K_CAPSSHIFT)) { value = KVAL(K_SHIFT); if (!up_flag) @@ -725,13 +879,17 @@ static void do_shift(unsigned char value, char up_flag) /* kludge */ if (up_flag && shift_state != old_state && npadch != -1) { - put_queue(npadch); + if (kbd->kbdmode == VC_UNICODE) + to_utf8(npadch & 0xffff); + else + put_queue(npadch & 0xff); npadch = -1; } } /* called after returning from RAW mode or when changing consoles - recompute k_down[] and shift_state from key_down[] */ +/* maybe called when keymap is undefined, so that shiftkey release is seen */ void compute_shiftstate(void) { int i, j, k, sym, val; @@ -745,9 +903,11 @@ void compute_shiftstate(void) k = (i<<5); for(j=0; j<32; j++,k++) if(test_bit(k, key_down)) { - sym = key_map[0][k]; + sym = U(plain_map[k]); if(KTYP(sym) == KT_SHIFT) { val = KVAL(sym); + if (val == KVAL(K_CAPSSHIFT)) + val = KVAL(K_SHIFT); k_down[val]++; shift_state |= (1<ledmode = LED_SHOW_IOCTL; + } else + kbd->ledmode = LED_SHOW_FLAGS; + set_leds(); +} + +static struct ledptr { + unsigned int *addr; + unsigned int mask; + unsigned char valid:1; +} ledptrs[3]; + +void register_leds(int console, unsigned int led, + unsigned int *addr, unsigned int mask) { + struct kbd_struct *kbd = kbd_table + console; + if (led < 3) { + ledptrs[led].addr = addr; + ledptrs[led].mask = mask; + ledptrs[led].valid = 1; + kbd->ledmode = LED_SHOW_MEM; + } else + kbd->ledmode = LED_SHOW_FLAGS; +} + +static inline unsigned char getleds(void){ + struct kbd_struct *kbd = kbd_table + fg_console; + unsigned char leds; + + if (kbd->ledmode == LED_SHOW_IOCTL) + return ledioctl; + leds = kbd->ledflagstate; + if (kbd->ledmode == LED_SHOW_MEM) { + if (ledptrs[0].valid) { + if (*ledptrs[0].addr & ledptrs[0].mask) + leds |= 1; + else + leds &= ~1; + } + if (ledptrs[1].valid) { + if (*ledptrs[1].addr & ledptrs[1].mask) + leds |= 2; + else + leds &= ~2; + } + if (ledptrs[2].valid) { + if (*ledptrs[2].addr & ledptrs[2].mask) + leds |= 4; + else + leds &= ~4; + } + } + return leds; +} + /* * This routine is the bottom half of the keyboard interrupt * routine, and runs with all interrupts enabled. It does @@ -828,11 +1068,10 @@ static int send_data(unsigned char data) */ static void kbd_bh(void * unused) { - static unsigned char old_leds = 0xff; - unsigned char leds = kbd_table[fg_console].ledstate; + unsigned char leds = getleds(); - if (leds != old_leds) { - old_leds = leds; + if (leds != ledstate) { + ledstate = leds; if (!send_data(0xed) || !send_data(leds)) send_data(0xf4); /* re-enable kbd if any errors */ } @@ -840,6 +1079,9 @@ static void kbd_bh(void * unused) if (want_console != fg_console) { last_console = fg_console; change_console(want_console); + /* we only changed when the console had already + been allocated - a new console is not created + in an interrupt routine */ } want_console = -1; } @@ -880,16 +1122,18 @@ void hard_reset_now(void) unsigned long kbd_init(unsigned long kmem_start) { int i; - struct kbd_struct * kbd; + struct kbd_struct kbd0; extern struct tty_driver console_driver; - kbd = kbd_table + 0; - for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) { - kbd->ledstate = KBD_DEFLEDS; - kbd->default_ledstate = KBD_DEFLEDS; - kbd->lockstate = KBD_DEFLOCK; - kbd->modeflags = KBD_DEFMODE; - } + kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; + kbd0.ledmode = LED_SHOW_FLAGS; + kbd0.lockstate = KBD_DEFLOCK; + kbd0.modeflags = KBD_DEFMODE; + kbd0.kbdmode = VC_XLATE; + + for (i = 0 ; i < MAX_NR_CONSOLES ; i++) + kbd_table[i] = kbd0; + ttytab = console_driver.table; bh_base[KEYBOARD_BH].routine = kbd_bh; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index d80445ab2e0e..4e721da79a6a 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -1,5 +1,5 @@ /* - * linux/kernel/chr_drv/mem.c + * linux/drivers/char/mem.c * * Copyright (C) 1991, 1992 Linus Torvalds */ diff --git a/drivers/char/mouse.c b/drivers/char/mouse.c index 107405f82525..bfab4185eb85 100644 --- a/drivers/char/mouse.c +++ b/drivers/char/mouse.c @@ -1,5 +1,5 @@ /* - * linux/kernel/chr_drv/mouse.c + * linux/drivers/char/mouse.c * * Generic mouse open routine by Johan Myreen * diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c index 9f43a1a83ec4..edc4c2baa227 100644 --- a/drivers/char/psaux.c +++ b/drivers/char/psaux.c @@ -1,5 +1,5 @@ /* - * linux/kernel/chr_drv/psaux.c + * linux/drivers/char/psaux.c * * Driver for PS/2 type mouse by Johan Myreen. * diff --git a/drivers/char/pty.c b/drivers/char/pty.c index f091af3d78a0..6577dcf565e4 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -1,5 +1,5 @@ /* - * linux/kernel/chr_drv/pty.c + * linux/drivers/char/pty.c * * Copyright (C) 1991, 1992 Linus Torvalds */ diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 768b7b5f11b6..f64072b389d2 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -1,5 +1,5 @@ /* - * linux/kernel/serial.c + * linux/drivers/char/serial.c * * Copyright (C) 1991, 1992 Linus Torvalds * @@ -987,7 +987,6 @@ static int startup(struct async_struct * info) static void shutdown(struct async_struct * info) { unsigned long flags; - unsigned long timeout; int retval; if (!(info->flags & ASYNC_INITIALIZED)) @@ -1039,24 +1038,6 @@ static void shutdown(struct async_struct * info) (void) inb((info->port & 0xFE0) | 0x01F); } - /* - * Before we drop DTR, make sure the UART transmitter has - * completely drained; this is especially important if there - * is a transmit FIFO! - * - * We busy loop here, which is not great; unfortunately the - * UART does not provide an interrupt for TEMT, and putting it - * in the interrupt handler would slow down normal accesses - * anyway. - */ - sti(); - timeout = jiffies + info->timeout; - while (!(serial_inp(info, UART_LSR) & UART_LSR_TEMT)) { - if (jiffies > timeout) - break; - } - cli(); - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); info->MCR_noint &= ~(UART_MCR_DTR|UART_MCR_RTS); @@ -1142,15 +1123,20 @@ static void change_speed(struct async_struct *info) } else fcr = 0; - /* CTS flow control flag */ - if (cflag & CRTSCTS) + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + if (cflag & CRTSCTS) { info->flags |= ASYNC_CTS_FLOW; - else + info->IER |= UART_IER_MSI; + } else info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; - else + else { info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + serial_out(info, UART_IER, info->IER); /* * Set up parity check flag @@ -1749,12 +1735,17 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) static void rs_close(struct tty_struct *tty, struct file * filp) { struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long flags; if (!info || serial_paranoia_check(info, tty->device, "rs_close")) return; - if (tty_hung_up_p(filp)) + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); return; + } #ifdef SERIAL_DEBUG_OPEN printk("rs_close ttys%d, count = %d\n", info->line, info->count); @@ -1776,8 +1767,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp) info->line, info->count); info->count = 0; } - if (info->count) + if (info->count) { + restore_flags(flags); return; + } info->flags |= ASYNC_CLOSING; /* * Save the termios structure, since this port may have @@ -1787,8 +1780,19 @@ static void rs_close(struct tty_struct *tty, struct file * filp) info->normal_termios = *tty->termios; if (info->flags & ASYNC_CALLOUT_ACTIVE) info->callout_termios = *tty->termios; - if (info->flags & ASYNC_INITIALIZED) + if (info->flags & ASYNC_INITIALIZED) { wait_until_sent(tty, 3000); /* 30 seconds timeout */ + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + while (!(serial_inp(info, UART_LSR) & UART_LSR_TEMT)) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + info->timeout; + schedule(); + } + } shutdown(info); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -1815,6 +1819,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); + restore_flags(flags); } /* @@ -1845,7 +1850,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, { struct wait_queue wait = { current, NULL }; int retval; - int do_clocal = C_CLOCAL(tty); + int do_clocal = 0; /* * If the device is in the middle of being closed, then block @@ -1893,6 +1898,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -1990,12 +1998,6 @@ int rs_open(struct tty_struct *tty, struct file * filp) return -ENOMEM; } - if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->normal_termios; - else - *tty->termios = info->callout_termios; - } /* * Start up serial port */ @@ -2012,6 +2014,14 @@ int rs_open(struct tty_struct *tty, struct file * filp) return retval; } + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } + info->session = current->session; info->pgrp = current->pgrp; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index c194f9671594..d79e45124938 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1,5 +1,5 @@ /* - * linux/kernel/tty_io.c + * linux/drivers/char/tty_io.c * * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -109,9 +109,12 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on); */ char *_tty_name(struct tty_struct *tty, char *buf) { - sprintf(buf, "%s%d", tty->driver.name, - MINOR(tty->device) - tty->driver.minor_start + - tty->driver.name_base); + if (tty) + sprintf(buf, "%s%d", tty->driver.name, + MINOR(tty->device) - tty->driver.minor_start + + tty->driver.name_base); + else + strcpy(buf, "NULL tty"); return buf; } @@ -363,6 +366,8 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops) if (p->tty == tty) p->tty = NULL; } + if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) + *tty->termios = tty->driver.init_termios; if (tty->driver.hangup) (tty->driver.hangup)(tty); } @@ -439,6 +444,19 @@ int vt_waitactive(void) #define vt_wake_waitactive() wake_up(&vt_activate_queue) +void reset_vc(unsigned int new_console) +{ + vt_cons[new_console]->vc_mode = KD_TEXT; + kbd_table[new_console].kbdmode = VC_XLATE; + vt_cons[new_console]->vt_mode.mode = VT_AUTO; + vt_cons[new_console]->vt_mode.waitv = 0; + vt_cons[new_console]->vt_mode.relsig = 0; + vt_cons[new_console]->vt_mode.acqsig = 0; + vt_cons[new_console]->vt_mode.frsig = 0; + vt_cons[new_console]->vt_pid = -1; + vt_cons[new_console]->vt_newvt = -1; +} + /* * Performs the back end of a vt switch */ @@ -446,15 +464,17 @@ void complete_change_console(unsigned int new_console) { unsigned char old_vc_mode; - if (new_console == fg_console || new_console >= NR_CONSOLES) - return; + if (new_console == fg_console) + return; + if (!vc_cons_allocated(new_console)) + return; /* * If we're switching, we could be going from KD_GRAPHICS to * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ - old_vc_mode = vt_cons[fg_console].vc_mode; + old_vc_mode = vt_cons[fg_console]->vc_mode; update_screen(new_console); /* @@ -462,15 +482,15 @@ void complete_change_console(unsigned int new_console) * telling it that it has acquired. Also check if it has died and * clean up (similar to logic employed in change_console()) */ - if (vt_cons[new_console].vt_mode.mode == VT_PROCESS) + if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ - if (kill_proc(vt_cons[new_console].vt_pid, - vt_cons[new_console].vt_mode.acqsig, + if (kill_proc(vt_cons[new_console]->vt_pid, + vt_cons[new_console]->vt_mode.acqsig, 1) != 0) { /* @@ -482,16 +502,7 @@ void complete_change_console(unsigned int new_console) * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ - vt_cons[new_console].vc_mode = KD_TEXT; - clr_vc_kbd_mode(kbd_table + new_console, VC_RAW); - clr_vc_kbd_mode(kbd_table + new_console, VC_MEDIUMRAW); - vt_cons[new_console].vt_mode.mode = VT_AUTO; - vt_cons[new_console].vt_mode.waitv = 0; - vt_cons[new_console].vt_mode.relsig = 0; - vt_cons[new_console].vt_mode.acqsig = 0; - vt_cons[new_console].vt_mode.frsig = 0; - vt_cons[new_console].vt_pid = -1; - vt_cons[new_console].vt_newvt = -1; + reset_vc(new_console); } } @@ -499,9 +510,9 @@ void complete_change_console(unsigned int new_console) * We do this here because the controlling process above may have * gone, and so there is now a new vc_mode */ - if (old_vc_mode != vt_cons[new_console].vc_mode) + if (old_vc_mode != vt_cons[new_console]->vc_mode) { - if (vt_cons[new_console].vc_mode == KD_TEXT) + if (vt_cons[new_console]->vc_mode == KD_TEXT) unblank_screen(); else { timer_active &= ~(1<= NR_CONSOLES) + if (new_console == fg_console) + return; + if (!vc_cons_allocated(new_console)) return; /* @@ -539,15 +552,15 @@ void change_console(unsigned int new_console) * the user waits just the right amount of time :-) and revert the * vt to auto control. */ - if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS) + if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ - if (kill_proc(vt_cons[fg_console].vt_pid, - vt_cons[fg_console].vt_mode.relsig, + if (kill_proc(vt_cons[fg_console]->vt_pid, + vt_cons[fg_console]->vt_mode.relsig, 1) == 0) { /* @@ -555,7 +568,7 @@ void change_console(unsigned int new_console) * return. The process needs to send us a * VT_RELDISP ioctl to complete the switch. */ - vt_cons[fg_console].vt_newvt = new_console; + vt_cons[fg_console]->vt_newvt = new_console; return; } @@ -568,16 +581,8 @@ void change_console(unsigned int new_console) * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ - vt_cons[fg_console].vc_mode = KD_TEXT; - clr_vc_kbd_mode(kbd_table + fg_console, VC_RAW); - clr_vc_kbd_mode(kbd_table + fg_console, VC_MEDIUMRAW); - vt_cons[fg_console].vt_mode.mode = VT_AUTO; - vt_cons[fg_console].vt_mode.waitv = 0; - vt_cons[fg_console].vt_mode.relsig = 0; - vt_cons[fg_console].vt_mode.acqsig = 0; - vt_cons[fg_console].vt_mode.frsig = 0; - vt_cons[fg_console].vt_pid = -1; - vt_cons[fg_console].vt_newvt = -1; + reset_vc(fg_console); + /* * Fall through to normal (VT_AUTO) handling of the switch... */ @@ -586,7 +591,7 @@ void change_console(unsigned int new_console) /* * Ignore all switches in KD_GRAPHICS+VT_AUTO mode */ - if (vt_cons[fg_console].vc_mode == KD_GRAPHICS) + if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; complete_change_console(new_console); @@ -971,27 +976,31 @@ static void release_dev(struct file * filp) if (tty->count) return; - /* - * Make sure there aren't any processes that still think this - * tty is their controlling tty. - */ - for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { - if ((*p) && (*p)->tty == tty) - (*p)->tty = NULL; - } - if (o_tty) { if (o_tty->count) return; tty->driver.other->table[idx] = NULL; tty->driver.other->termios[idx] = NULL; - tty->driver.other->termios_locked[idx] = NULL; + kfree_s(o_tp, sizeof(struct termios)); } #ifdef TTY_DEBUG_HANGUP printk("freeing tty structure..."); #endif + /* + * Make sure there aren't any processes that still think this + * tty is their controlling tty. + */ + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (*p == 0) + continue; + if ((*p)->tty == tty) + (*p)->tty = NULL; + if (o_tty && (*p)->tty == o_tty) + (*p)->tty = NULL; + } + /* * Shutdown the current line discipline, and reset it to * N_TTY. @@ -1004,9 +1013,7 @@ static void release_dev(struct file * filp) tty->driver.table[idx] = NULL; if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { tty->driver.termios[idx] = NULL; - tty->driver.termios_locked[idx] = NULL; kfree_s(tp, sizeof(struct termios)); - kfree_s(ltp, sizeof(struct termios)); } if (tty == redirect || o_tty == redirect) redirect = NULL; @@ -1037,10 +1044,6 @@ static void release_dev(struct file * filp) (*o_tty->driver.refcount)--; free_page((unsigned long) o_tty); } - if (o_tp) - kfree_s(o_tp, sizeof(struct termios)); - if (o_ltp) - kfree_s(o_ltp, sizeof(struct termios)); } /* @@ -1087,13 +1090,14 @@ retry_open: #ifdef TTY_DEBUG_HANGUP printk("opening %s...", tty_name(tty)); #endif - if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) - retval = -EBUSY; - else if (tty->driver.open) + if (tty->driver.open) retval = tty->driver.open(tty, filp); else retval = -ENODEV; + if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) + retval = -EBUSY; + if (retval) { #ifdef TTY_DEBUG_HANGUP printk("error %d in opening %s...", retval, tty_name(tty)); @@ -1396,12 +1400,18 @@ static int tty_ioctl(struct inode * inode, struct file * file, return set_selection(arg, tty); case 3: return paste_selection(tty); +#endif /* CONFIG_SELECTION */ case 4: unblank_screen(); return 0; +#ifdef CONFIG_SELECTION case 5: return sel_loadlut(arg); case 6: + /* Make it possible to react to Shift+Mousebutton */ + /* Note that shift_state is an undocumented + kernel-internal variable; programs not closely + related to the kernel should not use this. */ put_fs_byte(shift_state,arg); return 0; case 7: @@ -1451,6 +1461,8 @@ void do_SAK( struct tty_struct *tty) int i; struct file *filp; + if (!tty) + return; if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (tty->driver.flush_buffer) @@ -1563,6 +1575,44 @@ int tty_register_driver(struct tty_driver *driver) return error; } +/* + * Called by a tty driver to unregister itself. + */ +int tty_unregister_driver(struct tty_driver *driver) +{ + int retval; + struct tty_driver *p; + int found = 0; + int major_inuse = 0; + + if (driver->refcount) + return -EBUSY; + + for (p = tty_drivers; p; p = p->next) { + if (p == driver) + found++; + else if (p->major == driver->major) + major_inuse++; + } + + if (!major_inuse) { + retval = unregister_chrdev(driver->major, driver->name); + if (retval) + return retval; + } + + if (driver->prev) + driver->prev->next = driver->next; + else + tty_drivers = driver->next; + + if (driver->next) + driver->next = driver->next->prev; + + return 0; +} + + /* * Initialize the console device. This is called *early*, so * we can't necessarily depend on lots of kernel help here. diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 098ab9f3311d..796fe74d8193 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -1,5 +1,5 @@ /* - * linux/kernel/drivers/char/tty_ioctl.c + * linux/drivers/char/tty_ioctl.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * @@ -314,32 +314,22 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, (unsigned long *) arg); return 0; case TIOCGLCKTRMIOS: - retval = verify_area(VERIFY_READ, (void *) arg, - sizeof (unsigned long)); - if (retval) - return retval; - arg = get_fs_long((unsigned long *) arg); retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof (struct termios)); if (retval) return retval; memcpy_tofs((struct termios *) arg, - &real_tty->termios_locked, + real_tty->termios_locked, sizeof (struct termios)); return 0; case TIOCSLCKTRMIOS: if (!suser()) return -EPERM; - retval = verify_area(VERIFY_READ, (void *) arg, - sizeof (unsigned long)); - if (retval) - return retval; - arg = get_fs_long((unsigned long *) arg); retval = verify_area(VERIFY_READ, (void *) arg, sizeof (struct termios)); if (retval) return retval; - memcpy_fromfs(&real_tty->termios_locked, + memcpy_fromfs(real_tty->termios_locked, (struct termios *) arg, sizeof (struct termios)); return 0; diff --git a/drivers/char/uni_to_437.c b/drivers/char/uni_to_437.c new file mode 100644 index 000000000000..46d0f08805c7 --- /dev/null +++ b/drivers/char/uni_to_437.c @@ -0,0 +1,169 @@ +/* + * non-Latin-1 (>0x00ff) Unicode -> IBM CP437 conversion hash table + * Markus Kuhn + */ +#define IBM_HASHSIZE 146 +#define IBM_HASHSTEP 19 +#define IBM_HASHLEVEL 4 +static struct { + unsigned short ucs; /* a Unicode code */ + unsigned char ibm437; /* the corresponding IBM code */ +} ibm_hash[IBM_HASHSIZE] = { + {0x221a,0xfb}, {0x2580,0xdf}, {0x2524,0xb4}, {0xffff,0x00}, {0x221e,0xec}, + {0x20a7,0x9e}, {0x2126,0xea}, {0x253c,0xc5}, {0xffff,0x00}, {0x2588,0xdb}, + {0x2666,0x04}, {0x2190,0x1b}, {0x2193,0x19}, {0x2665,0x03}, {0x2195,0x12}, + {0x2663,0x05}, {0x2660,0x06}, {0x2590,0xde}, {0x2022,0x07}, {0x2592,0xb1}, + {0x266c,0x0e}, {0x2502,0xb3}, {0x266a,0x0d}, {0x250c,0xda}, {0x258c,0xdd}, + {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, {0x2191,0x18}, + {0x2261,0xf0}, {0x2514,0xc0}, {0x2192,0x1a}, {0x2264,0xf3}, {0x2194,0x1d}, + {0x2591,0xb0}, {0x0393,0xe2}, {0x2593,0xb2}, {0x2500,0xc4}, {0x251c,0xc3}, + {0x2205,0xed}, {0xffff,0x00}, {0x266b,0x0e}, {0x2518,0xd9}, {0x203c,0x13}, + {0xffff,0x00}, {0x2642,0x0b}, {0x2564,0xd1}, {0x2640,0x0c}, {0x2566,0xcb}, + {0x2561,0xb5}, {0x2560,0xcc}, {0x2563,0xb9}, {0x2562,0xb6}, {0x2510,0xbf}, + {0x256c,0xce}, {0x2008,0x00}, {0x03a6,0xe8}, {0x2569,0xca}, {0x2568,0xd0}, + {0x256b,0xd7}, {0x256a,0xd8}, {0x03a9,0xea}, {0xffff,0x00}, {0xffff,0x00}, + {0x25c0,0x11}, {0x0398,0xe9}, {0x2567,0xcf}, {0xffff,0x00}, {0x2248,0xf7}, + {0x03b1,0xe0}, {0x03a3,0xe4}, {0x2265,0xf2}, {0xffff,0x00}, {0x25cb,0x09}, + {0x03b4,0xeb}, {0x2320,0xf4}, {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, + {0x25c4,0x11}, {0xffff,0x00}, {0xffff,0x00}, {0x03bc,0xe6}, {0x2565,0xd2}, + {0xffff,0x00}, {0x22c5,0xf9}, {0x2302,0x7f}, {0x25d9,0x0a}, {0x25d8,0x08}, + {0xffff,0x00}, {0x03c4,0xe7}, {0xffff,0x00}, {0xffff,0x00}, {0x2555,0xb8}, + {0x2554,0xc9}, {0x2557,0xbb}, {0x2556,0xb7}, {0x2551,0xba}, {0x2550,0xcd}, + {0x2553,0xd6}, {0x2552,0xd5}, {0x255d,0xbc}, {0x255c,0xbd}, {0x255f,0xc7}, + {0x2310,0xa9}, {0x2559,0xd3}, {0x2558,0xd4}, {0x255b,0xbe}, {0x255a,0xc8}, + {0xffff,0x00}, {0x0192,0x9f}, {0x2319,0x1c}, {0x2321,0xf5}, {0xffff,0x00}, + {0x25a0,0xfe}, {0xffff,0x00}, {0x21a8,0x17}, {0x263c,0x0f}, {0x25ac,0x16}, + {0x263a,0x01}, {0x263b,0x02}, {0x03c3,0xe5}, {0xffff,0x00}, {0x255e,0xc6}, + {0x03c0,0xe3}, {0x03b2,0xe1}, {0x2300,0xed}, {0xffff,0x00}, {0x25b6,0x10}, + {0x207f,0xfc}, {0xffff,0x00}, {0x2208,0xee}, {0x25b2,0x1e}, {0x220e,0xfe}, + {0x25bc,0x1f}, {0x212b,0x8f}, {0x252c,0xc2}, {0xffff,0x00}, {0x2229,0xef}, + {0xffff,0x00}, {0x25ba,0x10}, {0xffff,0x00}, {0x2584,0xdc}, {0xffff,0x00}, + {0x2534,0xc1} +}; + +/* + * Find the correct PC character set (CP437) code for a + * UCS character outside Latin-1 by hash lookup in ibm_hash[]. + * Return -1 if character not available, return -2 for zero-width + * space characters. + */ +int +conv_uni_to_pc(unsigned long ucs) +{ + int c = -1; + int i, h; + + if (ucs == 0xffff || ucs == 0xfffe) + return -1; + if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) + return -2; + + h = (ucs ^ (ucs >> 8)) % IBM_HASHSIZE; + for (i = 0; i < IBM_HASHLEVEL && c == -1; i++) + if (ibm_hash[h].ucs == ucs) + c = ibm_hash[h].ibm437; + else + if ((h += IBM_HASHSTEP) >= IBM_HASHSIZE) + h -= IBM_HASHSIZE; + + return c; +} + +#if 0 +/* + * Conversion from unicode to ibm pc character set (code page 437) + * + * aeb@cwi.nl, Dec 1993 + */ +#define NOTFOUND 254 /* small square */ + +static struct unipc { + long unicode; + unsigned char pc; +} uni_to_pc[255] = { + {0x0020, 0x20}, {0x0021, 0x21}, {0x0022, 0x22}, {0x0023, 0x23}, + {0x0024, 0x24}, {0x0025, 0x25}, {0x0026, 0x26}, {0x0027, 0x27}, + {0x0028, 0x28}, {0x0029, 0x29}, {0x002A, 0x2A}, {0x002B, 0x2B}, + {0x002C, 0x2C}, {0x002D, 0x2D}, {0x002E, 0x2E}, {0x002F, 0x2F}, + {0x0030, 0x30}, {0x0031, 0x31}, {0x0032, 0x32}, {0x0033, 0x33}, + {0x0034, 0x34}, {0x0035, 0x35}, {0x0036, 0x36}, {0x0037, 0x37}, + {0x0038, 0x38}, {0x0039, 0x39}, {0x003A, 0x3A}, {0x003B, 0x3B}, + {0x003C, 0x3C}, {0x003D, 0x3D}, {0x003E, 0x3E}, {0x003F, 0x3F}, + {0x0040, 0x40}, {0x0041, 0x41}, {0x0042, 0x42}, {0x0043, 0x43}, + {0x0044, 0x44}, {0x0045, 0x45}, {0x0046, 0x46}, {0x0047, 0x47}, + {0x0048, 0x48}, {0x0049, 0x49}, {0x004A, 0x4A}, {0x004B, 0x4B}, + {0x004C, 0x4C}, {0x004D, 0x4D}, {0x004E, 0x4E}, {0x004F, 0x4F}, + {0x0050, 0x50}, {0x0051, 0x51}, {0x0052, 0x52}, {0x0053, 0x53}, + {0x0054, 0x54}, {0x0055, 0x55}, {0x0056, 0x56}, {0x0057, 0x57}, + {0x0058, 0x58}, {0x0059, 0x59}, {0x005A, 0x5A}, {0x005B, 0x5B}, + {0x005C, 0x5C}, {0x005D, 0x5D}, {0x005E, 0x5E}, {0x005F, 0x5F}, + {0x0060, 0x60}, {0x0061, 0x61}, {0x0062, 0x62}, {0x0063, 0x63}, + {0x0064, 0x64}, {0x0065, 0x65}, {0x0066, 0x66}, {0x0067, 0x67}, + {0x0068, 0x68}, {0x0069, 0x69}, {0x006A, 0x6A}, {0x006B, 0x6B}, + {0x006C, 0x6C}, {0x006D, 0x6D}, {0x006E, 0x6E}, {0x006F, 0x6F}, + {0x0070, 0x70}, {0x0071, 0x71}, {0x0072, 0x72}, {0x0073, 0x73}, + {0x0074, 0x74}, {0x0075, 0x75}, {0x0076, 0x76}, {0x0077, 0x77}, + {0x0078, 0x78}, {0x0079, 0x79}, {0x007A, 0x7A}, {0x007B, 0x7B}, + {0x007C, 0x7C}, {0x007D, 0x7D}, {0x007E, 0x7E}, {0x00A0, 0xFF}, + {0x00A1, 0xAD}, {0x00A2, 0x9B}, {0x00A3, 0x9C}, {0x00A5, 0x9D}, + {0x00A7, 0x15}, {0x00AA, 0xA6}, {0x00AB, 0xAE}, {0x00AC, 0xAA}, + {0x00B0, 0xF8}, {0x00B1, 0xF1}, {0x00B2, 0xFD}, {0x00B5, 0xE6}, + {0x00B6, 0x14}, {0x00B7, 0xFA}, {0x00BA, 0xA7}, {0x00BB, 0xAF}, + {0x00BC, 0xAC}, {0x00BD, 0xAB}, {0x00BF, 0xA8}, {0x00C4, 0x8E}, + {0x00C5, 0x8F}, {0x00C6, 0x92}, {0x00C7, 0x80}, {0x00C9, 0x90}, + {0x00D1, 0xA5}, {0x00D6, 0x99}, {0x00DC, 0x9A}, {0x00DF, 0xE1}, + {0x00E0, 0x85}, {0x00E1, 0xA0}, {0x00E2, 0x83}, {0x00E4, 0x84}, + {0x00E5, 0x86}, {0x00E6, 0x91}, {0x00E7, 0x87}, {0x00E8, 0x8A}, + {0x00E9, 0x82}, {0x00EA, 0x88}, {0x00EB, 0x89}, {0x00EC, 0x8D}, + {0x00ED, 0xA1}, {0x00EE, 0x8C}, {0x00EF, 0x8B}, {0x00F1, 0xA4}, + {0x00F2, 0x95}, {0x00F3, 0xA2}, {0x00F4, 0x93}, {0x00F6, 0x94}, + {0x00F7, 0xF6}, {0x00F9, 0x97}, {0x00FA, 0xA3}, {0x00FB, 0x96}, + {0x00FC, 0x81}, {0x00FF, 0x98}, {0x0192, 0x9F}, {0x0393, 0xE2}, + {0x0398, 0xE9}, {0x03A3, 0xE4}, {0x03A6, 0xE8}, {0x03A9, 0xEA}, + {0x03B1, 0xE0}, {0x03B4, 0xEB}, {0x03B5, 0xEE}, {0x03C0, 0xE3}, + {0x03C3, 0xE5}, {0x03C4, 0xE7}, {0x03C6, 0xED}, {0x2022, 0x07}, + {0x203C, 0x13}, {0x207F, 0xFC}, {0x20A7, 0x9E}, {0x2190, 0x1B}, + {0x2191, 0x18}, {0x2192, 0x1A}, {0x2193, 0x19}, {0x2194, 0x1D}, + {0x2195, 0x12}, {0x21A8, 0x17}, {0x2219, 0xF9}, {0x221A, 0xFB}, + {0x221E, 0xEC}, {0x221F, 0x1C}, {0x2229, 0xEF}, {0x2248, 0xF7}, + {0x2261, 0xF0}, {0x2264, 0xF3}, {0x2265, 0xF2}, {0x2302, 0x7F}, + {0x2310, 0xA9}, {0x2320, 0xF4}, {0x2321, 0xF5}, {0x2500, 0xC4}, + {0x2502, 0xB3}, {0x250C, 0xDA}, {0x2510, 0xBF}, {0x2514, 0xC0}, + {0x2518, 0xD9}, {0x251C, 0xC3}, {0x2524, 0xB4}, {0x252C, 0xC2}, + {0x2534, 0xC1}, {0x253C, 0xC5}, {0x2550, 0xCD}, {0x2551, 0xBA}, + {0x2552, 0xD5}, {0x2553, 0xD6}, {0x2554, 0xC9}, {0x2555, 0xB8}, + {0x2556, 0xB7}, {0x2557, 0xBB}, {0x2558, 0xD4}, {0x2559, 0xD3}, + {0x255A, 0xC8}, {0x255B, 0xBE}, {0x255C, 0xBD}, {0x255D, 0xBC}, + {0x255E, 0xC6}, {0x255F, 0xC7}, {0x2560, 0xCC}, {0x2561, 0xB5}, + {0x2562, 0xB6}, {0x2563, 0xB9}, {0x2564, 0xD1}, {0x2565, 0xD2}, + {0x2566, 0xCB}, {0x2567, 0xCF}, {0x2568, 0xD0}, {0x2569, 0xCA}, + {0x256A, 0xD8}, {0x256B, 0xD7}, {0x256C, 0xCE}, {0x2580, 0xDF}, + {0x2584, 0xDC}, {0x2588, 0xDB}, {0x258C, 0xDD}, {0x2590, 0xDE}, + {0x2591, 0xB0}, {0x2592, 0xB1}, {0x2593, 0xB2}, {0x25A0, 0xFE}, + {0x25AC, 0x16}, {0x25B2, 0x1E}, {0x25BA, 0x10}, {0x25BC, 0x1F}, + {0x25C4, 0x11}, {0x25CB, 0x09}, {0x25D8, 0x08}, {0x25D9, 0x0A}, + {0x263A, 0x01}, {0x263B, 0x02}, {0x263C, 0x0F}, {0x2640, 0x0C}, + {0x2642, 0x0B}, {0x2660, 0x06}, {0x2663, 0x05}, {0x2665, 0x03}, + {0x2666, 0x04}, {0x266A, 0x0D}, {0x266B, 0x0E} +}; + +unsigned char +conv_uni_to_pc(unsigned long u) { + /* Binary search - no doubt this can be sped up using hash codes */ + /* (or by table lookup if we are in the first half) */ + int step = 128; + struct unipc *up = uni_to_pc + step - 1; + + while(1) { + if(up->unicode == u) + return up->pc; + step >>= 1; + if(!step) + return NOTFOUND; + if(up->unicode < u) + up += step; + else + up -= step; + } +} +#endif diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 107eb727824f..c5816fb2b630 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -1,8 +1,10 @@ /* - * kernel/chr_drv/vt.c + * linux/drivers/char/vt.c * * Copyright (C) 1992 obz under the linux copyright + * * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 + * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994 */ #include @@ -14,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,6 +27,8 @@ extern struct tty_driver console_driver; +#define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count) + /* * Console (vt and kd) routines, as defined by USL SVR4 manual, and by * experimentation and study of X386 SYSV handling. @@ -31,13 +36,13 @@ extern struct tty_driver console_driver; * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will - * always treat our set of vt as numbered 1..NR_CONSOLES (corresponding to - * ttys 0..NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using + * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to + * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing * to the current console is done by the main ioctl code. */ -struct vt_struct vt_cons[NR_CONSOLES]; +struct vt_struct *vt_cons[MAX_NR_CONSOLES]; asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on); @@ -46,6 +51,8 @@ extern void change_console(unsigned int new_console); extern void complete_change_console(unsigned int new_console); extern int vt_waitactive(void); +extern unsigned int keymap_count; + /* * routines to load custom translation table and EGA/VGA font from console.c */ @@ -118,14 +125,15 @@ kd_mksound(unsigned int count, unsigned int ticks) int vt_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int console, i; + int i; + unsigned int console; unsigned char ucval; struct kbd_struct * kbd; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; console = vt->vc_num; - if (console < 0 || console >= NR_CONSOLES) + if (!vc_cons_allocated(console)) /* impossible? */ return -ENOIOCTLCMD; kbd = kbd_table + console; @@ -189,9 +197,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, default: return -EINVAL; } - if (vt_cons[console].vc_mode == (unsigned char) arg) + if (vt_cons[console]->vc_mode == (unsigned char) arg) return 0; - vt_cons[console].vc_mode = (unsigned char) arg; + vt_cons[console]->vc_mode = (unsigned char) arg; if (console != fg_console) return 0; /* @@ -208,7 +216,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDGETMODE: i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); if (!i) - put_fs_long(vt_cons[console].vc_mode, (unsigned long *) arg); + put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg); return i; case KDMAPDISP: @@ -222,16 +230,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDSKBMODE: switch(arg) { case K_RAW: - set_vc_kbd_mode(kbd, VC_RAW); - clr_vc_kbd_mode(kbd, VC_MEDIUMRAW); + kbd->kbdmode = VC_RAW; break; case K_MEDIUMRAW: - clr_vc_kbd_mode(kbd, VC_RAW); - set_vc_kbd_mode(kbd, VC_MEDIUMRAW); + kbd->kbdmode = VC_MEDIUMRAW; break; case K_XLATE: - clr_vc_kbd_mode(kbd, VC_RAW); - clr_vc_kbd_mode(kbd, VC_MEDIUMRAW); + kbd->kbdmode = VC_XLATE; + compute_shiftstate(); + break; + case K_UNICODE: + kbd->kbdmode = VC_UNICODE; compute_shiftstate(); break; default: @@ -244,8 +253,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDGKBMODE: i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); if (!i) { - ucval = (vc_kbd_mode(kbd, VC_RAW) ? K_RAW : - vc_kbd_mode(kbd, VC_MEDIUMRAW) ? K_MEDIUMRAW : + ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : + (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : + (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : K_XLATE); put_fs_long(ucval, (unsigned long *) arg); } @@ -278,6 +288,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDGKBENT: { struct kbentry * const a = (struct kbentry *)arg; + ushort *key_map, val; u_char s; i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry)); @@ -285,15 +296,23 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return i; if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS) return -EINVAL; - if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS) + if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS) return -EINVAL; - put_fs_word(key_map[s][i], (short *) &a->kb_value); + key_map = key_maps[s]; + if (key_map) { + val = U(key_map[i]); + if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) + val = K_HOLE; + } else + val = (i ? K_HOLE : K_NOSUCHMAP); + put_fs_word(val, (short *) &a->kb_value); return 0; } case KDSKBENT: { const struct kbentry * a = (struct kbentry *)arg; + ushort *key_map; u_char s; u_short v; @@ -302,20 +321,55 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return i; if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS) return -EINVAL; - if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS) + if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS) return -EINVAL; - if (KTYP(v = get_fs_word(&a->kb_value)) >= NR_TYPES) + v = get_fs_word(&a->kb_value); + if (!i && v == K_NOSUCHMAP) { + /* disallocate map */ + key_map = key_maps[s]; + if (key_map) { + key_maps[s] = 0; + if (key_map[0] == U(K_ALLOCATED)) { + kfree_s(key_map, sizeof(plain_map)); + keymap_count--; + } + } + return 0; + } + + if (KTYP(v) < NR_TYPES) { + if (KVAL(v) > max_vals[KTYP(v)]) return -EINVAL; - if (KVAL(v) > max_vals[KTYP(v)]) + } else + if (kbd->kbdmode != VC_UNICODE) return -EINVAL; + + /* assignment to entry 0 only tests validity of args */ + if (!i) + return 0; + + if (!(key_map = key_maps[s])) { + if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser()) + return -EPERM; + + key_map = (ushort *) kmalloc(sizeof(plain_map), + GFP_KERNEL); + if (!key_map) + return -ENOMEM; + key_maps[s] = key_map; + key_map[0] = U(K_ALLOCATED); + for (s = 1; s < NR_KEYS; s++) + key_map[s] = U(K_HOLE); + keymap_count++; + } /* * Only the Superuser can set or unset the Secure * Attention Key. */ - if (((key_map[s][i] == K_SAK) || (v == K_SAK)) && + if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) && !suser()) return -EPERM; - key_map[s][i] = v; + key_map[i] = U(v); return 0; } @@ -324,65 +378,91 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, struct kbsentry *a = (struct kbsentry *)arg; char *p; u_char *q; + int sz; i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry)); if (i) return i; - if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC || i < 0) + if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0) return -EINVAL; + sz = sizeof(a->kb_string) - 1; /* sz should have been + a struct member */ q = a->kb_string; p = func_table[i]; - if(!p) { - /* beware of tables generated for a smaller NR_FUNC */ - printk("KDGKBSENT error: func_table[%d] is nil.\n", - i); - return -EINVAL; - } - for ( ; *p; p++) - put_fs_byte(*p, q++); + if(p) + for ( ; *p && sz; p++, sz--) + put_fs_byte(*p, q++); put_fs_byte(0, q); - return 0; + return ((p && *p) ? -EOVERFLOW : 0); } case KDSKBSENT: { struct kbsentry * const a = (struct kbsentry *)arg; int delta; - char *first_free; - int k; + char *first_free, *fj, *fnw; + int j, k, sz; u_char *p; char *q; i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry)); if (i) return i; - if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC) + if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC) return -EINVAL; q = func_table[i]; - if (!q) { - /* beware of tables generated for a smaller NR_FUNC */ - printk("KDSKBSENT error: func_table[%d] is nil.\n", - i); - return -EINVAL; - } - delta = -strlen(q); - for (p = a->kb_string; get_fs_byte(p); p++) + + first_free = funcbufptr + (funcbufsize - funcbufleft); + for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ; + if (j < MAX_NR_FUNC) + fj = func_table[j]; + else + fj = first_free; + + delta = (q ? -strlen(q) : 1); + sz = sizeof(a->kb_string); /* sz should have been + a struct member */ + for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--) delta++; - first_free = func_table[NR_FUNC - 1] + - strlen(func_table[NR_FUNC - 1]) + 1; - if ( - delta > 0 && - first_free + delta > func_buf + FUNC_BUFSIZE - ) - return -EINVAL; - if (i < NR_FUNC - 1) { - memmove( - func_table[i + 1] + delta, - func_table[i + 1], - first_free - func_table[i + 1]); - for (k = i + 1; k < NR_FUNC; k++) - if (func_table[k]) /* just to be sure */ + if (!sz) + return -EOVERFLOW; + if (delta <= funcbufleft) { /* it fits in current buf */ + if (j < MAX_NR_FUNC) { + memmove(fj + delta, fj, first_free - fj); + for (k = j; k < MAX_NR_FUNC; k++) + if (func_table[k]) func_table[k] += delta; + } + if (!q) + func_table[i] = fj; + funcbufleft -= delta; + } else { /* allocate a larger buffer */ + sz = 256; + while (sz < funcbufsize - funcbufleft + delta) + sz <<= 1; + fnw = (char *) kmalloc(sz, GFP_KERNEL); + if(!fnw) + return -ENOMEM; + + if (!q) + func_table[i] = fj; + if (fj > funcbufptr) + memmove(fnw, funcbufptr, fj - funcbufptr); + for (k = 0; k < j; k++) + if (func_table[k]) + func_table[k] = fnw + (func_table[k] - funcbufptr); + + if (first_free > fj) { + memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); + for (k = j; k < MAX_NR_FUNC; k++) + if (func_table[k]) + func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; + } + if (funcbufptr != func_buf) + kfree_s(funcbufptr, funcbufsize); + funcbufptr = fnw; + funcbufleft = funcbufleft - delta + sz - funcbufsize; + funcbufsize = sz; } for (p = a->kb_string, q = func_table[i]; ; p++, q++) if (!(*q = get_fs_byte(p))) @@ -392,11 +472,11 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDGKBDIACR: { - struct kbdiacrs *a = (struct kbdiacrs *)arg; + struct kbdiacrs *a = (struct kbdiacrs *)arg; - i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs)); + i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs)); if (i) - return i; + return i; put_fs_long(accent_table_size, &a->kb_cnt); memcpy_tofs(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)); @@ -405,34 +485,51 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDSKBDIACR: { - struct kbdiacrs *a = (struct kbdiacrs *)arg; + struct kbdiacrs *a = (struct kbdiacrs *)arg; unsigned int ct; - i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs)); + i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs)); if (i) - return i; + return i; ct = get_fs_long(&a->kb_cnt); if (ct >= MAX_DIACR) - return -EINVAL; + return -EINVAL; accent_table_size = ct; memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)); return 0; } - case KDGETLED: + /* the ioctls below read/set the flags usually shown in the leds */ + /* don't use them - they will go away without warning */ + case KDGKBLED: i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char)); if (i) return i; - put_fs_byte(kbd->ledstate, (char *) arg); + put_fs_byte(kbd->ledflagstate | + (kbd->default_ledflagstate << 4), (char *) arg); return 0; - case KDSETLED: - if (arg & ~7) + case KDSKBLED: + if (arg & ~0x77) return -EINVAL; - kbd->ledstate = arg; + kbd->ledflagstate = (arg & 7); + kbd->default_ledflagstate = ((arg >> 4) & 7); set_leds(); return 0; + /* the ioctls below only set the lights, not the functions */ + /* for those, see KDGKBLED and KDSKBLED above */ + case KDGETLED: + i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char)); + if (i) + return i; + put_fs_byte(getledstate(), (char *) arg); + return 0; + + case KDSETLED: + setledstate(kbd, arg); + return 0; + case VT_SETMODE: { struct vt_mode *vtmode = (struct vt_mode *)arg; @@ -444,14 +541,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, mode = get_fs_byte(&vtmode->mode); if (mode != VT_AUTO && mode != VT_PROCESS) return -EINVAL; - vt_cons[console].vt_mode.mode = mode; - vt_cons[console].vt_mode.waitv = get_fs_byte(&vtmode->waitv); - vt_cons[console].vt_mode.relsig = get_fs_word(&vtmode->relsig); - vt_cons[console].vt_mode.acqsig = get_fs_word(&vtmode->acqsig); + vt_cons[console]->vt_mode.mode = mode; + vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv); + vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig); + vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig); /* the frsig is ignored, so we set it to 0 */ - vt_cons[console].vt_mode.frsig = 0; - vt_cons[console].vt_pid = current->pid; - vt_cons[console].vt_newvt = 0; + vt_cons[console]->vt_mode.frsig = 0; + vt_cons[console]->vt_pid = current->pid; + vt_cons[console]->vt_newvt = 0; return 0; } @@ -462,17 +559,18 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode)); if (i) return i; - put_fs_byte(vt_cons[console].vt_mode.mode, &vtmode->mode); - put_fs_byte(vt_cons[console].vt_mode.waitv, &vtmode->waitv); - put_fs_word(vt_cons[console].vt_mode.relsig, &vtmode->relsig); - put_fs_word(vt_cons[console].vt_mode.acqsig, &vtmode->acqsig); - put_fs_word(vt_cons[console].vt_mode.frsig, &vtmode->frsig); + put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode); + put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv); + put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig); + put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig); + put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig); return 0; } /* * Returns global vt state. Note that VT 0 is always open, since * it's an alias for the current VT, and people can't use it here. + * We cannot return state for more than 16 VTs, since v_state is short. */ case VT_GETSTATE: { @@ -484,7 +582,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return i; put_fs_word(fg_console + 1, &vtstat->v_active); state = 1; /* /dev/tty0 is always open */ - for (i = 0, mask = 2; i < NR_CONSOLES; ++i, mask <<= 1) + for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) if (console_driver.table[i] && console_driver.table[i]->count > 0) state |= mask; @@ -499,32 +597,36 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long)); if (i) return i; - for (i = 0; i < NR_CONSOLES; ++i) - if (!console_driver.table[i] || - console_driver.table[i]->count == 0) + for (i = 0; i < MAX_NR_CONSOLES; ++i) + if (! VT_IS_IN_USE(i)) break; - put_fs_long(i < NR_CONSOLES ? (i+1) : -1, + put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1, (unsigned long *)arg); return 0; /* * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, - * with num >= 1 (switches to vt 0, our console) are not allowed, just - * to preserve sanity. + * with num >= 1 (switches to vt 0, our console, are not allowed, just + * to preserve sanity). */ case VT_ACTIVATE: - if (arg == 0 || arg > NR_CONSOLES) + if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; - change_console(arg - 1); + arg--; + i = vc_allocate(arg); + if (i) + return i; + change_console(arg); return 0; /* * wait until the specified VT has been activated */ case VT_WAITACTIVE: - if (arg == 0 || arg > NR_CONSOLES) + if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; - while (fg_console != arg - 1) + arg--; + while (fg_console != arg) { if (vt_waitactive() < 0) return -EINTR; @@ -542,20 +644,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * 2: completed switch-to OK */ case VT_RELDISP: - if (vt_cons[console].vt_mode.mode != VT_PROCESS) + if (vt_cons[console]->vt_mode.mode != VT_PROCESS) return -EINVAL; /* * Switching-from response */ - if (vt_cons[console].vt_newvt >= 0) + if (vt_cons[console]->vt_newvt >= 0) { if (arg == 0) /* * Switch disallowed, so forget we were trying * to do it. */ - vt_cons[console].vt_newvt = -1; + vt_cons[console]->vt_newvt = -1; else { @@ -563,8 +665,11 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * The current vt has been released, so * complete the switch. */ - int newvt = vt_cons[console].vt_newvt; - vt_cons[console].vt_newvt = -1; + int newvt = vt_cons[console]->vt_newvt; + vt_cons[console]->vt_newvt = -1; + i = vc_allocate(newvt); + if (i) + return i; complete_change_console(newvt); } } @@ -583,6 +688,45 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return 0; + /* + * Disallocate memory associated to VT (but leave VT1) + */ + case VT_DISALLOCATE: + if (arg > MAX_NR_CONSOLES) + return -ENXIO; + if (arg == 0) { + /* disallocate all unused consoles, but leave 0 */ + for (i=1; iv_rows); + cc = get_fs_word(&vtsizes->v_cols); + return vc_resize(ll, cc); + } + case PIO_FONT: return con_set_font((char *)arg); /* con_set_font() defined in console.c */ diff --git a/drivers/char/vt_kern.h b/drivers/char/vt_kern.h index a36babfbf991..c4817d0d687b 100644 --- a/drivers/char/vt_kern.h +++ b/drivers/char/vt_kern.h @@ -18,8 +18,12 @@ extern struct vt_struct { int vt_pid; int vt_newvt; struct wait_queue *paste_wait; -} vt_cons[NR_CONSOLES]; +} *vt_cons[MAX_NR_CONSOLES]; void kd_mksound(unsigned int count, unsigned int ticks); +int vc_allocate(unsigned int console); +int vc_cons_allocated(unsigned int console); +int vc_resize(unsigned long lines, unsigned long cols); +void vc_disallocate(unsigned int console); #endif /* _VT_KERN_H */ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index eeaa058d2d00..6f5f98525b76 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -190,8 +190,14 @@ ifdef MODULES modules: echo $(MODULES) > ../../modules/NET_MODULES - $(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES) - (cd ../../modules;for i in $(MODULES); do ln -sf ../drivers/net/$$i .; done) + @(cd ../../modules; \ + for i in $(MODULES:.o=.c); \ + do ln -sf ../drivers/net/$$i .; \ + done ; \ + ln -sf ../drivers/net/CONFIG . ; \ + $(MAKE) -f../drivers/net/Makefile -I../drivers/net \ + CFLAGS="$(CFLAGS) -I../net/inet -I../drivers/net -DMODULE" $(MODULES); \ + rm $(MODULES:.o=.c) CONFIG) else diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 917a22afdca0..fcb8f86afa05 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -160,11 +160,13 @@ 0.351 30-apr-94 Added EISA support. Added DE422 recognition. 0.36 16-may-94 DE422 fix released. 0.37 22-jul-94 Added MODULE support + 0.38 15-aug-94 Added DBR ROM switch in depca_close(). + Multi DEPCA bug fix. ========================================================================= */ -static char *version = "depca.c:v0.37 7/22/94 davies@wanton.lkg.dec.com\n"; +static char *version = "depca.c:v0.38 8/15/94 davies@wanton.lkg.dec.com\n"; #include #include @@ -289,7 +291,7 @@ struct depca_init { }; struct depca_private { - char devname[8]; /* Not used */ + char devname[8]; /* Device Product String */ struct depca_rx_head *rx_ring; /* Pointer to start of RX descriptor ring */ struct depca_tx_head *tx_ring; /* Pointer to start of TX descriptor ring */ struct depca_init init_block;/* Initialization block */ @@ -338,7 +340,7 @@ static struct device *isa_probe(struct device *dev); static struct device *eisa_probe(struct device *dev); static struct device *alloc_device(struct device *dev, int ioaddr); -static int num_depcas = 0, num_eth = 0;; +static int num_depcas = 0, num_eth = 0, autoprobed = 0; #else int init_module(void); @@ -370,15 +372,20 @@ int depca_probe(struct device *dev) } } else if (base_addr > 0) { /* Don't probe at all. */ status = -ENXIO; - } else { /* First probe for the DEPCA test */ -#ifdef MODULE /* pattern in ROM */ +#ifdef MODULE + } else { printk("Autoprobing is not supported when loading a module based driver.\n"); status = -EIO; #else + } else if (!autoprobed) { /* First probe for the DEPCA test */ + /* pattern in ROM */ eth0=isa_probe(dev); eth0=eisa_probe(eth0); if (dev->priv) status=0; + autoprobed = 1; + } else { + status = -ENXIO; #endif /* MODULE */ } @@ -416,19 +423,18 @@ depca_probe1(struct device *dev, short ioaddr) ** shortens the search time a little for multiple DEPCAs. */ - for (j = 0, i = 0; mem_base[i] && (j == 0);) { + for (j = 0, i = 0; mem_base[i] && (j == 0);i++) { if (((mem_chkd >> i) & 0x01) == 0) { /* has the memory been checked? */ name = DepcaSignature(mem_base[i]);/* check for a DEPCA here */ mem_chkd |= (0x01 << i); /* mark location checked */ - if (*name != '\0') { /* one found? */ + if (*name != '\0') { /* one found? */ j = 1; /* set exit flag */ - } else { - i++; /* increment search index */ + --i; } } } - if (*name != '\0') { /* found a DEPCA device */ + if (*name != '\0') { /* found a DEPCA device */ mem_start = mem_base[i]; dev->base_addr = ioaddr; @@ -448,7 +454,7 @@ depca_probe1(struct device *dev, short ioaddr) read the ROM info. */ - if (strstr(name,"DE100") != NULL) { + if (strstr(name,"DE100")!= NULL) { j = 1; } else { j = 0; @@ -471,7 +477,7 @@ depca_probe1(struct device *dev, short ioaddr) /* ** Set up the maximum amount of network RAM(kB) */ - if (strstr(name,"DEPCA") == NULL) { + if (strstr(name,"DEPCA")== NULL) { netRAM=64; } else { netRAM=48; @@ -542,6 +548,7 @@ depca_probe1(struct device *dev, short ioaddr) dev->priv = (void *)((mem_start + 0x07) & ~0x07); lp = (struct depca_private *)dev->priv; memset(dev->priv, 0, sizeof(struct depca_private)); + strcpy(lp->devname,name); /* Tx & Rx descriptors (aligned to a quadword boundary) */ mem_start = ((((unsigned long)dev->priv + @@ -675,6 +682,14 @@ depca_open(struct device *dev) STOP_DEPCA; nicsr = inb(DEPCA_NICSR); + /* + ** Make sure the shadow RAM is enabled + */ + if (strstr(lp->devname,"DEPCA") == NULL) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + /* ** Re-initialize the DEPCA... */ @@ -721,9 +736,9 @@ depca_open(struct device *dev) } /* - ** Enable DEPCA board interrupts + ** Enable DEPCA board interrupts and turn off LED */ - nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN); + nicsr = ((nicsr & ~IM & ~LED)|IEN); outb(nicsr, DEPCA_NICSR); outw(CSR0,DEPCA_ADDR); @@ -1121,33 +1136,43 @@ depca_tx(struct device *dev) static int depca_close(struct device *dev) { - int ioaddr = dev->base_addr; + struct depca_private *lp = (struct depca_private *)dev->priv; + int nicsr, ioaddr = dev->base_addr; + + dev->start = 0; + dev->tbusy = 1; - dev->start = 0; - dev->tbusy = 1; + outw(CSR0, DEPCA_ADDR); - outw(CSR0, DEPCA_ADDR); + if (depca_debug > 1) { + printk("%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, inw(DEPCA_DATA)); + } - if (depca_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(DEPCA_DATA)); - } + /* + ** We stop the DEPCA here -- it occasionally polls + ** memory if we don't. + */ + outw(STOP, DEPCA_DATA); - /* - ** We stop the DEPCA here -- it occasionally polls - ** memory if we don't. - */ - outw(STOP, DEPCA_DATA); + /* + ** Give back the ROM in case the user wants to go to DOS + */ + if (strstr(lp->devname,"DEPCA") == NULL) { + nicsr = inb(DEPCA_NICSR); + nicsr &= ~SHE; + outb(nicsr, DEPCA_NICSR); + } - free_irq(dev->irq); + free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; + irq2dev_map[dev->irq] = 0; #ifdef MODULE - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #endif - return 0; + return 0; } static void LoadCSRs(struct device *dev) @@ -1373,12 +1398,12 @@ static struct device *alloc_device(struct device *dev, int ioaddr) */ if ((dev->next != NULL) && (num_eth > 0) && (num_eth < 9999)) { - dev = dev->next; /* point to the new device */ + dev = dev->next; /* point to the new device */ dev->name = (char *)(dev + 1); sprintf(dev->name,"eth%d", num_eth);/* New device name */ - dev->base_addr = ioaddr; /* assign the io address */ - dev->next = NULL; /* mark the end of list */ - dev->init = &depca_probe; /* initialisation routine */ + dev->base_addr = ioaddr; /* assign the io address */ + dev->next = NULL; /* mark the end of list */ + dev->init = &depca_probe; /* initialisation routine */ num_depcas++; } @@ -1401,10 +1426,10 @@ static char *DepcaSignature(unsigned long mem_addr) for (i=0;i<16;i++) { /* copy the first 16 bytes of ROM to */ tmpstr[i] = *(unsigned char *)(mem_addr+0xc000+i); /* a temporary string */ } - tmpstr[i] = '\0'; + tmpstr[i]='\0'; strcpy(thisName,""); - for (i = 0 ; *signatures[i] != '\0' && *thisName == '\0' ; i++) { + for (i=0;*signatures[i]!='\0' && *thisName=='\0';i++) { for (j=0,k=0;j<16 && kchip) { case 810: case 815: + case 825: hostdata->dstat_sir_intr = NCR53c8x0_dstat_sir_intr; hostdata->init_save_regs = NULL; hostdata->dsa_fixup = NCR53c8xx_dsa_fixup; diff --git a/drivers/scsi/buslogic.h b/drivers/scsi/buslogic.h index 6ab93d1d4683..585de430779a 100644 --- a/drivers/scsi/buslogic.h +++ b/drivers/scsi/buslogic.h @@ -19,7 +19,14 @@ const char *buslogic_info(void); int buslogic_reset(Scsi_Cmnd *); int buslogic_biosparam(Disk *, int, int *); -#define BUSLOGIC_CMDLUN 4 /* ??? */ +#define BUSLOGIC_CMDLUN 1 /* Do not set this too high. It sucks + up lots of memory on machines with > 16Mb + because of the huge number of bounce + buffers that need to be allocated. + For boards that use non-ISA bus, we can + bump this in the board detect routine. + 10/8/94 ERY */ + #define BUSLOGIC { NULL, \ "BusLogic", \ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c7acc1404cc6..9324c865e374 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -373,9 +373,9 @@ static void scan_scsis (struct Scsi_Host * shpnt) #ifdef DEBUG printk("scsi: unknown type %d\n", type); print_inquiry(scsi_result); -#endif #endif type = -1; +#endif } SDpnt->soft_reset = diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 9c96ccd19448..5a62c959a424 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -515,7 +515,7 @@ extern int scsi_reset (Scsi_Cmnd *); extern int max_scsi_hosts; #if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR) -static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) +static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) { struct request * req; struct buffer_head * bh; @@ -547,7 +547,7 @@ static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) } while(sectors && bh); if (req->bh){ req->buffer = bh->b_data; - return; + return SCpnt; }; DEVICE_OFF(req->dev); if (req->sem != NULL) { @@ -555,7 +555,7 @@ static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) } req->dev = -1; wake_up(&SCpnt->device->device_wait); - return; + return NULL; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 569b9c613c5e..5c26bc39195e 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -226,7 +226,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt) SCpnt->request.sector, this_count); } } - end_scsi_request(SCpnt, 1, this_count); + SCpnt = end_scsi_request(SCpnt, 1, this_count); requeue_sd_request(SCpnt); return; } @@ -284,7 +284,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt) /* further access. */ rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->changed = 1; - end_scsi_request(SCpnt, 0, this_count); + SCpnt = end_scsi_request(SCpnt, 0, this_count); requeue_sd_request(SCpnt); return; } @@ -316,7 +316,7 @@ of the disk. if (driver_byte(result) & DRIVER_SENSE) print_sense("sd", SCpnt); - end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); requeue_sd_request(SCpnt); return; } @@ -406,7 +406,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt) repeat: - if(SCpnt->request.dev <= 0) { + if(!SCpnt || SCpnt->request.dev <= 0) { do_sd_request(); return; } @@ -423,7 +423,7 @@ repeat: !rscsi_disks[DEVICE_NR(dev)].device || block + SCpnt->request.nr_sectors > sd[dev].nr_sects) { - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } @@ -436,7 +436,7 @@ repeat: * quietly refuse to do anything to a changed disc until the changed bit has been reset */ /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } @@ -449,7 +449,7 @@ repeat: case WRITE : if (!rscsi_disks[dev].device->writeable) { - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } cmd[0] = WRITE_6; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index c6851fd58585..14ccb0f19f90 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -195,7 +195,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt) SCpnt->request.sector, this_count); } - end_scsi_request(SCpnt, 1, this_count); /* All done */ + SCpnt = end_scsi_request(SCpnt, 1, this_count); /* All done */ requeue_sr_request(SCpnt); return; } /* Normal completion */ @@ -225,7 +225,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt) /* further access. */ scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->changed = 1; - end_scsi_request(SCpnt, 0, this_count); + SCpnt = end_scsi_request(SCpnt, 0, this_count); requeue_sr_request(SCpnt); return; } @@ -240,7 +240,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt) return; } else { printk("CD-ROM error: Drive reports %d.\n", SCpnt->sense_buffer[2]); - end_scsi_request(SCpnt, 0, this_count); + SCpnt = end_scsi_request(SCpnt, 0, this_count); requeue_sr_request(SCpnt); /* Do next request */ return; } @@ -249,7 +249,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt) if (SCpnt->sense_buffer[2] == NOT_READY) { printk("CDROM not ready. Make sure you have a disc in the drive.\n"); - end_scsi_request(SCpnt, 0, this_count); + SCpnt = end_scsi_request(SCpnt, 0, this_count); requeue_sr_request(SCpnt); /* Do next request */ return; }; @@ -266,7 +266,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt) if (status_byte(result) == CHECK_CONDITION) print_sense("sr", SCpnt); - end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); requeue_sr_request(SCpnt); } } @@ -369,7 +369,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt) tries = 2; repeat: - if(SCpnt->request.dev <= 0) { + if(!SCpnt || SCpnt->request.dev <= 0) { do_sr_request(); return; } @@ -382,7 +382,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt) if (dev >= sr_template.nr_dev) { /* printk("CD-ROM request error: invalid device.\n"); */ - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); tries = 2; goto repeat; } @@ -390,7 +390,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt) if (!scsi_CDs[dev].use) { /* printk("CD-ROM request error: device marked not in use.\n"); */ - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); tries = 2; goto repeat; } @@ -401,7 +401,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt) * quietly refuse to do anything to a changed disc until the changed bit has been reset */ /* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */ - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); tries = 2; goto repeat; } @@ -409,7 +409,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt) switch (SCpnt->request.cmd) { case WRITE: - end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); + SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; break; case READ : diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 31eb30e6c264..d6d6f898f53a 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -309,7 +309,7 @@ static inline int find_and_clear_bit_16(unsigned short *field) static inline unsigned char xchgb(unsigned char reg, volatile unsigned char *mem) { - asm ("xchgb %0, (%2)" : "=q" (reg) : "0" (reg), "q" (mem) : "m"); + __asm__ ("xchgb %0,%1" : "=q" (reg), "=m" (*mem) : "0" (reg)); return reg; } diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index d5c73f4ccfe9..f5603357da3a 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -71,8 +71,9 @@ static char irq2dev[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -static int ad_format_mask[2 /*devc->mode*/ ] = +static int ad_format_mask[3 /*devc->mode*/ ] = { + 0, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM }; diff --git a/drivers/sound/sb16_midi.c b/drivers/sound/sb16_midi.c index 7a3fdb1a3be6..e40fe876b837 100644 --- a/drivers/sound/sb16_midi.c +++ b/drivers/sound/sb16_midi.c @@ -282,7 +282,6 @@ int probe_sb16midi (struct address_info *hw_config) { int ok = 0; - int i; extern int sbc_major; if (sbc_major < 4) diff --git a/fs/Makefile b/fs/Makefile index 8e423bfb11fb..93c23f26a851 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -43,6 +43,12 @@ ifdef CONFIG_HPFS_FS FS_SUBDIRS := $(FS_SUBDIRS) hpfs endif +ifdef CONFIG_BINFMT_ELF +BINFMTS := $(BINFMTS) binfmt_elf.o +else +MODULES := $(MODULES) binfmt_elf.o +endif + .c.s: $(CC) $(CFLAGS) -S $< .c.o: @@ -54,7 +60,7 @@ OBJS= open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \ block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \ select.o fifo.o locks.o filesystems.o dcache.o $(BINFMTS) -all: fs.o filesystems.a +all: fs.o filesystems.a modules fs.o: $(OBJS) $(LD) -r -o fs.o $(OBJS) @@ -65,6 +71,18 @@ filesystems.a: dummy test ! -d $$i || \ { $(MAKE) -C $$i; $(AR) rcs filesystems.a $$i/$$i.o; }; done +ifdef MODULES + +modules: + $(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES) + (cd ../modules;for i in $(MODULES); do ln -sf ../fs/$$i .; done) + +else + +modules: + +endif + depend dep: $(CPP) -M *.c > .depend set -e; for i in $(SUBDIRS); do \ diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c new file mode 100644 index 000000000000..463db21ce53a --- /dev/null +++ b/fs/binfmt_elf.c @@ -0,0 +1,791 @@ +/* + * linux/fs/binfmt_elf.c + * + * These are the functions used to load ELF format executables as used + * on SVr4 machines. Information on the format may be found in the book + * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support + * Tools". + * + * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifndef CONFIG_BINFMT_ELF +#include +#include "../tools/version.h" +#endif + +#include +typedef int (*sysfun_p)(); +extern sysfun_p sys_call_table[]; +#define SYS(name) (sys_call_table[__NR_##name]) + +#define DLINFO_ITEMS 8 + +#include + +static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); +static int load_elf_library(int fd); + +struct linux_binfmt elf_format = { +#ifdef CONFIG_BINFMT_ELF + NULL, NULL, load_elf_binary, load_elf_library, NULL +#else + NULL, &mod_use_count_, load_elf_binary, load_elf_library, NULL +#endif +}; + +/* We need to explicitly zero any fractional pages + after the data section (i.e. bss). This would + contain the junk from the file that should not + be in memory */ + + +static void padzero(int elf_bss){ + unsigned int fpnt, nbyte; + + if(elf_bss & 0xfff) { + + nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff; + if(nbyte){ + verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte); + + fpnt = elf_bss; + while(fpnt & 0xfff) put_fs_byte(0, fpnt++); + }; + }; +} + +unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs) +{ + unsigned long *argv,*envp, *dlinfo; + unsigned long * sp; + struct vm_area_struct *mpnt; + + mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL); + if (mpnt) { + mpnt->vm_task = current; + mpnt->vm_start = PAGE_MASK & (unsigned long) p; + mpnt->vm_end = TASK_SIZE; + mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY; +#ifdef VM_STACK_FLAGS + mpnt->vm_flags = VM_STACK_FLAGS; + mpnt->vm_pte = 0; +#else +# ifdef VM_GROWSDOWN + mpnt->vm_flags = VM_GROWSDOWN; +# endif +#endif + mpnt->vm_share = NULL; + mpnt->vm_inode = NULL; + mpnt->vm_offset = 0; + mpnt->vm_ops = NULL; + insert_vm_struct(current, mpnt); +#ifndef VM_GROWSDOWN + current->mm->stk_vma = mpnt; +#endif + + } + sp = (unsigned long *) (0xfffffffc & (unsigned long) p); + if(exec) sp -= DLINFO_ITEMS*2; + dlinfo = sp; + sp -= envc+1; + envp = sp; + sp -= argc+1; + argv = sp; + if (!ibcs) { + put_fs_long((unsigned long)envp,--sp); + put_fs_long((unsigned long)argv,--sp); + } + + /* The constant numbers (0-9) that we are writing here are + described in the header file sys/auxv.h on at least + some versions of SVr4 */ + if(exec) { /* Put this here for an ELF program interpreter */ + struct elf_phdr * eppnt; + eppnt = (struct elf_phdr *) exec->e_phoff; + put_fs_long(3,dlinfo++); put_fs_long(load_addr + exec->e_phoff,dlinfo++); + put_fs_long(4,dlinfo++); put_fs_long(sizeof(struct elf_phdr),dlinfo++); + put_fs_long(5,dlinfo++); put_fs_long(exec->e_phnum,dlinfo++); + put_fs_long(9,dlinfo++); put_fs_long((unsigned long) exec->e_entry,dlinfo++); + put_fs_long(7,dlinfo++); put_fs_long(SHM_RANGE_START,dlinfo++); + put_fs_long(8,dlinfo++); put_fs_long(0,dlinfo++); + put_fs_long(6,dlinfo++); put_fs_long(PAGE_SIZE,dlinfo++); + put_fs_long(0,dlinfo++); put_fs_long(0,dlinfo++); + }; + + put_fs_long((unsigned long)argc,--sp); + current->mm->arg_start = (unsigned long) p; + while (argc-->0) { + put_fs_long((unsigned long) p,argv++); + while (get_fs_byte(p++)) /* nothing */ ; + } + put_fs_long(0,argv); + current->mm->arg_end = current->mm->env_start = (unsigned long) p; + while (envc-->0) { + put_fs_long((unsigned long) p,envp++); + while (get_fs_byte(p++)) /* nothing */ ; + } + put_fs_long(0,envp); + current->mm->env_end = (unsigned long) p; + return sp; +} + + +/* This is much more generalized than the library routine read function, + so we keep this separate. Techincally the library read function + is only provided so that we can read a.out libraries that have + an ELF header */ + +static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex, + struct inode * interpreter_inode) +{ + struct file * file; + struct elf_phdr *elf_phdata = NULL; + struct elf_phdr *eppnt; + unsigned int len; + unsigned int load_addr; + int elf_exec_fileno; + int elf_bss; + int old_fs, retval; + unsigned int last_bss; + int error; + int i, k; + + elf_bss = 0; + last_bss = 0; + error = load_addr = 0; + + /* First of all, some simple consistency checks */ + if((interp_elf_ex->e_type != ET_EXEC && + interp_elf_ex->e_type != ET_DYN) || + (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) || + (!interpreter_inode->i_op || + !interpreter_inode->i_op->default_file_ops->mmap)){ + return 0xffffffff; + }; + + /* Now read in all of the header information */ + + if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) + return 0xffffffff; + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); + if(!elf_phdata) return 0xffffffff; + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata, + sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); + set_fs(old_fs); + + elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY); + if (elf_exec_fileno < 0) return 0xffffffff; + file = current->files->fd[elf_exec_fileno]; + + eppnt = elf_phdata; + for(i=0; ie_phnum; i++, eppnt++) + if(eppnt->p_type == PT_LOAD) { + error = do_mmap(file, + eppnt->p_vaddr & 0xfffff000, + eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_DENYWRITE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0), + eppnt->p_offset & 0xfffff000); + + if(!load_addr && interp_elf_ex->e_type == ET_DYN) + load_addr = error; + k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + if(error < 0 && error > -1024) break; /* Real error */ + k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; + if(k > last_bss) last_bss = k; + } + + /* Now use mmap to map the library into memory. */ + + + SYS(close)(elf_exec_fileno); + if(error < 0 && error > -1024) { + kfree(elf_phdata); + return 0xffffffff; + } + + padzero(elf_bss); + len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ + + /* Map the last of the bss segment */ + if (last_bss > len) + do_mmap(NULL, len, last_bss-len, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + kfree(elf_phdata); + + return ((unsigned int) interp_elf_ex->e_entry) + load_addr; +} + +static unsigned int load_aout_interp(struct exec * interp_ex, + struct inode * interpreter_inode) +{ + int retval; + unsigned int elf_entry; + + current->mm->brk = interp_ex->a_bss + + (current->mm->end_data = interp_ex->a_data + + (current->mm->end_code = interp_ex->a_text)); + elf_entry = interp_ex->a_entry; + + + if (N_MAGIC(*interp_ex) == OMAGIC) { + do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + retval = read_exec(interpreter_inode, 32, (char *) 0, + interp_ex->a_text+interp_ex->a_data); + } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) { + do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + retval = read_exec(interpreter_inode, + N_TXTOFF(*interp_ex) , + (char *) N_TXTADDR(*interp_ex), + interp_ex->a_text+interp_ex->a_data); + } else + retval = -1; + + if(retval >= 0) + do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & + 0xfffff000, interp_ex->a_bss, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + if(retval < 0) return 0xffffffff; + return elf_entry; +} + +/* + * These are the functions used to load ELF style executables and shared + * libraries. There is no binary dependent code anywhere else. + */ + +#define INTERPRETER_NONE 0 +#define INTERPRETER_AOUT 1 +#define INTERPRETER_ELF 2 + + +static int +load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) +{ + struct elfhdr elf_ex; + struct elfhdr interp_elf_ex; + struct file * file; + struct exec interp_ex; + struct inode *interpreter_inode; + unsigned int load_addr; + unsigned int interpreter_type = INTERPRETER_NONE; + unsigned char ibcs2_interpreter; + int i; + int old_fs; + int error; + struct elf_phdr * elf_ppnt, *elf_phdata; + int elf_exec_fileno; + unsigned int elf_bss, k, elf_brk; + int retval; + char * elf_interpreter; + unsigned int elf_entry; + int status; + unsigned int start_code, end_code, end_data; + unsigned int elf_stack; + char passed_fileno[6]; + +#ifndef CONFIG_BINFMT_ELF + MOD_INC_USE_COUNT; +#endif + + ibcs2_interpreter = 0; + status = 0; + load_addr = 0; + elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ + + if (elf_ex.e_ident[0] != 0x7f || + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) { +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + } + + + /* First of all, some simple consistency checks */ + if(elf_ex.e_type != ET_EXEC || + (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || + (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || + !bprm->inode->i_op->default_file_ops->mmap)){ +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + }; + + /* Now read in all of the header information */ + + elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * + elf_ex.e_phnum, GFP_KERNEL); + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata, + elf_ex.e_phentsize * elf_ex.e_phnum); + set_fs(old_fs); + if (retval < 0) { + kfree (elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return retval; + } + + elf_ppnt = elf_phdata; + + elf_bss = 0; + elf_brk = 0; + + elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); + + if (elf_exec_fileno < 0) { + kfree (elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return elf_exec_fileno; + } + + file = current->files->fd[elf_exec_fileno]; + + elf_stack = 0xffffffff; + elf_interpreter = NULL; + start_code = 0; + end_code = 0; + end_data = 0; + + old_fs = get_fs(); + set_fs(get_ds()); + + for(i=0;i < elf_ex.e_phnum; i++){ + if(elf_ppnt->p_type == PT_INTERP) { + /* This is the program interpreter used for shared libraries - + for now assume that this is an a.out format binary */ + + elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, + GFP_KERNEL); + + retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter, + elf_ppnt->p_filesz); + /* If the program interpreter is one of these two, + then assume an iBCS2 image. Otherwise assume + a native linux image. */ + if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || + strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) + ibcs2_interpreter = 1; +#if 0 + printk("Using ELF interpreter %s\n", elf_interpreter); +#endif + if(retval >= 0) + retval = namei(elf_interpreter, &interpreter_inode); + if(retval >= 0) + retval = read_exec(interpreter_inode,0,bprm->buf,128); + + if(retval >= 0){ + interp_ex = *((struct exec *) bprm->buf); /* exec-header */ + interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ + + }; + if(retval < 0) { + kfree (elf_phdata); + kfree(elf_interpreter); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return retval; + }; + }; + elf_ppnt++; + }; + + set_fs(old_fs); + + /* Some simple consistency checks for the interpreter */ + if(elf_interpreter){ + interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; + if(retval < 0) { + kfree(elf_interpreter); + kfree(elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ELIBACC; + }; + /* Now figure out which format our binary is */ + if((N_MAGIC(interp_ex) != OMAGIC) && + (N_MAGIC(interp_ex) != ZMAGIC) && + (N_MAGIC(interp_ex) != QMAGIC)) + interpreter_type = INTERPRETER_ELF; + + if (interp_elf_ex.e_ident[0] != 0x7f || + strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) + interpreter_type &= ~INTERPRETER_ELF; + + if(!interpreter_type) + { + kfree(elf_interpreter); + kfree(elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ELIBBAD; + }; + } + + /* OK, we are done with that, now set up the arg stuff, + and then start this sucker up */ + + if (!bprm->sh_bang) { + char * passed_p; + + if(interpreter_type == INTERPRETER_AOUT) { + sprintf(passed_fileno, "%d", elf_exec_fileno); + passed_p = passed_fileno; + + if(elf_interpreter) { + bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); + bprm->argc++; + }; + }; + if (!bprm->p) { + if(elf_interpreter) { + kfree(elf_interpreter); + } + kfree (elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -E2BIG; + } + } + + /* OK, This is the point of no return */ + flush_old_exec(bprm); + + current->mm->end_data = 0; + current->mm->end_code = 0; + current->mm->start_mmap = ELF_START_MMAP; + current->mm->mmap = NULL; + elf_entry = (unsigned int) elf_ex.e_entry; + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ + current->mm->rss = 0; + bprm->p += change_ldt(0, bprm->page); + current->mm->start_stack = bprm->p; + + /* Now we do a little grungy work by mmaping the ELF image into + the correct location in memory. At this point, we assume that + the image should be loaded at fixed address, not at a variable + address. */ + + old_fs = get_fs(); + set_fs(get_ds()); + + elf_ppnt = elf_phdata; + for(i=0;i < elf_ex.e_phnum; i++){ + + if(elf_ppnt->p_type == PT_INTERP) { + /* Set these up so that we are able to load the interpreter */ + /* Now load the interpreter into user address space */ + set_fs(old_fs); + + if(interpreter_type & 1) elf_entry = + load_aout_interp(&interp_ex, interpreter_inode); + + if(interpreter_type & 2) elf_entry = + load_elf_interp(&interp_elf_ex, interpreter_inode); + + old_fs = get_fs(); + set_fs(get_ds()); + + iput(interpreter_inode); + kfree(elf_interpreter); + + if(elf_entry == 0xffffffff) { + printk("Unable to load interpreter\n"); + kfree(elf_phdata); + send_sig(SIGSEGV, current, 0); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return 0; + }; + }; + + + if(elf_ppnt->p_type == PT_LOAD) { + error = do_mmap(file, + elf_ppnt->p_vaddr & 0xfffff000, + elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, + elf_ppnt->p_offset & 0xfffff000); + +#ifdef LOW_ELF_STACK + if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) + elf_stack = elf_ppnt->p_vaddr & 0xfffff000; +#endif + + if(!load_addr) + load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; + k = elf_ppnt->p_vaddr; + if(k > start_code) start_code = k; + k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k) + end_code = k; + if(end_data < k) end_data = k; + k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; + if(k > elf_brk) elf_brk = k; + }; + elf_ppnt++; + }; + set_fs(old_fs); + + kfree(elf_phdata); + + if(interpreter_type != INTERPRETER_AOUT) SYS(close)(elf_exec_fileno); + current->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); + + if (current->exec_domain && current->exec_domain->use_count) + (*current->exec_domain->use_count)--; + if (current->binfmt && current->binfmt->use_count) + (*current->binfmt->use_count)--; + current->exec_domain = lookup_exec_domain(current->personality); + current->binfmt = &elf_format; + if (current->exec_domain && current->exec_domain->use_count) + (*current->exec_domain->use_count)++; + if (current->binfmt && current->binfmt->use_count) + (*current->binfmt->use_count)++; + +#ifndef VM_STACK_FLAGS + current->executable = bprm->inode; + bprm->inode->i_count++; +#endif +#ifdef LOW_ELF_STACK + current->start_stack = p = elf_stack - 4; +#endif + bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; + bprm->p = (unsigned long) + create_elf_tables((char *)bprm->p, + bprm->argc, + bprm->envc, + (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), + load_addr, + (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); + if(interpreter_type == INTERPRETER_AOUT) + current->mm->arg_start += strlen(passed_fileno) + 1; + current->mm->start_brk = current->mm->brk = elf_brk; + current->mm->end_code = end_code; + current->mm->start_code = start_code; + current->mm->end_data = end_data; + current->mm->start_stack = bprm->p; + current->suid = current->euid = bprm->e_uid; + current->sgid = current->egid = bprm->e_gid; + + /* Calling sys_brk effectively mmaps the pages that we need for the bss and break + sections */ + current->mm->brk = (elf_bss + 0xfff) & 0xfffff000; + SYS(brk)((elf_brk + 0xfff) & 0xfffff000); + + padzero(elf_bss); + +#if 0 + printk("(start_brk) %x\n" , current->mm->start_brk); + printk("(end_code) %x\n" , current->mm->end_code); + printk("(start_code) %x\n" , current->mm->start_code); + printk("(end_data) %x\n" , current->mm->end_data); + printk("(start_stack) %x\n" , current->mm->start_stack); + printk("(brk) %x\n" , current->mm->brk); +#endif + + /* Why this, you ask??? Well SVr4 maps page 0 as read-only, + and some applications "depend" upon this behavior. + Since we do not have the power to recompile these, we + emulate the SVr4 behavior. Sigh. */ + error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); + + regs->eip = elf_entry; /* eip, magic happens :-) */ + regs->esp = bprm->p; /* stack pointer */ + if (current->flags & PF_PTRACED) + send_sig(SIGTRAP, current, 0); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +/* This is really simpleminded and specialized - we are loading an + a.out library that is given an ELF header. */ + +static int +load_elf_library(int fd){ + struct file * file; + struct elfhdr elf_ex; + struct elf_phdr *elf_phdata = NULL; + struct inode * inode; + unsigned int len; + int elf_bss; + int old_fs, retval; + unsigned int bss; + int error; + int i,j, k; + +#ifndef CONFIG_BINFMT_ELF + MOD_INC_USE_COUNT; +#endif + + len = 0; + file = current->files->fd[fd]; + inode = file->f_inode; + elf_bss = 0; + + set_fs(KERNEL_DS); + if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) { + SYS(close)(fd); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -EACCES; + } + set_fs(USER_DS); + + if (elf_ex.e_ident[0] != 0x7f || + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) { +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + } + + /* First of all, some simple consistency checks */ + if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || + (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || + (!inode->i_op || !inode->i_op->default_file_ops->mmap)){ +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + }; + + /* Now read in all of the header information */ + + if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) { +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + } + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata, + sizeof(struct elf_phdr) * elf_ex.e_phnum); + set_fs(old_fs); + + j = 0; + for(i=0; ip_type == PT_LOAD) j++; + + if(j != 1) { + kfree(elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return -ENOEXEC; + }; + + while(elf_phdata->p_type != PT_LOAD) elf_phdata++; + + /* Now use mmap to map the library into memory. */ + error = do_mmap(file, + elf_phdata->p_vaddr & 0xfffff000, + elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, + elf_phdata->p_offset & 0xfffff000); + + k = elf_phdata->p_vaddr + elf_phdata->p_filesz; + if(k > elf_bss) elf_bss = k; + + SYS(close)(fd); + if (error != elf_phdata->p_vaddr & 0xfffff000) { + kfree(elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return error; + } + + padzero(elf_bss); + + len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; + bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; + if (bss > len) + do_mmap(NULL, len, bss-len, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + kfree(elf_phdata); +#ifndef CONFIG_BINFMT_ELF + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +#ifndef CONFIG_BINFMT_ELF +char kernel_version[] = UTS_RELEASE; + +int init_module(void) { + /* Install the COFF, ELF and XOUT loaders. + * N.B. We *rely* on the table being the right size with the + * right number of free slots... + */ + register_binfmt(&elf_format); + return 0; +} + +void cleanup_module( void) { + + if (MOD_IN_USE) + printk(KERN_INFO "iBCS: module is in use, remove delayed\n"); + + /* Remove the COFF and ELF loaders. */ + unregister_binfmt(&elf_format); +} +#endif diff --git a/fs/exec.c b/fs/exec.c index 838072625d8b..e0d416cbc80e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -60,9 +60,16 @@ static int aout_core_dump(long signr, struct pt_regs * regs); * Here are the actual binaries that will be accepted: * add more with "register_binfmt()".. */ +extern struct linux_binfmt elf_format; + static struct linux_binfmt aout_format = { - NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump +#ifndef CONFIG_BINFMT_ELF + NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump +#else + &elf_format, NULL, load_aout_binary, load_aout_library, aout_core_dump +#endif }; + static struct linux_binfmt *formats = &aout_format; int register_binfmt(struct linux_binfmt * fmt) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 2d823bf0c5f7..e71d2948342a 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -7,7 +7,9 @@ * - Do not copy data too often around in the kernel. * - In nfs_file_read the return value of kmalloc wasn't checked. * - Put in a better version of read look-ahead buffering. Original idea - * and implementation by Wai S Kok elekokw@ee.nus.sg. + * and implementation by Wai S Kok elekokws@ee.nus.sg. + * + * Expire cache on write to a file by Wai S Kok (Oct 1994). * * nfs regular file handling functions */ @@ -201,6 +203,14 @@ static int nfs_file_write(struct inode *inode, struct file *file, char *buf, } if (count <= 0) return 0; + + cli(); + /* If hit, cache is dirty and must be expired. */ + for (i = 0; i < READ_CACHE_SIZE; i++) + if(cache[i].inode_num == inode->i_ino) + cache[i].time -= EXPIRE_CACHE; + sti(); + pos = file->f_pos; if (file->f_flags & O_APPEND) pos = inode->i_size; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index e06c63d24097..5a7a7d0498eb 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -77,7 +77,7 @@ static int nfs_stat_to_errno(int stat); static inline int *nfs_rpc_alloc(int size) { -#if 1 +#if 0 /* Allow for the NFS crap as well as buffer */ return (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL); #else @@ -88,7 +88,7 @@ static inline int *nfs_rpc_alloc(int size) so that other processes are run inbetween (and hopefully give some memory back). Florian */ - int i; + int *i; while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL))) { /* printk("NFS: call schedule\n"); */ diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index a0d595d61b27..30e3d1b41ffc 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -71,7 +71,7 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode, } error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem, &res, &len, NFS_MAXPATHLEN); -#if 1 +#if 0 if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) { printk("NFS: no memory in nfs_follow_link\n"); error = -EIO; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 1e7536537f3d..0d0848b33d98 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -175,7 +175,11 @@ void proc_read_inode(struct inode * inode) return; inode->i_op = &proc_link_inode_operations; inode->i_size = 64; - inode->i_mode = S_IFLNK | S_IRWXU; + inode->i_mode = S_IFLNK; + if (p->files->fd[ino]->f_mode & 1) + inode->i_mode |= S_IRUSR | S_IXUSR; + if (p->files->fd[ino]->f_mode & 2) + inode->i_mode |= S_IWUSR | S_IXUSR; return; } return; diff --git a/fs/proc/link.c b/fs/proc/link.c index d173cb075f57..c95df7807344 100644 --- a/fs/proc/link.c +++ b/fs/proc/link.c @@ -15,13 +15,30 @@ #include static int proc_readlink(struct inode *, char *, int); -static int proc_follow_link(struct inode *, struct inode *, int, int, struct inode **); +static int proc_follow_link(struct inode *, struct inode *, int, int, + struct inode **); +static int proc_fd_dupf(struct inode * inode, struct file * f); + +#define PLAN9_SEMANTICS /* * links can't do much... */ +static struct file_operations proc_fd_link_operations = { + NULL, /* lseek - default */ + NULL, /* read - bad */ + NULL, /* write - bad */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + NULL, /* mmap */ + proc_fd_dupf, /* very special open code */ + NULL, /* no special release code */ + NULL /* can't fsync */ +}; + struct inode_operations proc_link_inode_operations = { - NULL, /* no file-operations */ + &proc_fd_link_operations,/* file-operations */ NULL, /* create */ NULL, /* lookup */ NULL, /* link */ @@ -38,11 +55,53 @@ struct inode_operations proc_link_inode_operations = { NULL /* permission */ }; +/* + * This open routine is somewhat of a hack.... what we are doing is + * looking up the file structure of the newly opened proc fd file, and + * replacing it with the actual file structure of the process's file + * descriptor. This allows plan 9 semantics, so that the returned + * file descriptor is an dup of the target file descriptor. + */ +static int proc_fd_dupf(struct inode * inode, struct file * f) +{ + unsigned int pid, ino; + int i, fd; + struct task_struct * p; + struct file *new_f; + + for(fd=0 ; fdfiles->fd[fd] == f) + break; + if (fd>=NR_OPEN) + return -ENOENT; /* should never happen */ + + ino = inode->i_ino; + pid = ino >> 16; + ino &= 0x0000ffff; + + for (i = 0 ; i < NR_TASKS ; i++) + if ((p = task[i]) && p->pid == pid) + break; + + if ((i >= NR_TASKS) || + ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff])) + return -ENOENT; + + if (new_f->f_mode && !f->f_mode && 3) + return -EPERM; + + new_f->f_count++; + current->files->fd[fd] = new_f; + f->f_count--; + return 0; +} + static int proc_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { unsigned int pid, ino; struct task_struct * p; + struct inode * new_inode; int i; *res_inode = NULL; @@ -57,25 +116,26 @@ static int proc_follow_link(struct inode * dir, struct inode * inode, ino = inode->i_ino; pid = ino >> 16; ino &= 0x0000ffff; - iput(inode); for (i = 0 ; i < NR_TASKS ; i++) if ((p = task[i]) && p->pid == pid) break; - if (i >= NR_TASKS) + if (i >= NR_TASKS) { + iput(inode); return -ENOENT; - inode = NULL; + } + new_inode = NULL; switch (ino) { case PROC_PID_CWD: - inode = p->fs->pwd; + new_inode = p->fs->pwd; break; case PROC_PID_ROOT: - inode = p->fs->root; + new_inode = p->fs->root; break; case PROC_PID_EXE: { struct vm_area_struct * vma = p->mm->mmap; while (vma) { if (vma->vm_flags & VM_EXECUTABLE) { - inode = vma->vm_inode; + new_inode = vma->vm_inode; break; } vma = vma->vm_next; @@ -84,17 +144,25 @@ static int proc_follow_link(struct inode * dir, struct inode * inode, } default: switch (ino >> 8) { - case PROC_PID_FD_DIR: - ino &= 0xff; - if (ino < NR_OPEN && p->files->fd[ino]) - inode = p->files->fd[ino]->f_inode; - break; + case PROC_PID_FD_DIR: + ino &= 0xff; + if (ino < NR_OPEN && p->files->fd[ino]) { +#ifdef PLAN9_SEMANTICS + if (dir) { + *res_inode = inode; + return 0; + } +#endif + new_inode = p->files->fd[ino]->f_inode; + } + break; } } - if (!inode) + iput(inode); + if (!new_inode) return -ENOENT; - *res_inode = inode; - inode->i_count++; + *res_inode = new_inode; + new_inode->i_count++; return 0; } diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 661aec4876e1..81a5ff09cabb 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -15,67 +15,69 @@ errno = -__res; \ return -1; \ } -#define _syscall1(type,name,atype,a) \ -type name(atype a) \ +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(a))); \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ if (__res >= 0) \ return (type) __res; \ errno = -__res; \ return -1; \ } -#define _syscall2(type,name,atype,a,btype,b) \ -type name(atype a,btype b) \ +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ if (__res >= 0) \ return (type) __res; \ errno = -__res; \ return -1; \ } -#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ -type name(atype a,btype b,ctype c) \ +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ if (__res>=0) \ return (type) __res; \ errno=-__res; \ return -1; \ } -#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ -type name (atype a, btype b, ctype c, dtype d) \ +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \ - "d" ((long)(c)),"S" ((long)(d))); \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ if (__res>=0) \ return (type) __res; \ errno=-__res; \ return -1; \ -} +} -#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \ -type name (atype a,btype b,ctype c,dtype d,etype e) \ +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \ - "d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ if (__res>=0) \ return (type) __res; \ errno=-__res; \ diff --git a/include/linux/elf.h b/include/linux/elf.h index b1a7164ba476..cc47c39bd854 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -75,13 +75,13 @@ -struct dynamic{ +typedef struct dynamic{ int d_tag; union{ int d_val; char * d_ptr; } d_un; -}; +} Elf32_Dyn; /* The following are used with relocations */ #define ELF32_R_SYM(x) ((x) >> 8) @@ -100,27 +100,27 @@ struct dynamic{ #define R_386_GOTPC 10 #define R_386_NUM 11 -struct Elf32_Rel{ +typedef struct elf32_rel { unsigned int * offset; int info; -}; +} Elf32_Rel; -struct Elf32_Rela{ +typedef struct elf32_rela{ unsigned int * offset; int info; int addend; -}; +} Elf32_Rela; -struct Elf32_Sym{ +typedef struct elf32_sym{ int st_name; unsigned int st_value; int st_size; unsigned char st_info; unsigned char st_other; short int st_shndx; -}; +} Elf32_Sym; -struct elfhdr{ +typedef struct elfhdr{ char e_ident[16]; short int e_type; short int e_machine; @@ -135,9 +135,9 @@ struct elfhdr{ short int e_shentsize; short int e_shnum; short int e_shstrndx; -}; +} Elf32_Ehdr; -struct elf_phdr{ +typedef struct elf_phdr{ int p_type; int p_offset; int p_vaddr; @@ -146,7 +146,7 @@ struct elf_phdr{ int p_memsz; int p_flags; int p_align; -}; +} Elf32_Phdr; #define ELF_START_MMAP 0x80000000 diff --git a/include/linux/kd.h b/include/linux/kd.h index 2de678a5dc48..4743061b1632 100644 --- a/include/linux/kd.h +++ b/include/linux/kd.h @@ -108,11 +108,11 @@ struct kd_disparam { #define KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ #define KDMKTONE 0x4B30 /* generate tone */ -#define KDGETLED 0x4B31 /* return current led flags */ -#define KDSETLED 0x4B32 /* set current led flags */ -#define LED_SCR 0x01 /* scroll lock */ -#define LED_CAP 0x04 /* caps lock */ -#define LED_NUM 0x02 /* num lock */ +#define KDGETLED 0x4B31 /* return current led state */ +#define KDSETLED 0x4B32 /* set led state [lights, not flags] */ +#define LED_SCR 0x01 /* scroll lock led */ +#define LED_CAP 0x04 /* caps lock led */ +#define LED_NUM 0x02 /* num lock led */ #define KDGKBTYPE 0x4B33 /* get keyboard type */ #define KB_84 0x01 @@ -164,15 +164,21 @@ typedef char scrnmap_t; #define K_RAW 0x00 #define K_XLATE 0x01 #define K_MEDIUMRAW 0x02 +#define K_UNICODE 0x03 #define KDGKBMODE 0x4B44 /* gets current keyboard mode */ #define KDSKBMODE 0x4B45 /* sets current keyboard mode */ -/* merge with previous pair of ioctls? */ #define K_METABIT 0x03 #define K_ESCPREFIX 0x04 #define KDGKBMETA 0x4B62 /* gets meta key handling mode */ #define KDSKBMETA 0x4B63 /* sets meta key handling mode */ +#define K_SCROLLLOCK 0x01 +#define K_CAPSLOCK 0x02 +#define K_NUMLOCK 0x04 +#define KDGKBLED 0x4B64 /* get led flags (not lights) */ +#define KDSKBLED 0x4B65 /* set led flags (not lights) */ + struct kbentry { u_char kb_table; u_char kb_index; @@ -182,13 +188,13 @@ struct kbentry { #define K_SHIFTTAB 0x01 #define K_ALTTAB 0x02 #define K_ALTSHIFTTAB 0x03 -#define K_SRQTAB 0x04 + #define KDGKBENT 0x4B46 /* gets one entry in translation table */ #define KDSKBENT 0x4B47 /* sets one entry in translation table */ struct kbsentry { u_char kb_func; - u_char kb_string[512]; /* FUNC_BUFSIZE from keyboard.h */ + u_char kb_string[512]; }; #define KDGKBSENT 0x4B48 /* gets one function key string entry */ #define KDSKBSENT 0x4B49 /* sets one function key string entry */ diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h index 9ee195cd8770..a10422b54d4c 100644 --- a/include/linux/keyboard.h +++ b/include/linux/keyboard.h @@ -5,24 +5,29 @@ #define KG_CTRL 2 #define KG_ALT 3 #define KG_ALTGR 1 -#define KG_SHIFTL 4 -#define KG_SHIFTR 5 -#define KG_CTRLL 6 -#define KG_CTRLR 7 +#define KG_SHIFTL 4 +#define KG_SHIFTR 5 +#define KG_CTRLL 6 +#define KG_CTRLR 7 +#define KG_CAPSSHIFT 8 + +#define NR_SHIFT 9 + +#define NR_KEYS 128 +#define MAX_NR_KEYMAPS 256 +/* This means 64Kb if all keymaps are allocated. Only the superuser + may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */ +#define MAX_NR_OF_USER_KEYMAPS 256 /* should be at least 7 */ -#define NR_KEYS 128 -#define NR_KEYMAPS 16 extern const int NR_TYPES; extern const int max_vals[]; -extern unsigned short key_map[NR_KEYMAPS][NR_KEYS]; +extern unsigned short *key_maps[MAX_NR_KEYMAPS]; +extern unsigned short plain_map[NR_KEYS]; -#define NR_FUNC 36 -#define FUNC_BUFSIZE 512 -extern char func_buf[FUNC_BUFSIZE]; -extern char *func_table[NR_FUNC]; +#define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */ #define KT_LATIN 0 /* we depend on this being zero */ -#define KT_LETTER 11 /* symbol that can be acted upon by CapsLock */ +#define KT_LETTER 11 /* symbol that can be acted upon by CapsLock */ #define KT_FN 1 #define KT_SPEC 2 #define KT_PAD 3 @@ -62,12 +67,239 @@ extern char *func_table[NR_FUNC]; #define K_INSERT K(KT_FN,21) #define K_REMOVE K(KT_FN,22) #define K_SELECT K(KT_FN,23) -#define K_PGUP K(KT_FN,24) -#define K_PGDN K(KT_FN,25) -#define K_MACRO K(KT_FN,26) -#define K_HELP K(KT_FN,27) -#define K_DO K(KT_FN,28) -#define K_PAUSE K(KT_FN,29) +#define K_PGUP K(KT_FN,24) /* PGUP is a synonym for PRIOR */ +#define K_PGDN K(KT_FN,25) /* PGDN is a synonym for NEXT */ +#define K_MACRO K(KT_FN,26) +#define K_HELP K(KT_FN,27) +#define K_DO K(KT_FN,28) +#define K_PAUSE K(KT_FN,29) +#define K_F21 K(KT_FN,30) +#define K_F22 K(KT_FN,31) +#define K_F23 K(KT_FN,32) +#define K_F24 K(KT_FN,33) +#define K_F25 K(KT_FN,34) +#define K_F26 K(KT_FN,35) +#define K_F27 K(KT_FN,36) +#define K_F28 K(KT_FN,37) +#define K_F29 K(KT_FN,38) +#define K_F30 K(KT_FN,39) +#define K_F31 K(KT_FN,40) +#define K_F32 K(KT_FN,41) +#define K_F33 K(KT_FN,42) +#define K_F34 K(KT_FN,43) +#define K_F35 K(KT_FN,44) +#define K_F36 K(KT_FN,45) +#define K_F37 K(KT_FN,46) +#define K_F38 K(KT_FN,47) +#define K_F39 K(KT_FN,48) +#define K_F40 K(KT_FN,49) +#define K_F41 K(KT_FN,50) +#define K_F42 K(KT_FN,51) +#define K_F43 K(KT_FN,52) +#define K_F44 K(KT_FN,53) +#define K_F45 K(KT_FN,54) +#define K_F46 K(KT_FN,55) +#define K_F47 K(KT_FN,56) +#define K_F48 K(KT_FN,57) +#define K_F49 K(KT_FN,58) +#define K_F50 K(KT_FN,59) +#define K_F51 K(KT_FN,60) +#define K_F52 K(KT_FN,61) +#define K_F53 K(KT_FN,62) +#define K_F54 K(KT_FN,63) +#define K_F55 K(KT_FN,64) +#define K_F56 K(KT_FN,65) +#define K_F57 K(KT_FN,66) +#define K_F58 K(KT_FN,67) +#define K_F59 K(KT_FN,68) +#define K_F60 K(KT_FN,69) +#define K_F61 K(KT_FN,70) +#define K_F62 K(KT_FN,71) +#define K_F63 K(KT_FN,72) +#define K_F64 K(KT_FN,73) +#define K_F65 K(KT_FN,74) +#define K_F66 K(KT_FN,75) +#define K_F67 K(KT_FN,76) +#define K_F68 K(KT_FN,77) +#define K_F69 K(KT_FN,78) +#define K_F70 K(KT_FN,79) +#define K_F71 K(KT_FN,80) +#define K_F72 K(KT_FN,81) +#define K_F73 K(KT_FN,82) +#define K_F74 K(KT_FN,83) +#define K_F75 K(KT_FN,84) +#define K_F76 K(KT_FN,85) +#define K_F77 K(KT_FN,86) +#define K_F78 K(KT_FN,87) +#define K_F79 K(KT_FN,88) +#define K_F80 K(KT_FN,89) +#define K_F81 K(KT_FN,90) +#define K_F82 K(KT_FN,91) +#define K_F83 K(KT_FN,92) +#define K_F84 K(KT_FN,93) +#define K_F85 K(KT_FN,94) +#define K_F86 K(KT_FN,95) +#define K_F87 K(KT_FN,96) +#define K_F88 K(KT_FN,97) +#define K_F89 K(KT_FN,98) +#define K_F90 K(KT_FN,99) +#define K_F91 K(KT_FN,100) +#define K_F92 K(KT_FN,101) +#define K_F93 K(KT_FN,102) +#define K_F94 K(KT_FN,103) +#define K_F95 K(KT_FN,104) +#define K_F96 K(KT_FN,105) +#define K_F97 K(KT_FN,106) +#define K_F98 K(KT_FN,107) +#define K_F99 K(KT_FN,108) +#define K_F100 K(KT_FN,109) +#define K_F101 K(KT_FN,110) +#define K_F102 K(KT_FN,111) +#define K_F103 K(KT_FN,112) +#define K_F104 K(KT_FN,113) +#define K_F105 K(KT_FN,114) +#define K_F106 K(KT_FN,115) +#define K_F107 K(KT_FN,116) +#define K_F108 K(KT_FN,117) +#define K_F109 K(KT_FN,118) +#define K_F110 K(KT_FN,119) +#define K_F111 K(KT_FN,120) +#define K_F112 K(KT_FN,121) +#define K_F113 K(KT_FN,122) +#define K_F114 K(KT_FN,123) +#define K_F115 K(KT_FN,124) +#define K_F116 K(KT_FN,125) +#define K_F117 K(KT_FN,126) +#define K_F118 K(KT_FN,127) +#define K_F119 K(KT_FN,128) +#define K_F120 K(KT_FN,129) +#define K_F121 K(KT_FN,130) +#define K_F122 K(KT_FN,131) +#define K_F123 K(KT_FN,132) +#define K_F124 K(KT_FN,133) +#define K_F125 K(KT_FN,134) +#define K_F126 K(KT_FN,135) +#define K_F127 K(KT_FN,136) +#define K_F128 K(KT_FN,137) +#define K_F129 K(KT_FN,138) +#define K_F130 K(KT_FN,139) +#define K_F131 K(KT_FN,140) +#define K_F132 K(KT_FN,141) +#define K_F133 K(KT_FN,142) +#define K_F134 K(KT_FN,143) +#define K_F135 K(KT_FN,144) +#define K_F136 K(KT_FN,145) +#define K_F137 K(KT_FN,146) +#define K_F138 K(KT_FN,147) +#define K_F139 K(KT_FN,148) +#define K_F140 K(KT_FN,149) +#define K_F141 K(KT_FN,150) +#define K_F142 K(KT_FN,151) +#define K_F143 K(KT_FN,152) +#define K_F144 K(KT_FN,153) +#define K_F145 K(KT_FN,154) +#define K_F146 K(KT_FN,155) +#define K_F147 K(KT_FN,156) +#define K_F148 K(KT_FN,157) +#define K_F149 K(KT_FN,158) +#define K_F150 K(KT_FN,159) +#define K_F151 K(KT_FN,160) +#define K_F152 K(KT_FN,161) +#define K_F153 K(KT_FN,162) +#define K_F154 K(KT_FN,163) +#define K_F155 K(KT_FN,164) +#define K_F156 K(KT_FN,165) +#define K_F157 K(KT_FN,166) +#define K_F158 K(KT_FN,167) +#define K_F159 K(KT_FN,168) +#define K_F160 K(KT_FN,169) +#define K_F161 K(KT_FN,170) +#define K_F162 K(KT_FN,171) +#define K_F163 K(KT_FN,172) +#define K_F164 K(KT_FN,173) +#define K_F165 K(KT_FN,174) +#define K_F166 K(KT_FN,175) +#define K_F167 K(KT_FN,176) +#define K_F168 K(KT_FN,177) +#define K_F169 K(KT_FN,178) +#define K_F170 K(KT_FN,179) +#define K_F171 K(KT_FN,180) +#define K_F172 K(KT_FN,181) +#define K_F173 K(KT_FN,182) +#define K_F174 K(KT_FN,183) +#define K_F175 K(KT_FN,184) +#define K_F176 K(KT_FN,185) +#define K_F177 K(KT_FN,186) +#define K_F178 K(KT_FN,187) +#define K_F179 K(KT_FN,188) +#define K_F180 K(KT_FN,189) +#define K_F181 K(KT_FN,190) +#define K_F182 K(KT_FN,191) +#define K_F183 K(KT_FN,192) +#define K_F184 K(KT_FN,193) +#define K_F185 K(KT_FN,194) +#define K_F186 K(KT_FN,195) +#define K_F187 K(KT_FN,196) +#define K_F188 K(KT_FN,197) +#define K_F189 K(KT_FN,198) +#define K_F190 K(KT_FN,199) +#define K_F191 K(KT_FN,200) +#define K_F192 K(KT_FN,201) +#define K_F193 K(KT_FN,202) +#define K_F194 K(KT_FN,203) +#define K_F195 K(KT_FN,204) +#define K_F196 K(KT_FN,205) +#define K_F197 K(KT_FN,206) +#define K_F198 K(KT_FN,207) +#define K_F199 K(KT_FN,208) +#define K_F200 K(KT_FN,209) +#define K_F201 K(KT_FN,210) +#define K_F202 K(KT_FN,211) +#define K_F203 K(KT_FN,212) +#define K_F204 K(KT_FN,213) +#define K_F205 K(KT_FN,214) +#define K_F206 K(KT_FN,215) +#define K_F207 K(KT_FN,216) +#define K_F208 K(KT_FN,217) +#define K_F209 K(KT_FN,218) +#define K_F210 K(KT_FN,219) +#define K_F211 K(KT_FN,220) +#define K_F212 K(KT_FN,221) +#define K_F213 K(KT_FN,222) +#define K_F214 K(KT_FN,223) +#define K_F215 K(KT_FN,224) +#define K_F216 K(KT_FN,225) +#define K_F217 K(KT_FN,226) +#define K_F218 K(KT_FN,227) +#define K_F219 K(KT_FN,228) +#define K_F220 K(KT_FN,229) +#define K_F221 K(KT_FN,230) +#define K_F222 K(KT_FN,231) +#define K_F223 K(KT_FN,232) +#define K_F224 K(KT_FN,233) +#define K_F225 K(KT_FN,234) +#define K_F226 K(KT_FN,235) +#define K_F227 K(KT_FN,236) +#define K_F228 K(KT_FN,237) +#define K_F229 K(KT_FN,238) +#define K_F230 K(KT_FN,239) +#define K_F231 K(KT_FN,240) +#define K_F232 K(KT_FN,241) +#define K_F233 K(KT_FN,242) +#define K_F234 K(KT_FN,243) +#define K_F235 K(KT_FN,244) +#define K_F236 K(KT_FN,245) +#define K_F237 K(KT_FN,246) +#define K_F238 K(KT_FN,247) +#define K_F239 K(KT_FN,248) +#define K_F240 K(KT_FN,249) +#define K_F241 K(KT_FN,250) +#define K_F242 K(KT_FN,251) +#define K_F243 K(KT_FN,252) +#define K_F244 K(KT_FN,253) +#define K_F245 K(KT_FN,254) +#define K_F246 K(KT_FN,255) + #define K_HOLE K(KT_SPEC,0) #define K_ENTER K(KT_SPEC,1) @@ -83,8 +315,13 @@ extern char *func_table[NR_FUNC]; #define K_SCROLLBACK K(KT_SPEC,11) #define K_BOOT K(KT_SPEC,12) #define K_CAPSON K(KT_SPEC,13) -#define K_COMPOSE K(KT_SPEC,14) +#define K_COMPOSE K(KT_SPEC,14) #define K_SAK K(KT_SPEC,15) +#define K_DECRCONSOLE K(KT_SPEC,16) +#define K_INCRCONSOLE K(KT_SPEC,17) + +#define K_ALLOCATED K(KT_SPEC,126) /* dynamically allocated keymap */ +#define K_NOSUCHMAP K(KT_SPEC,127) /* returned by KDGKBENT */ #define K_P0 K(KT_PAD,0) #define K_P1 K(KT_PAD,1) @@ -96,14 +333,16 @@ extern char *func_table[NR_FUNC]; #define K_P7 K(KT_PAD,7) #define K_P8 K(KT_PAD,8) #define K_P9 K(KT_PAD,9) -#define K_PPLUS K(KT_PAD,10) /* key-pad plus */ -#define K_PMINUS K(KT_PAD,11) /* key-pad minus */ -#define K_PSTAR K(KT_PAD,12) /* key-pad asterisk (star) */ -#define K_PSLASH K(KT_PAD,13) /* key-pad slash */ -#define K_PENTER K(KT_PAD,14) /* key-pad enter */ -#define K_PCOMMA K(KT_PAD,15) /* key-pad comma: kludge... */ +#define K_PPLUS K(KT_PAD,10) /* key-pad plus */ +#define K_PMINUS K(KT_PAD,11) /* key-pad minus */ +#define K_PSTAR K(KT_PAD,12) /* key-pad asterisk (star) */ +#define K_PSLASH K(KT_PAD,13) /* key-pad slash */ +#define K_PENTER K(KT_PAD,14) /* key-pad enter */ +#define K_PCOMMA K(KT_PAD,15) /* key-pad comma: kludge... */ #define K_PDOT K(KT_PAD,16) /* key-pad dot (period): kludge... */ -#define K_PPLUSMINUS K(KT_PAD,17) /* key-pad plus/minus */ +#define K_PPLUSMINUS K(KT_PAD,17) /* key-pad plus/minus */ + +#define NR_PAD 18 #define K_DGRAVE K(KT_DEAD,0) #define K_DACUTE K(KT_DEAD,1) @@ -111,6 +350,8 @@ extern char *func_table[NR_FUNC]; #define K_DTILDE K(KT_DEAD,3) #define K_DDIERE K(KT_DEAD,4) +#define NR_DEAD 5 + #define K_DOWN K(KT_CUR,0) #define K_LEFT K(KT_CUR,1) #define K_RIGHT K(KT_CUR,2) @@ -120,14 +361,11 @@ extern char *func_table[NR_FUNC]; #define K_CTRL K(KT_SHIFT,KG_CTRL) #define K_ALT K(KT_SHIFT,KG_ALT) #define K_ALTGR K(KT_SHIFT,KG_ALTGR) -#define K_SHIFTL K(KT_SHIFT,KG_SHIFTL) -#define K_SHIFTR K(KT_SHIFT,KG_SHIFTR) -#define K_CTRLL K(KT_SHIFT,KG_CTRLL) -#define K_CTRLR K(KT_SHIFT,KG_CTRLR) - -#define NR_SHIFT 4 - -#define K_CAPSSHIFT K(KT_SHIFT,NR_SHIFT) +#define K_SHIFTL K(KT_SHIFT,KG_SHIFTL) +#define K_SHIFTR K(KT_SHIFT,KG_SHIFTR) +#define K_CTRLL K(KT_SHIFT,KG_CTRLL) +#define K_CTRLR K(KT_SHIFT,KG_CTRLR) +#define K_CAPSSHIFT K(KT_SHIFT,KG_CAPSSHIFT) #define K_ASC0 K(KT_ASCII,0) #define K_ASC1 K(KT_ASCII,1) @@ -139,11 +377,35 @@ extern char *func_table[NR_FUNC]; #define K_ASC7 K(KT_ASCII,7) #define K_ASC8 K(KT_ASCII,8) #define K_ASC9 K(KT_ASCII,9) +#define K_HEX0 K(KT_ASCII,10) +#define K_HEX1 K(KT_ASCII,11) +#define K_HEX2 K(KT_ASCII,12) +#define K_HEX3 K(KT_ASCII,13) +#define K_HEX4 K(KT_ASCII,14) +#define K_HEX5 K(KT_ASCII,15) +#define K_HEX6 K(KT_ASCII,16) +#define K_HEX7 K(KT_ASCII,17) +#define K_HEX8 K(KT_ASCII,18) +#define K_HEX9 K(KT_ASCII,19) +#define K_HEXa K(KT_ASCII,20) +#define K_HEXb K(KT_ASCII,21) +#define K_HEXc K(KT_ASCII,22) +#define K_HEXd K(KT_ASCII,23) +#define K_HEXe K(KT_ASCII,24) +#define K_HEXf K(KT_ASCII,25) + +#define NR_ASCII 26 #define K_SHIFTLOCK K(KT_LOCK,KG_SHIFT) #define K_CTRLLOCK K(KT_LOCK,KG_CTRL) #define K_ALTLOCK K(KT_LOCK,KG_ALT) #define K_ALTGRLOCK K(KT_LOCK,KG_ALTGR) +#define K_SHIFTLLOCK K(KT_LOCK,KG_SHIFTL) +#define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) +#define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) +#define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) + +#define NR_LOCK 8 -#define MAX_DIACR 256 +#define MAX_DIACR 256 #endif diff --git a/include/linux/tty.h b/include/linux/tty.h index e44c5e2cb85a..e53cd0eab711 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -18,8 +18,14 @@ /* * Note: don't mess with NR_PTYS until you understand the tty minor * number allocation game... + * (Note: the *_driver.minor_start values 1, 64, 128, 192 are + * hardcoded at present.) */ -#define NR_CONSOLES 8 +#define MIN_NR_CONSOLES 1 /* must be at least 1 */ +#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ +#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ + /* Note: the ioctl VT_GETSTATE does not work for + consoles 16 and higher (since it returns a short) */ #define NR_PTYS 64 #define NR_LDISCS 16 @@ -257,8 +263,6 @@ extern struct termios tty_std_termios; extern struct tty_struct * redirect; extern struct tty_ldisc ldiscs[]; extern int fg_console; -extern unsigned long video_num_columns; -extern unsigned long video_num_lines; extern struct wait_queue * keypress_wait; /* intr=^C quit=^| erase=del kill=^U diff --git a/include/linux/vt.h b/include/linux/vt.h index 107ad315471a..33f1ad659052 100644 --- a/include/linux/vt.h +++ b/include/linux/vt.h @@ -30,5 +30,13 @@ struct vt_stat { #define VT_ACTIVATE 0x5606 /* make vt active */ #define VT_WAITACTIVE 0x5607 /* wait for vt active */ +#define VT_DISALLOCATE 0x5608 /* free memory associated to vt */ + +struct vt_sizes { + ushort v_rows; /* number of rows */ + ushort v_cols; /* number of columns */ + ushort v_scrollsize; /* number of lines of scrollback */ +}; +#define VT_RESIZE 0x5609 /* set kernel's idea of screensize */ #endif /* _LINUX_VT_H */ diff --git a/net/inet/ip.c b/net/inet/ip.c index 182c19bf19aa..d34435601d4c 100644 --- a/net/inet/ip.c +++ b/net/inet/ip.c @@ -1803,11 +1803,9 @@ void ip_do_retransmit(struct sock *sk, int all) struct sk_buff * skb; struct proto *prot; struct device *dev; - int retransmits; prot = sk->prot; skb = sk->send_head; - retransmits = sk->retransmits; while (skb != NULL) { @@ -1869,7 +1867,7 @@ void ip_do_retransmit(struct sock *sk, int all) /* * Count retransmissions */ - retransmits++; + sk->retransmits++; sk->prot->retransmits ++; /* @@ -1881,7 +1879,7 @@ void ip_do_retransmit(struct sock *sk, int all) /* * This should cut it off before we send too many packets. */ - if (sk->retransmits > sk->cong_window) + if (sk->retransmits >= sk->cong_window) break; skb = skb->link3; } diff --git a/net/inet/ipx.c b/net/inet/ipx.c index 561b20ba1e88..341657f81ec5 100644 --- a/net/inet/ipx.c +++ b/net/inet/ipx.c @@ -155,11 +155,11 @@ int ipx_get_info(char *buffer, char **start, off_t offset, int length) for (s = ipx_socket_list; s != NULL; s = s->next) { len += sprintf (buffer+len,"%02X ", s->ipx_type); - len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_source_addr.net), + len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_source_addr.net), s->ipx_source_addr.node[0], s->ipx_source_addr.node[1], s->ipx_source_addr.node[2], s->ipx_source_addr.node[3], s->ipx_source_addr.node[4], s->ipx_source_addr.node[5], htons(s->ipx_source_addr.sock)); - len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_dest_addr.net), + len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_dest_addr.net), s->ipx_dest_addr.node[0], s->ipx_dest_addr.node[1], s->ipx_dest_addr.node[2], s->ipx_dest_addr.node[3], s->ipx_dest_addr.node[4], s->ipx_dest_addr.node[5], htons(s->ipx_dest_addr.sock)); @@ -643,10 +643,13 @@ static unsigned short first_free_socketnum(void) { static unsigned short socketNum = 0x4000; - while (ipx_find_socket(htons(socketNum)) != NULL) - if (socketNum > 0x7ffc) socketNum = 0x4000; + while (ipx_find_socket(ntohs(socketNum)) != NULL) + if (socketNum > 0x7ffc) + socketNum = 0x4000; + else + socketNum++; - return htons(socketNum++); + return ntohs(socketNum); } static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len) @@ -726,8 +729,8 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; - - if(addr_len!=sizeof(addr)) + + if(addr_len!=sizeof(*addr)) return(-EINVAL); addr=(struct sockaddr_ipx *)uaddr; @@ -748,6 +751,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, memcpy(sk->ipx_dest_addr.node,addr->sipx_node,sizeof(sk->ipx_source_addr.node)); if(ipxrtr_get_dev(sk->ipx_dest_addr.net)==NULL) return -ENETUNREACH; + sk->ipx_type=addr->sipx_type; sock->state = SS_CONNECTED; sk->state=TCP_ESTABLISHED; return(0); @@ -786,6 +790,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, addr=&sk->ipx_source_addr; sipx.sipx_family = AF_IPX; + sipx.sipx_type = sk->ipx_type; sipx.sipx_port = addr->sock; sipx.sipx_network = addr->net; memcpy(sipx.sipx_node,addr->node,sizeof(sipx.sipx_node)); @@ -856,7 +861,7 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) int free_it=0; /* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */ - if(ipx->ipx_tctrl==16) + if((ipx->ipx_tctrl==16) || (dev->flags & IFF_PROMISC)) { kfree_skb(skb,FREE_READ); return(0); @@ -998,6 +1003,7 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock, return -ENOTCONN; usipx=&local_sipx; usipx->sipx_family=AF_IPX; + usipx->sipx_type=sk->ipx_type; usipx->sipx_port=sk->ipx_dest_addr.sock; usipx->sipx_network=sk->ipx_dest_addr.net; memcpy(usipx->sipx_node,sk->ipx_dest_addr.node,sizeof(usipx->sipx_node)); -- 2.39.5