]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.92 1.1.92
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:55 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:55 +0000 (15:09 -0500)
54 files changed:
Makefile
arch/alpha/config.in
arch/i386/config.in
arch/mips/config.in
arch/sparc/config.in
drivers/block/README.sonycd535
drivers/block/ll_rw_blk.c
drivers/block/sonycd535.c
drivers/char/Makefile
drivers/char/console.c
drivers/char/consolemap.c [new file with mode: 0644]
drivers/char/consolemap.h [new file with mode: 0644]
drivers/char/kbd_kern.h
drivers/char/keyboard.c
drivers/char/selection.c [new file with mode: 0644]
drivers/char/selection.h [new file with mode: 0644]
drivers/char/tty_io.c
drivers/char/uni_to_437.c [deleted file]
drivers/char/vc_screen.c [new file with mode: 0644]
drivers/char/vt.c
drivers/net/3c501.c
drivers/net/3c509.c
drivers/net/ppp.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/eata_dma.c
drivers/scsi/eata_dma.h
drivers/scsi/hosts.c
drivers/scsi/scsi.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
fs/binfmt_elf.c
fs/locks.c
fs/nfs/inode.c
fs/open.c
fs/proc/array.c
include/asm-alpha/system.h
include/asm-i386/pgtable.h
include/asm-i386/system.h
include/linux/fs.h
include/linux/major.h
include/linux/mm.h
include/linux/tty.h
init/main.c
kernel/ksyms.c
mm/filemap.c
mm/memory.c
mm/mprotect.c
mm/swap.c
net/inet/arp.c
net/inet/dev.c
net/inet/ip.c

index cf4f2d762745da06cf7b028fdca0bc9baf06e109..f91831ae3b3c4de621a8da9ba1a37e4acaac7862 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 91
+SUBLEVEL = 92
 
 ARCH = i386
 
@@ -198,7 +198,7 @@ ifdef CONFIG_MODVERSIONS
 MODV = -DCONFIG_MODVERSIONS
 endif
 
-modules: dummy
+modules: include/linux/version.h
        @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) -DMODULE $(MODV)" modules; done
        
 modules_install:
index c34e6e9242debb314b50059db46c664dec428cd8..794f280127f855b35c008648bc52e442123aa922 100644 (file)
@@ -199,11 +199,6 @@ bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
-bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
-if [ "$CONFIG_VESA_PSPM" = "y" ]; then
-bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
-fi
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
index f714ae9f1b16135dd1ceb42942bcd4e103165460..5b902b832a52ce6e97f9e2b030bd8f46c57b737e 100644 (file)
@@ -10,7 +10,7 @@ bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
 bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
 if [ "$CONFIG_ST506" = "y" ]; then
   comment 'Please see drivers/block/README.ide for help/info on IDE drives'
-  bool '   Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y
+  bool '   Use old disk-only driver for primary i/f' CONFIG_BLK_DEV_HD n
   if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
     bool '   Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
   else
@@ -229,7 +229,6 @@ bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
index c64fd450366818ed815667a1b844f25c926ec7be..14c7554f58c86f2b662da29d1a122db1298d16d3 100644 (file)
@@ -219,7 +219,6 @@ bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE n
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
   
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
 if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
index 5fac1cfe5e7204043426c096d6171f7801dcf2eb..96504d3972135073cb1df7ae2ad0dd4df32b7d41 100644 (file)
@@ -206,11 +206,6 @@ bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
-bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
-if [ "$CONFIG_VESA_PSPM" = "y" ]; then
-bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
-fi
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
index 9e6d3cde67f64f16e55461295eb6a73e5c0267e0..4c6f4da1f152e4352e07b5b37415dc1282fc7d48 100644 (file)
@@ -45,7 +45,7 @@ NOTES:
 ======
 
 1) The drive MUST be turned on when booting or it will not be recognized!
-   (but see comments on modulized version below)
+   (but see comments on modularized version below)
 
 2) when the cdrom device is opened the eject button is disabled to keep the
    user from ejecting a mounted disk and replacing it with another.
@@ -60,8 +60,13 @@ THANKS
 Many thanks to Ron Jeppesen (ronj.an@site007.saic.com) for getting
 this project off the ground.  He wrote the initial release and
 the first two patches to this driver (0.1, 0.2, and 0.3).
+Thanks also to Eberhard Moenkeberg (emoenke@gwdg.de) for prodding
+me to place this code into the mainstream Linux source tree (as
+of Linux version 1.1.91), as well as some patches to make it a
+better device citizen.  Further thanks to "S. Joel Katz"
+<stimpson@panix.com> for his MODULE patches (see details below).
 
-(aknowlegements from Ron Jeppesen in the 0.3 release:)
+(Acknowledgments from Ron Jeppesen in the 0.3 release:)
 Thanks to Corey Minyard who wrote the original CDU-31A driver on which
 this driver is based.  Thanks to Ken Pizzini and Bob Blair who provided 
 patches and feedback on the first release of this driver.
@@ -89,7 +94,7 @@ rmmod sony535
 to if MODULE is not defined. That means your patched file should behave
 exactly as it used to if compiled into the kernel.
 
-       I have an externel drive, and I usually leave it powered off. I used
+       I have an external drive, and I usually leave it powered off. I used
 to have to reboot if I needed to use the CDROM drive. Now I don't.
 
        Even if you have an internal drive, why waste the 268K of memory
index 650d5b3f5864cefa838549fe19d8d5087bbe9d25..94a97b1d79c04bf7be551b1a6b1ad3fd292affff 100644 (file)
@@ -399,9 +399,6 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
        int correct_size;
        struct blk_dev_struct * dev;
        int i;
-#if defined(CONFIG_CDU535) && defined(CONFIG_CDU31A)
-       int sonycd_save_mem_start;
-#endif
 
        /* Make sure that the first block contains something reasonable */
        while (!*bh) {
@@ -545,24 +542,12 @@ long blk_dev_init(long mem_start, long mem_end)
 #ifdef CONFIG_BLK_DEV_XD
        mem_start = xd_init(mem_start,mem_end);
 #endif
-#if defined(CONFIG_CDU535) && defined(CONFIG_CDU31A)
-       {  /* since controllers for 535 and 31A can be at same location
-           * we have to be careful.
-           */
-               sonycd_save_mem_start = mem_start;
-               mem_start = cdu31a_init(mem_start,mem_end);
-               if ( mem_start == sonycd_save_mem_start ) {  /* CDU31A not found */
-                       mem_start = sony535_init(mem_start,mem_end);
-               }
-       }
-#else
 #ifdef CONFIG_CDU31A
        mem_start = cdu31a_init(mem_start,mem_end);
 #endif
 #ifdef CONFIG_CDU535
        mem_start = sony535_init(mem_start,mem_end);
 #endif
-#endif  /* CONFIG_CDU31A && CONFIG_CDU535 */
 #ifdef CONFIG_MCD
        mem_start = mcd_init(mem_start,mem_end);
 #endif
index 6940b60a0a3653bf82d503eb96e44ca7d270cd2e..64b7754e70acc96efc9853bd02386862d37946c3 100644 (file)
@@ -44,7 +44,7 @@
  * include/linux/cdrom.h).  With this interface, CDROMs can be
  * accessed and standard audio CDs can be played back normally.
  *
- * This interface is (unfortunatly) a polled interface.  This is
+ * This interface is (unfortunately) a polled interface.  This is
  * because most Sony interfaces are set up with DMA and interrupts
  * disables.  Some (like mine) do not even have the capability to
  * handle interrupts or DMA.  For this reason you will see a lot of
@@ -65,7 +65,7 @@
  *
  * This ugly hack waits for something to happen, sleeping a little
  * between every try.  it also handles attentions, which are
- * asyncronous events from the drive informing the driver that a disk
+ * asynchronous events from the drive informing the driver that a disk
  * has been inserted, removed, etc.
  *
  * One thing about these drives: They talk in MSF (Minute Second Frame) format.
 
 
 #include <linux/config.h>
-#ifdef CONFIG_CDU535
+#if defined(CONFIG_CDU535) || defined(MODULE)
 
 #ifdef MODULE
 # include <linux/module.h>
+# include <linux/malloc.h>
 # include <linux/version.h>
 #endif
 
 #endif
 
 /*
- * this is the base address of the interface card for the Sony CDU535
+ * this is the base address of the interface card for the Sony CDU-535
  * CDROM drive.  If your jumpers are set for an address other than
  * this one (the default), change the following line to the
  * proper address.
  */
 #ifndef CDU535_ADDRESS
-#define CDU535_ADDRESS (0x340)
+# define CDU535_ADDRESS        (0x340)
 #endif
 
-#define DEBUG  1
+#ifndef CDU535_HANDLE
+# define CDU535_HANDLE                 "cdu535"
+#endif
+#ifndef CDU535_MESSAGE_NAME
+# define CDU535_MESSAGE_NAME   "Sony CDU-535"
+#endif
+
+#ifndef DEBUG
+# define DEBUG 1
+#endif
 
 /*
  *  SONY535_BUFFER_SIZE determines the size of internal buffer used
@@ -440,10 +450,10 @@ check_drive_status(void)
  *  should be placed in the cmd[] array, number of bytes in the command is
  *  stored in nCmd.  The response from the command will be stored in the
  *  response array.  The number of bytes you expect back (excluding status)
- *  should be passed in nReponse.  Finally, some
+ *  should be passed in nResponse.  Finally, some
  *  commands set bit 7 of the return status even when there is no second
  *  status byte, on these commands set ignoreStatusBit7 TRUE.
- *    If the command was sent and data recieved back, then we return 0,
+ *    If the command was sent and data received back, then we return 0,
  *  else we return TIME_OUT.  You still have to check the status yourself.
  *    You should call check_drive_status() before calling this routine
  *  so that you do not lose notifications of disk changes, etc.
@@ -843,7 +853,7 @@ do_cdu535_request(void)
                        break;
 
                default:
-                       panic("Unkown SONY CD cmd");
+                       panic("Unknown SONY CD cmd");
                }
        }
 }
@@ -1432,7 +1442,8 @@ init_module(void)
                if (do_sony_cmd(cmd_buff, 1, status, (Byte *) & drive_config, 28, 1) == 0) {
                        /* was able to get the configuration, set drive mode as rest of init */
 #if DEBUG > 0
-                       if ( (status[0] & 0x7f) != 0 )
+                       /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
+                       if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
                                printk("Inquiry command returned status = 0x%x\n", status[0]);
 #endif
                        cmd_buff[0] = SONY535_SET_DRIVE_MODE;
@@ -1448,8 +1459,9 @@ init_module(void)
                                           drive_config.product_rev_level);
                                printk("  using %d byte buffer\n", sony_buffer_size);
 
-                               if (register_blkdev(MAJOR_NR, "cdu-535", &cdu_fops)) {
-                                       printk("Unable to get major %d for sony CDU-535 cd\n", MAJOR_NR);
+                               if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
+                                       printk("Unable to get major %d for %s\n",
+                                                       MAJOR_NR, CDU535_MESSAGE_NAME);
 #ifndef MODULE
                                        return mem_start;
 #else
@@ -1482,19 +1494,17 @@ init_module(void)
                }
        }
 
-#ifndef MODULE
-       if (!initialized)
-               printk("Did not find a Sony CDU-535 drive\n");
-       else
-               snarf_region(sony_cd_base_io, 4);
-       return mem_start;
-#else
        if (!initialized) {
-               printk("Did not find a Sony CDU-535 drive\n");
+               printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
+#ifdef MODULE
                return -EIO;
+#endif
        } else {
-               snarf_region(sony_cd_base_io, 4);
+               request_region(sony_cd_base_io, 4, CDU535_HANDLE);
        }
+#ifndef MODULE
+       return mem_start;
+#else
        return 0;
 #endif
 }
@@ -1519,7 +1529,8 @@ sonycd535_setup(char *strings, int *ints)
                irq_used = ints[2];
 #endif
        if ((strings != NULL) && (*strings != '\0'))
-               printk("Sony CDU-535: Warning: Unknown interface type: %s\n", strings);
+               printk("%s: Warning: Unknown interface type: %s\n",
+                               strings, CDU535_MESSAGE_NAME);
 }
 
 #else /* MODULE */
@@ -1527,21 +1538,21 @@ sonycd535_setup(char *strings, int *ints)
 void 
 cleanup_module(void)
 {
-       int     i;
+       int i;
        if (MOD_IN_USE) {
                printk("Sony 535 module in use, cannot remove\n");
                return;
        }
-       if (unregister_blkdev(MAJOR_NR, "cdu-535") == (-EINVAL)) {
-               printk("Uh oh, couldn't unregister cdu-535\n");
-               return;
-       }
+       release_region(sony_cd_base_io, 4);
        kfree_s(sony_toc, sizeof (*sony_toc));
        kfree_s(last_sony_subcode, sizeof (*last_sony_subcode));
        for (i = 0; i < sony_buffer_sectors; i++)
                kfree_s(sony_buffer[i], 2048);
        kfree_s(sony_buffer, 4 * sony_buffer_sectors);
-       printk("cdu-535 module released\n");
+       if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
+               printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
+       else
+               printk(CDU535_HANDLE " module released\n");
 }
 #endif /* MODULE */
 
index c6b82dcdc93e8494454d33af97a2f6b3dafde9c2..45fd9de6d1d8fd6b5099ea42de1dd3c1e3643f46 100644 (file)
        $(CC) $(CFLAGS) -c $<
 
 OBJS  = tty_io.o n_tty.o console.o keyboard.o serial.o \
-       tty_ioctl.o pty.o vt.o mem.o \
-       defkeymap.o uni_to_437.o vesa_blank.o
+       tty_ioctl.o pty.o vt.o mem.o vc_screen.o \
+       defkeymap.o consolemap.o vesa_blank.o selection.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 uni_to_437.c vesa_blank.c
+       tty_ioctl.c pty.c vt.c mem.c vc_screen.c \
+       defkeymap.c consolemap.c vesa_blank.c selection.c
 
 
 ifdef CONFIG_CYCLADES
index a3d31b8ef467a5a44b71bd79e5953481e22c3ca0..90120c6fb75aaa52e1e8ca3a5299c72ee431be18 100644 (file)
  *     'void do_blank_screen(int)'
  *     'void do_unblank_screen(void)'
  *     'void poke_blanked_console(void)'
+ *
+ *     'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
+ *     'void complement_pos(int currcons, int offset)'
+ *     'void invert_screen(int currcons, int offset, int count, int shift)'
+ *
  *     'void scrollback(int lines)'
  *     'void scrollfront(int lines)'
- *     'int do_screendump(int arg, int mode)'
  *
  *     'int con_get_font(char *)' 
- *     'int con_set_font(char *)' 
- *     'int con_get_trans(char *)'
- *     'int con_set_trans(char *)'
+ *     'int con_set_font(char *)'
  *
- *     'int set_selection(const int arg)'
- *     'int paste_selection(struct tty_struct *tty)'
- *     'int sel_loadlut(const int arg)'
+ *     'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
  *     'int mouse_reporting(void)'
- * 
+ *
  * Hopefully this will be a rather complete VT102 implementation.
  *
  * Beeping thanks to John T Kohl.
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
+#include "consolemap.h"
+#include "selection.h"
 
-#ifdef __alpha__
-static inline void scrwritew(unsigned short val, unsigned short * addr)
-{
-       if ((long) addr < 0)
-               *addr = val;
-       else
-               writew(val, (unsigned long) addr);
-}
-
-static inline unsigned short scrreadw(unsigned short * addr)
-{
-       if ((long) addr < 0)
-               return *addr;
-       return readw((unsigned long) addr);
-}
-
-#else
-
-static inline void scrwritew(unsigned short val, unsigned short * addr)
-{
-       *addr = val;
-}
-
-static inline unsigned short scrreadw(unsigned short * addr)
-{
-       return *addr;
-}
-
-#endif
-
-#define writew(x,y) scrwritew((x),(y))
-#define readw(x) scrreadw(x)
 
 #ifndef MIN
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
@@ -149,23 +118,6 @@ 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 <linux/ctype.h>
-
-/* Routines for selection control. */
-int set_selection(const int arg, struct tty_struct *tty);
-int paste_selection(struct tty_struct *tty);
-static void clear_selection(void);
-static void highlight_pointer(const int currcons, const int where);
-
-/* Variables for selection control. */
-/* Use a dynamic buffer, instead of static (Dec 1994) */
-static int sel_cons = 0;
-static int sel_start = -1;
-static int sel_end;
-static char *sel_buffer = NULL;
-#endif /* CONFIG_SELECTION */
-
 #define NPAR 16
 
 static void con_setsize(unsigned long rows, unsigned long cols);
@@ -194,11 +146,13 @@ 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 char   video_page;             /* Initial video page (unused)  */
+       /* these two also used in vesa_blank.c */
        unsigned short  video_port_reg;         /* Video register select port   */
        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;
+       /* these three also used in selection.c */
+       unsigned long   video_num_columns;      /* Number of text columns       */
+       unsigned long   video_num_lines;        /* Number of text lines         */
+       unsigned long   video_size_row;
 static unsigned long   video_screen_size;
 static int can_do_color = 0;
 static int printable = 0;                      /* Is console ready for printing? */
@@ -260,10 +214,10 @@ struct vc_data {
        unsigned long   vc_utf_char;
        unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
        unsigned char * vc_translate;
-       unsigned char * vc_G0_charset;
-       unsigned char * vc_G1_charset;
-       unsigned char * vc_saved_G0;
-       unsigned char * vc_saved_G1;
+       unsigned char   vc_G0_charset;
+       unsigned char   vc_G1_charset;
+       unsigned char   vc_saved_G0;
+       unsigned char   vc_saved_G1;
        /* additional information is in vt_kern.h */
 };
 
@@ -342,7 +296,7 @@ static void memsetw(void * s, unsigned short c, unsigned int count)
        count /= 2;
        while (count) {
                count--;
-               writew(c, addr++);
+               scr_writew(c, addr++);
        }
 }
 
@@ -352,7 +306,7 @@ static inline void memcpyw(unsigned short *to, unsigned short *from,
        count /= 2;
        while (count) {
                count--;
-               writew(readw(from++), to++);
+               scr_writew(scr_readw(from++), to++);
        }
 }
 
@@ -522,81 +476,6 @@ void vc_disallocate(unsigned int currcons)
 #define VT100ID "\033[?1;2c"
 #define VT102ID "\033[?6c"
 
-static unsigned char * translations[] = {
-/* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
-(unsigned char *)
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
-       " !\"#$%&'()*+,-./0123456789:;<=>?"
-       "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
-       "`abcdefghijklmnopqrstuvwxyz{|}~\0"
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
-       "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
-       "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
-       "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
-       "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
-       "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
-/* vt100 graphics */
-(unsigned char *)
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
-       " !\"#$%&'()*+,-./0123456789:;<=>?"
-       "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
-       "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
-       "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
-       "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
-       "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
-       "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
-       "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
-       "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
-/* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
-(unsigned char *)
-       "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
-       "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
-       "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
-       "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
-       "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
-       "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
-       "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
-       "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
-       "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
-       "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
-       "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
-       "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
-       "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
-       "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
-       "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
-       "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
- /* USER: customizable mappings, initialized as the previous one (IBM) */
-(unsigned char *)
-       "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
-       "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
-       "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
-       "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
-       "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
-       "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
-       "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
-       "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
-       "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
-       "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
-       "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
-       "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
-       "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
-       "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
-       "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
-       "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
-};
-
-#define NORM_TRANS (translations[0])
-#define GRAF_TRANS (translations[1])
-#define NULL_TRANS (translations[2])
-#define USER_TRANS (translations[3])
-
 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
                                       8,12,10,14, 9,13,11,15 };
 
@@ -641,9 +520,9 @@ static unsigned short __origin;             /* offset of currently displayed screen */
 static inline void __set_origin(unsigned short offset)
 {
        unsigned long flags;
-#ifdef CONFIG_SELECTION
+
        clear_selection();
-#endif /* CONFIG_SELECTION */
+
        save_flags(flags); cli();
        __origin = offset;
        outb_p(12, video_port_reg);
@@ -740,12 +619,12 @@ static void scrup(int currcons, unsigned int t, unsigned int b)
                        count = (video_num_lines-1)*video_num_columns;
                        while (count) {
                                count--;
-                               writew(readw(s++),d++);
+                               scr_writew(scr_readw(s++),d++);
                        }
                        count = video_num_columns;
                        while (count) {
                                count--;
-                               writew(video_erase_char, d++);
+                               scr_writew(video_erase_char, d++);
                        }
                        scr_end -= origin-video_mem_start;
                        pos -= origin-video_mem_start;
@@ -759,7 +638,7 @@ static void scrup(int currcons, unsigned int t, unsigned int b)
                        count = video_num_columns;
                        while (count) {
                                count--;
-                               writew(video_erase_char, d++);
+                               scr_writew(video_erase_char, d++);
                        }
                }
                set_origin(currcons);
@@ -770,12 +649,12 @@ static void scrup(int currcons, unsigned int t, unsigned int b)
 
                while (count) {
                        count--;
-                       writew(readw(s++), d++);
+                       scr_writew(scr_readw(s++), d++);
                }
                count = video_num_columns;
                while (count) {
                        count--;
-                       writew(video_erase_char, d++);
+                       scr_writew(video_erase_char, d++);
                }
        }
 }
@@ -792,12 +671,12 @@ static void scrdown(int currcons, unsigned int t, unsigned int b)
        count = (b-t-1)*video_num_columns;
        while (count) {
                count--;
-               writew(readw(--s), --d);
+               scr_writew(scr_readw(--s), --d);
        }
        count = video_num_columns;
        while (count) {
                count--;
-               writew(video_erase_char, --d);
+               scr_writew(video_erase_char, --d);
        }
        has_scrolled = 1;
 }
@@ -873,7 +752,7 @@ static void csi_J(int currcons, int vpar)
        }
        while (count) {
                count--;
-               writew(video_erase_char, start++);
+               scr_writew(video_erase_char, start++);
        }
        need_wrap = 0;
 }
@@ -901,7 +780,7 @@ static void csi_K(int currcons, int vpar)
        }
        while (count) {
                count--;
-               writew(video_erase_char, start++);
+               scr_writew(video_erase_char, start++);
        }
        need_wrap = 0;
 }
@@ -919,7 +798,7 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions
 
        while (count) {
                count--;
-               writew(video_erase_char, start++);
+               scr_writew(video_erase_char, start++);
        }
        need_wrap = 0;
 }
@@ -934,7 +813,7 @@ static void update_attr(int currcons)
                        attr = (attr & 0xf0) | halfcolor;
        }
        if (reverse ^ decscnm)
-               attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
+               attr = reverse_video_char(attr);
        if (blink)
                attr ^= 0x80;
        if (intensity == 2)
@@ -946,7 +825,7 @@ static void update_attr(int currcons)
                        attr = (attr & 0xf0) | 0x08;
        }
        if (decscnm)
-               video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
+               video_erase_char = (reverse_video_char(color) << 8) | ' ';
        else
                video_erase_char = (color << 8) | ' ';
 }
@@ -989,7 +868,7 @@ static void csi_m(int currcons)
                                  * control chars if defined, don't set
                                  * bit 8 on output.
                                  */
-                               translate = (charset == 0
+                               translate = set_translate(charset == 0
                                                ? G0_charset
                                                : G1_charset);
                                disp_ctrl = 0;
@@ -999,7 +878,7 @@ static void csi_m(int currcons)
                                  * Select first alternate font, let's
                                  * chars < 32 be displayed as ROM chars.
                                  */
-                               translate = NULL_TRANS;
+                               translate = set_translate(NULL_MAP);
                                disp_ctrl = 1;
                                toggle_meta = 0;
                                break;
@@ -1007,7 +886,7 @@ static void csi_m(int currcons)
                                  * Select second alternate font, toggle
                                  * high bit before displaying as ROM char.
                                  */
-                               translate = NULL_TRANS;
+                               translate = set_translate(NULL_MAP);
                                disp_ctrl = 1;
                                toggle_meta = 1;
                                break;
@@ -1072,9 +951,17 @@ static void cursor_report(int currcons, struct tty_struct * tty)
        respond_string(buf, tty);
 }
 
-#ifdef CONFIG_SELECTION
-static void mouse_report(int currcons, struct tty_struct * tty,
-                        int butt, int mrx, int mry)
+static inline void status_report(struct tty_struct * tty)
+{
+       respond_string("\033[0n", tty); /* Terminal ok */
+}
+
+static inline void respond_ID(struct tty_struct * tty)
+{
+       respond_string(VT102ID, tty);
+}
+
+void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
 {
        char buf[8];
 
@@ -1082,33 +969,85 @@ static void mouse_report(int currcons, struct tty_struct * tty,
                (char)('!' + mry));
        respond_string(buf, tty);
 }
-#endif
 
-static inline void status_report(int currcons, struct tty_struct * tty)
+/* invoked via ioctl(TIOCLINUX) */
+int mouse_reporting(void)
 {
-       respond_string("\033[0n", tty); /* Terminal ok */
+       int currcons = fg_console;
+
+       return report_mouse;
 }
 
-static inline void respond_ID(int currcons, struct tty_struct * tty)
+static inline unsigned short *screenpos(int currcons, int offset, int viewed)
 {
-       respond_string(VT102ID, tty);
+       unsigned short *p = (unsigned short *)(origin + offset);
+       if (viewed && currcons == fg_console)
+               p -= (__real_origin - __origin);
+       return p;
 }
 
-static void invert_screen(int currcons) {
+/* Note: inverting the screen twice should revert to the original state */
+void invert_screen(int currcons, int offset, int count, int viewed)
+{
        unsigned short *p;
 
+       count /= 2;
+       p = screenpos(currcons, offset, viewed);
        if (can_do_color)
-               for (p = (unsigned short *)origin; p < (unsigned short *)scr_end; p++) {
-                       unsigned short old = readw(p);
-                       writew((old & 0x88ff) | (((old >> 4) | ((old & 0xff00) << 4)) & 0x7700), p);
+               while (count--) {
+                       unsigned short old = scr_readw(p);
+                       scr_writew(reverse_video_short(old), p);
+                       p++;
                }
        else
-               for (p = (unsigned short *)origin; p < (unsigned short *)scr_end; p++) {
-                       unsigned short old = readw(p);
-                       writew(old ^ ((old & 0x0700 == 0x0100) ? 0x7000 : 0x7700), p);
+               while (count--) {
+                       unsigned short old = scr_readw(p);
+                       scr_writew(old ^ ((old & 0x0700 == 0x0100)
+                                         ? 0x7000 : 0x7700), p);
                }
 }
 
+/* used by selection: complement pointer position */
+void complement_pos(int currcons, int offset)
+{
+       static unsigned short *p = NULL;
+       static unsigned short old = 0;
+
+       if (p)
+               scr_writew(old, p);
+       if (offset == -1)
+               p = NULL;
+       else {
+               p = screenpos(currcons, offset, 1);
+               old = scr_readw(p);
+               scr_writew(old ^ 0x7700, p);
+       }
+}
+
+/* used by selection */
+unsigned short screen_word(int currcons, int offset, int viewed)
+{
+       return scr_readw(screenpos(currcons, offset, viewed));
+}
+
+/* used by vcs - note the word offset */
+unsigned short *screen_pos(int currcons, int w_offset, int viewed)
+{
+       return screenpos(currcons, 2 * w_offset, viewed);
+}
+
+void getconsxy(int currcons, char *p)
+{
+       p[0] = x;
+       p[1] = y;
+}
+
+void putconsxy(int currcons, char *p)
+{
+       gotoxy(currcons, p[0], p[1]);
+       set_cursor(currcons);
+}
+
 static void set_mode(int currcons, int on_off)
 {
        int i;
@@ -1132,7 +1071,7 @@ static void set_mode(int currcons, int on_off)
                        case 5:                 /* Inverted screen on/off */
                                if (decscnm != on_off) {
                                        decscnm = on_off;
-                                       invert_screen(currcons);
+                                       invert_screen(currcons, 0, video_screen_size, 0);
                                        update_attr(currcons);
                                }
                                break;
@@ -1211,8 +1150,8 @@ static void insert_char(int currcons)
        unsigned short * p = (unsigned short *) pos;
 
        while (i++ < video_num_columns) {
-               tmp = readw(p);
-               writew(old, p);
+               tmp = scr_readw(p);
+               scr_writew(old, p);
                old = tmp;
                p++;
        }
@@ -1231,10 +1170,10 @@ static void delete_char(int currcons)
        unsigned short * p = (unsigned short *) pos;
 
        while (++i < video_num_columns) {
-               writew(readw(p+1), p);
+               scr_writew(scr_readw(p+1), p);
                p++;
        }
-       writew(video_erase_char, p);
+       scr_writew(video_erase_char, p);
        need_wrap = 0;
 }
 
@@ -1309,7 +1248,7 @@ static void restore_cur(int currcons)
        color           = s_color;
        G0_charset      = saved_G0;
        G1_charset      = saved_G1;
-       translate       = charset ? G1_charset : G0_charset;
+       translate       = set_translate(charset ? G1_charset : G0_charset);
        update_attr(currcons);
        need_wrap = 0;
 }
@@ -1323,9 +1262,9 @@ static void reset_terminal(int currcons, int do_clear)
        bottom          = video_num_lines;
        vc_state        = ESnormal;
        ques            = 0;
-       translate       = NORM_TRANS;
-       G0_charset      = NORM_TRANS;
-       G1_charset      = GRAF_TRANS;
+       translate       = set_translate(NORM_MAP);
+       G0_charset      = NORM_MAP;
+       G1_charset      = GRAF_MAP;
        charset         = 0;
        need_wrap       = 0;
        report_mouse    = 0;
@@ -1412,11 +1351,10 @@ static int con_write(struct tty_struct * tty, int from_user,
            }
            return 0;
        }
-#ifdef CONFIG_SELECTION
-       /* clear the selection */
+
        if (currcons == sel_cons)
                clear_selection();
-#endif /* CONFIG_SELECTION */
+
        disable_bh(KEYBOARD_BH);
        while (!tty->stopped && count) {
                c = from_user ? get_fs_byte(buf) : *buf;
@@ -1426,7 +1364,6 @@ static int con_write(struct tty_struct * tty, int from_user,
                    /* 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--;
@@ -1448,18 +1385,15 @@ static int con_write(struct tty_struct * tty, int from_user,
                        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];
+                   tc = conv_uni_to_pc(c);
+                   if (tc == -1 || tc == -2)
+                     continue;
+                   if (tc == -3 || tc == -4) { /* hashtable not valid */
+                                               /* or symbol not found */
+                       tc = (c <= 0xff) ? translate[c] : 040;
                        ok = 0;
-                   }
+                   } else
+                       ok = 1;
                } else {        /* no utf */
                    tc = translate[toggle_meta ? (c|0x80) : c];
                    ok = 0;
@@ -1483,7 +1417,7 @@ static int con_write(struct tty_struct * tty, int from_user,
                        }
                        if (decim)
                                insert_char(currcons);
-                       writew((attr << 8) + tc, (unsigned short *) pos);
+                       scr_writew((attr << 8) + tc, (unsigned short *) pos);
                        if (x == video_num_columns - 1)
                                need_wrap = decawm;
                        else {
@@ -1522,12 +1456,12 @@ static int con_write(struct tty_struct * tty, int from_user,
                                continue;
                        case 14:
                                charset = 1;
-                               translate = G1_charset;
+                               translate = set_translate(G1_charset);
                                disp_ctrl = 1;
                                continue;
                        case 15:
                                charset = 0;
-                               translate = G0_charset;
+                               translate = set_translate(G0_charset);
                                disp_ctrl = 0;
                                continue;
                        case 24: case 26:
@@ -1567,7 +1501,7 @@ static int con_write(struct tty_struct * tty, int from_user,
                                        tab_stop[x >> 5] |= (1 << (x & 31));
                                        continue;
                                  case 'Z':
-                                       respond_ID(currcons,tty);
+                                       respond_ID(tty);
                                        continue;
                                  case '7':
                                        save_cur(currcons);
@@ -1628,7 +1562,7 @@ static int con_write(struct tty_struct * tty, int from_user,
                                        case 'n':
                                                if (!ques)
                                                        if (par[0] == 5)
-                                                               status_report(currcons,tty);
+                                                               status_report(tty);
                                                        else if (par[0] == 6)
                                                                cursor_report(currcons,tty);
                                                continue;
@@ -1692,7 +1626,7 @@ static int con_write(struct tty_struct * tty, int from_user,
                                                continue;
                                        case 'c':
                                                if (!par[0])
-                                                       respond_ID(currcons,tty);
+                                                       respond_ID(tty);
                                                continue;
                                        case 'g':
                                                if (!par[0])
@@ -1775,28 +1709,28 @@ static int con_write(struct tty_struct * tty, int from_user,
                                continue;
                        case ESsetG0:
                                if (c == '0')
-                                       G0_charset = GRAF_TRANS;
+                                       G0_charset = GRAF_MAP;
                                else if (c == 'B')
-                                       G0_charset = NORM_TRANS;
+                                       G0_charset = NORM_MAP;
                                else if (c == 'U')
-                                       G0_charset = NULL_TRANS;
+                                       G0_charset = NULL_MAP;
                                else if (c == 'K')
-                                       G0_charset = USER_TRANS;
+                                       G0_charset = USER_MAP;
                                if (charset == 0)
-                                       translate = G0_charset;
+                                       translate = set_translate(G0_charset);
                                vc_state = ESnormal;
                                continue;
                        case ESsetG1:
                                if (c == '0')
-                                       G1_charset = GRAF_TRANS;
+                                       G1_charset = GRAF_MAP;
                                else if (c == 'B')
-                                       G1_charset = NORM_TRANS;
+                                       G1_charset = NORM_MAP;
                                else if (c == 'U')
-                                       G1_charset = NULL_TRANS;
+                                       G1_charset = NULL_MAP;
                                else if (c == 'K')
-                                       G1_charset = USER_TRANS;
+                                       G1_charset = USER_MAP;
                                if (charset == 1)
-                                       translate = G1_charset;
+                                       translate = set_translate(G1_charset);
                                vc_state = ESnormal;
                                continue;
                        default:
@@ -1859,7 +1793,7 @@ void console_print(const char * b)
                        if (c == 10 || c == 13)
                                continue;
                }
-               writew((attr << 8) + c, (unsigned short *) pos);
+               scr_writew((attr << 8) + c, (unsigned short *) pos);
                if (x == video_num_columns - 1) {
                        need_wrap = 1;
                        continue;
@@ -2189,9 +2123,9 @@ void update_screen(int new_console)
                return;
        }
        lock = 1;
-#ifdef CONFIG_SELECTION
+
        clear_selection();
-#endif /* CONFIG_SELECTION */
+
        if (!console_blanked)
                get_scrmem(fg_console);
        else
@@ -2206,59 +2140,6 @@ void update_screen(int new_console)
        lock = 0;
 }
 
-/*
- * do_screendump is used for three tasks:
- *   if (mode==0) is the old ioctl(TIOCLINUX,0)
- *   if (mode==1) dumps wd,hg, cursor position, and all the char-attr pairs
- *   if (mode==2) restores what mode1 got.
- * the new modes are needed for a fast and complete dump-restore cycle,
- * needed to implement root-window menus in text mode (A Rubini Nov 1994)
- */
-int do_screendump(unsigned long arg, int mode)
-{
-       char *sptr, *buf = (char *)arg;
-       int currcons, l, chcount;
-
-       l = verify_area(VERIFY_READ, buf, 2);
-       if (l)
-               return l;
-       currcons = get_fs_byte(buf+1);
-       currcons = (currcons ? currcons-1 : fg_console);
-       if (!vc_cons_allocated(currcons))
-               return -EIO;
-       
-       /* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */
-       chcount=video_num_columns*video_num_lines;
-       l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE,
-               buf, (2+chcount)*(mode ? 2 : 1));
-       if (l)
-               return l;
-       if (mode<2) {
-       put_fs_byte((char)(video_num_lines),buf++);   
-       put_fs_byte((char)(video_num_columns),buf++);
-           }
-#ifdef CONFIG_SELECTION
-       clear_selection();
-#endif
-       switch(mode) {
-           case 0:
-                       sptr = (char *) origin;
-                       for (l=chcount; l>0 ; l--, sptr++)
-                               put_fs_byte(*sptr++,buf++);     
-                       break;
-           case 1:
-                       put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++);
-/*XXX*/                        memcpy_tofs(buf,(char *)origin,2*chcount);
-                       break;
-           case 2:
-                       gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3));
-                       buf+=4; /* ioctl#, console#, x,y */
-/*XXX*/                        memcpy_fromfs((char *)origin,buf,2*chcount);
-                       break;
-           }
-       return(0);
-}
-
 /*
  * Allocate the console screen memory.
  */
@@ -2283,289 +2164,6 @@ int con_open(struct tty_struct *tty, struct file * filp)
        return 0;
 }
 
-#ifdef CONFIG_SELECTION
-/* correction factor for when screen is hardware-scrolled */
-#define        hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
-
-/* set reverse video on characters s-e of console with selection. */
-static void highlight(const int currcons, const int s, const int e)
-{
-       unsigned char *p, *p1, *p2;
-
-       p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
-       p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
-
-       for (p = p1; p <= p2; p += 2)
-               *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
-}
-
-/* use complementary color to show the pointer */
-static void highlight_pointer(const int currcons, const int where)
-{
-       unsigned char *p;
-       static unsigned char *prev=NULL;
-
-       if (where==-1) /* remove the pointer */
-       {
-               if (prev)
-               {
-                       *prev ^= 0x77;
-                       prev=NULL;
-               }
-       }
-       else
-       {
-               p = (unsigned char *)origin - hwscroll_offset + where + 1;
-               *p ^= 0x77;
-               if (prev) *prev ^= 0x77; /* remove the previous one */
-               prev=p;
-       }
-}
-
-
-/*
- * This function uses a 128-bit look up table
- * WARNING: This depends on both endianness and the ascii code
- */
-static unsigned long inwordLut[4]={
-  0x00000000, /* control chars     */
-  0x03FF0000, /* digits            */
-  0x87FFFFFE, /* uppercase and '_' */
-  0x07FFFFFE  /* lowercase         */
-};
-static inline int inword(const char c) {
-   return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
-}
-
-/* set inwordLut contents. Invoked by ioctl(). */
-int sel_loadlut(const int arg)
-{
-    memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
-    return 0;
-}
-
-/* does screen address p correspond to character at LH/RH edge of screen? */
-static inline int atedge(const int p)
-{
-       return (!(p % video_size_row) || !((p + 2) % video_size_row));
-}
-
-/* constrain v such that v <= u */
-static inline unsigned short limit(const unsigned short v, const unsigned short u)
-{
-/* gcc miscompiles the ?: operator, so don't use it.. */
-       if (v > u)
-               return u;
-       return v;
-}
-
-/* invoked via ioctl(TIOCLINUX) */
-int mouse_reporting(void)
-{
-       int currcons = fg_console;
-
-       return report_mouse;
-}
-
-/* set the current selection. Invoked by ioctl(). */
-int set_selection(const int arg, struct tty_struct *tty)
-{
-       unsigned short *args, xs, ys, xe, ye;
-       int currcons = fg_console;
-       int sel_mode, new_sel_start, new_sel_end, spc;
-       char *bp, *obp, *spos;
-       int i, ps, pe;
-       char *off = (char *)origin - hwscroll_offset;
-
-       unblank_screen();
-       args = (unsigned short *)(arg + 1);
-       xs = get_fs_word(args++) - 1;
-       ys = get_fs_word(args++) - 1;
-       xe = get_fs_word(args++) - 1;
-       ye = get_fs_word(args++) - 1;
-       sel_mode = get_fs_word(args);
-
-       xs = limit(xs, video_num_columns - 1);
-       ys = limit(ys, video_num_lines - 1);
-       xe = limit(xe, video_num_columns - 1);
-       ye = limit(ye, video_num_lines - 1);
-       ps = ys * video_size_row + (xs << 1);
-       pe = ye * video_size_row + (xe << 1);
-
-       if (report_mouse && (sel_mode & 16)) {
-               mouse_report(currcons, tty, sel_mode & 15, xs, ys);
-               return 0;
-       }
-
-       if (ps > pe)    /* make sel_start <= sel_end */
-       {
-               int tmp = ps;
-               ps = pe;
-               pe = tmp;
-       }
-
-       switch (sel_mode)
-       {
-               case 0: /* character-by-character selection */
-                       new_sel_start = ps;
-                       new_sel_end = pe;
-                       break;
-               case 1: /* word-by-word selection */
-                       spc = isspace(*(off + ps));
-                       for (new_sel_start = ps; ; ps -= 2)
-                       {
-                               if ((spc && !isspace(*(off + ps))) ||
-                                   (!spc && !inword(*(off + ps))))
-                                       break;
-                               new_sel_start = ps;
-                               if (!(ps % video_size_row))
-                                       break;
-                       }
-                       spc = isspace(*(off + pe));
-                       for (new_sel_end = pe; ; pe += 2)
-                       {
-                               if ((spc && !isspace(*(off + pe))) ||
-                                   (!spc && !inword(*(off + pe))))
-                                       break;
-                               new_sel_end = pe;
-                               if (!((pe + 2) % video_size_row))
-                                       break;
-                       }
-                       break;
-               case 2: /* line-by-line selection */
-                       new_sel_start = ps - ps % video_size_row;
-                       new_sel_end = pe + video_size_row
-                                   - pe % video_size_row - 2;
-                       break;
-               case 3: /* pointer highlight */
-                       if (sel_cons != currcons)
-                       {
-                               clear_selection();
-                               sel_cons = currcons;
-                       }
-                       highlight_pointer(sel_cons,pe);
-                       return 0; /* nothing more */
-               default:
-                       return -EINVAL;
-       }
-       /* remove the pointer */
-       highlight_pointer(sel_cons,-1);
-       /* select to end of line if on trailing space */
-       if (new_sel_end > new_sel_start &&
-               !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
-       {
-               for (pe = new_sel_end + 2; ; pe += 2)
-               {
-                       if (!isspace(*(off + pe)) || atedge(pe))
-                               break;
-               }
-               if (isspace(*(off + pe)))
-                       new_sel_end = pe;
-       }
-       if (sel_cons != currcons)
-       {
-               clear_selection();
-               sel_cons = currcons;
-       }
-       if (sel_start == -1)    /* no current selection */
-               highlight(sel_cons, new_sel_start, new_sel_end);
-       else if (new_sel_start == sel_start)
-       {
-               if (new_sel_end == sel_end)     /* no action required */
-                       return 0;
-               else if (new_sel_end > sel_end) /* extend to right */
-                       highlight(sel_cons, sel_end + 2, new_sel_end);
-               else                            /* contract from right */
-                       highlight(sel_cons, new_sel_end + 2, sel_end);
-       }
-       else if (new_sel_end == sel_end)
-       {
-               if (new_sel_start < sel_start)  /* extend to left */
-                       highlight(sel_cons, new_sel_start, sel_start - 2);
-               else                            /* contract from left */
-                       highlight(sel_cons, sel_start, new_sel_start - 2);
-       }
-       else    /* some other case; start selection from scratch */
-       {
-               clear_selection();
-               highlight(sel_cons, new_sel_start, new_sel_end);
-       }
-       sel_start = new_sel_start;
-       sel_end = new_sel_end;
-
-       /* realloc the buffer (it seems to be efficient, anyway) */
-       if (sel_buffer) kfree(sel_buffer);
-       sel_buffer = kmalloc((sel_end-sel_start)/2+2, GFP_KERNEL);
-       if (!sel_buffer)
-       {
-               printk("selection: kmalloc() failed\n");
-               clear_selection();
-               return (0); /* is it right? */
-       }
-       obp = bp = sel_buffer;
-       for (i = sel_start; i <= sel_end; i += 2)
-       {
-               spos = (char *)off + i;
-               *bp++ = *spos;
-               if (!isspace(*spos))
-                       obp = bp;
-               if (! ((i + 2) % video_size_row))
-               {
-                       /* strip trailing blanks from line and add newline,
-                          unless non-space at end of line. */
-                       if (obp != bp)
-                       {
-                               bp = obp;
-                               *bp++ = '\r';
-                       }
-                       obp = bp;
-               }
-       }
-       *bp = '\0';
-       return 0;
-}
-
-/* insert the contents of the selection buffer into the queue of the
-   tty associated with the current console. Invoked by ioctl(). */
-int paste_selection(struct tty_struct *tty)
-{
-       struct wait_queue wait = { current, NULL };
-       char    *bp = sel_buffer;
-       int     c, l;
-       struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
-       
-       if (!bp || !bp[0])
-               return 0;
-       unblank_screen();
-       c = strlen(sel_buffer);
-       current->state = TASK_INTERRUPTIBLE;
-       add_wait_queue(&vt->paste_wait, &wait);
-       while (c) {
-               if (test_bit(TTY_THROTTLED, &tty->flags)) {
-                       schedule();
-                       continue;
-               }
-               l = MIN(c, tty->ldisc.receive_room(tty));
-               tty->ldisc.receive_buf(tty, bp, 0, l);
-               c -= l;
-               bp += l;
-       }
-       current->state = TASK_RUNNING;
-       return 0;
-}
-
-/* remove the current selection highlight, if any, from the console holding
-   the selection. */
-static void clear_selection()
-{
-       highlight_pointer(sel_cons, -1); /* hide the pointer */
-       if (sel_start != -1)
-       {
-               highlight(sel_cons, sel_start, sel_end);
-               sel_start = -1;
-       }
-}
-#endif /* CONFIG_SELECTION */
 
 /*
  * PIO_FONT support.
@@ -2668,6 +2266,7 @@ static int set_get_font(char * arg, int set)
 
 int con_set_font (char *arg)
 {
+       hashtable_contents_valid = 0;
        return set_get_font (arg,1);
 }
 
@@ -2675,36 +2274,3 @@ int con_get_font (char *arg)
 {
        return set_get_font (arg,0);
 }
-
-/*
- * Load customizable translation table (USER_TRANS[]). All checks are here,
- * so we need only include 'return con_set_trans(arg)' in the ioctl handler
- * arg points to a 256 byte translation table.
- */
-int con_set_trans(char * arg)
-{
-       int i;
-
-       i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
-       if (i)
-               return i;
-
-       for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
-       USER_TRANS[012]=0;
-       USER_TRANS[014]=0;
-       USER_TRANS[015]=0;
-       USER_TRANS[033]=0;
-       return 0;
-}
-
-int con_get_trans(char * arg)
-{
-       int i;
-
-       i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
-       if (i)
-               return i;
-
-       for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
-       return 0;
-}
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
new file mode 100644 (file)
index 0000000..54c2d19
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * consolemap.c
+ *
+ * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
+ * to font positions.
+ *
+ * aeb, 950210
+ */
+
+#include <linux/kd.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <asm/segment.h>
+#include "consolemap.h"
+
+static unsigned char * translations[] = {
+/* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
+(unsigned char *)
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
+       " !\"#$%&'()*+,-./0123456789:;<=>?"
+       "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+       "`abcdefghijklmnopqrstuvwxyz{|}~\0"
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
+       "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
+       "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
+       "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
+       "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
+       "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
+/* vt100 graphics */
+(unsigned char *)
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
+       " !\"#$%&'()*+,-./0123456789:;<=>?"
+       "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
+       "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
+       "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+       "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
+       "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
+       "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
+       "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
+       "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
+       "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
+/* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
+(unsigned char *)
+       "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
+       "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
+       "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
+       "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
+       "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
+       "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
+       "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
+       "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
+       "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+       "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+       "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+       "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+       "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+       "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+       "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
+       "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
+ /* USER: customizable mappings, initialized as the previous one (IBM) */
+(unsigned char *)
+       "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
+       "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
+       "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
+       "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
+       "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
+       "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
+       "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
+       "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
+       "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+       "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+       "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+       "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+       "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+       "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+       "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
+       "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+};
+
+/* the above mappings are not invertible - this is just a best effort */
+static unsigned char * inv_translate = NULL;
+static unsigned char inv_norm_transl[E_TABSZ];
+static unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
+
+static void set_inverse_transl(int i)
+{
+       int j;
+       unsigned char *p = translations[i];
+       unsigned char *q = inverse_translations[i];
+
+       if (!q) {
+               /* slightly messy to avoid calling kmalloc too early */
+               q = inverse_translations[i] = ((i == NORM_MAP)
+                       ? inv_norm_transl
+                       : (unsigned char *) kmalloc(E_TABSZ, GFP_KERNEL));
+               if (!q)
+                       return;
+       }
+       for (j=0; j<E_TABSZ; j++)
+               q[j] = 0;
+       for (j=0; j<E_TABSZ; j++)
+               if (q[p[j]] < 32)       /* prefer '-' above SHY etc. */
+                       q[p[j]] = j;
+}
+
+unsigned char *set_translate(int m)
+{
+       if (!inverse_translations[m])
+               set_inverse_transl(m);
+       inv_translate = inverse_translations[m];
+       return translations[m];
+}
+
+/*
+ * Inverse translation is impossible for several reasons:
+ * 1. The translation maps are not 1-1
+ * 2. The text may have been written while a different translation map
+ *    was active
+ * Still, it is now possible to a certain extent to cut and paste non-ASCII.
+ */
+unsigned char inverse_translate(unsigned char c) {
+       return ((inv_translate && inv_translate[c]) ? inv_translate[c] : c);
+}
+
+/*
+ * Load customizable translation table
+ * arg points to a 256 byte translation table.
+ */
+int con_set_trans(char * arg)
+{
+       int i;
+       unsigned char *p = translations[USER_MAP];
+
+       i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
+       if (i)
+               return i;
+
+       for (i=0; i<E_TABSZ ; i++)
+               p[i] = get_fs_byte(arg+i);
+       p[012] = p[014] = p[015] = p[033] = 0;
+       set_inverse_transl(USER_MAP);
+       return 0;
+}
+
+int con_get_trans(char * arg)
+{
+       int i;
+       unsigned char *p = translations[USER_MAP];
+
+       i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
+       if (i)
+               return i;
+
+       for (i=0; i<E_TABSZ ; i++) put_fs_byte(p[i],arg+i);
+       return 0;
+}
+
+/*
+ * Unicode -> current font conversion 
+ *
+ * A font has at most 512 chars, usually 256.
+ * But one font position may represent several Unicode chars
+ * (and moreover, hashtables work best when they are not too full),
+ * so pick HASHSIZE somewhat larger than 512.
+ * Since there are likely to be long consecutive stretches
+ * (like U+0000 to U+00FF), HASHSTEP should not be too small.
+ * Searches longer than MAXHASHLEVEL steps are refused, unless
+ * requested explicitly.
+ *
+ * Note: no conversion tables are compiled in, so the user
+ * must supply an explicit mapping herself. See kbd-0.90 (or an
+ * earlier kernel version) for the default Unicode-to-PC mapping.
+ * Usually, the mapping will be loaded simultaneously with the font.
+ */
+
+#define HASHSIZE   641
+#define HASHSTEP   189         /* yields hashlevel = 3 initially */
+#define MAXHASHLEVEL 6
+static struct unipair hashtable[HASHSIZE];
+
+int hashtable_contents_valid = 0;      /* cleared by setfont */
+
+static unsigned int hashsize;
+static unsigned int hashstep;
+static unsigned int hashlevel;
+static unsigned int maxhashlevel;
+
+void
+con_clear_unimap(struct unimapinit *ui) {
+       int i;
+
+       /* read advisory values for hash algorithm */
+       hashsize = ui->advised_hashsize;
+       if (hashsize < 256 || hashsize > HASHSIZE)
+         hashsize = HASHSIZE;
+       hashstep = (ui->advised_hashstep % hashsize);
+       if (hashstep < 64)
+         hashstep = HASHSTEP;
+       maxhashlevel = ui->advised_hashlevel;
+       if (!maxhashlevel)
+         maxhashlevel = MAXHASHLEVEL;
+       if (maxhashlevel > hashsize)
+         maxhashlevel = hashsize;
+
+       /* initialize */
+       hashlevel = 0;
+       for (i=0; i<hashsize; i++)
+         hashtable[i].unicode = 0xffff;
+       hashtable_contents_valid = 1;
+}
+
+int
+con_set_unimap(ushort ct, struct unipair *list){
+       int i, lct;
+       ushort u, hu;
+       struct unimapinit hashdefaults = { 0, 0, 0 };
+
+       if (!hashtable_contents_valid)
+         con_clear_unimap(&hashdefaults);
+       while(ct) {
+           u = get_fs_word(&list->unicode);
+           i = u % hashsize;
+           lct = 1;
+           while ((hu = hashtable[i].unicode) != 0xffff && hu != u) {
+               if (lct++ >=  maxhashlevel)
+                 return -ENOMEM;
+               i += hashstep;
+               if (i >= hashsize)
+                 i -= hashsize;
+           }
+           if (lct > hashlevel)
+             hashlevel = lct;
+           hashtable[i].unicode = u;
+           hashtable[i].fontpos = get_fs_word(&list->fontpos);
+           list++;
+           ct--;
+       }
+       return 0;
+}
+
+int
+con_get_unimap(ushort ct, ushort *uct, struct unipair *list){
+       int i, ect;
+
+       ect = 0;
+       if (hashtable_contents_valid)
+         for (i = 0; i<hashsize; i++)
+           if (hashtable[i].unicode != 0xffff) {
+               if (ect++ < ct) {
+                   put_fs_word(hashtable[i].unicode, &list->unicode);
+                   put_fs_word(hashtable[i].fontpos, &list->fontpos);
+                   list++;
+               }
+           }
+       put_fs_word(ect, uct);
+       return ((ect <= ct) ? 0 : -ENOMEM);
+}
+
+int
+conv_uni_to_pc(unsigned long ucs) {
+      int i, h;
+
+      if (!hashtable_contents_valid || ucs < 0x20)
+       return -3;
+      if (ucs == 0xffff || ucs == 0xfffe)
+       return -1;
+      if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
+       return -2;
+      
+      h = ucs % hashsize;
+      for (i = 0; i < hashlevel; i++) {
+         if (hashtable[h].unicode == ucs)
+           return hashtable[h].fontpos;
+         if ((h += hashstep) >= hashsize)
+           h -= hashsize;
+      }
+
+      return -4;               /* not found */
+}
diff --git a/drivers/char/consolemap.h b/drivers/char/consolemap.h
new file mode 100644 (file)
index 0000000..f0a2a91
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * consolemap.h
+ *
+ * Interface between console.c, selection.c  and consolemap.c
+ */
+#define NORM_MAP 0
+#define GRAF_MAP 1
+#define NULL_MAP 2
+#define USER_MAP 3
+
+extern int hashtable_contents_valid;
+extern unsigned char inverse_translate(unsigned char c);
+extern unsigned char *set_translate(int m);
index 09d0b6c17efb35afcca4a14991c9706cc1420930..b23fa1ed847a2b8ca8b6df1287028030cbe7ce32 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/interrupt.h>
 #include <linux/keyboard.h>
 
+extern int shift_state;
+
 extern char *func_table[MAX_NR_FUNC];
 extern char func_buf[];
 extern char *funcbufptr;
index a340ee9927d1054d77c8971f807cadd025f8cbb1..28002703b84db955cec38ad6f739868076defece 100644 (file)
@@ -370,25 +370,29 @@ static void keyboard_interrupt(int irq, struct pt_regs *regs)
                prev_scancode = 0;
                goto end_kbd_intr;
        }
+
+       tty = ttytab[fg_console];
+       kbd = kbd_table + fg_console;
+       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
+                  values when finishing RAW mode or when changing VT's */
+       }
+
        if (scancode == 0xff) {
+               /* in scancode mode 1, my ESC key generates 0xff */
                /* the calculator keys on a FOCUS 9000 generate 0xff */
 #ifndef KBD_IS_FOCUS_9000
 #ifdef KBD_REPORT_ERR
-               printk("keyboard error\n");
+               if (!raw_mode)
+                 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 = (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
-                  values when finishing RAW mode or when changing VT's */
-       }
        if (scancode == 0xe0 || scancode == 0xe1) {
                prev_scancode = scancode;
                goto end_kbd_intr;
@@ -414,7 +418,8 @@ static void keyboard_interrupt(int irq, struct pt_regs *regs)
                  prev_scancode = 0;
              } else {
 #ifdef KBD_REPORT_UNKN
-                 printk("keyboard: unknown e1 escape sequence\n");
+                 if (!raw_mode)
+                   printk("keyboard: unknown e1 escape sequence\n");
 #endif
                  prev_scancode = 0;
                  goto end_kbd_intr;
@@ -729,7 +734,7 @@ static void SAK(void)
         * work.
         */
        reset_vc(fg_console);
-       unblank_screen();       /* not in interrupt routine? */
+       do_unblank_screen();    /* not in interrupt routine? */
 #endif
 }
 
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
new file mode 100644 (file)
index 0000000..a44b44e
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * linux/drivers/char/selection.c
+ *
+ * This module exports the functions:
+ *
+ *     'int set_selection(const int arg)'
+ *     'void clear_selection(void)'
+ *     'int paste_selection(struct tty_struct *tty)'
+ *     'int sel_loadlut(const int arg)'
+ *
+ * Now that /dev/vcs exists, most of this can disappear again.
+ */
+
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include "vt_kern.h"
+#include "consolemap.h"
+#include "selection.h"
+
+#ifndef MIN
+#define MIN(a,b)       ((a) < (b) ? (a) : (b))
+#endif
+
+/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
+#define isspace(c)     ((c) == ' ')
+
+/* Variables for selection control. */
+/* Use a dynamic buffer, instead of static (Dec 1994) */
+       int sel_cons = 0;               /* must not be disallocated */
+static volatile int sel_start = -1;    /* cleared by clear_selection */
+static int sel_end;
+static int sel_buffer_lth = 0;
+static char *sel_buffer = NULL;
+
+#define sel_pos(n)     inverse_translate(screen_word(sel_cons, n, 1) & 0xff)
+
+/* clear_selection, highlight and highlight_pointer can be called
+   from interrupt (via scrollback/front) */
+
+/* set reverse video on characters s-e of console with selection. */
+inline static void
+highlight(const int s, const int e) {
+       invert_screen(sel_cons, s, e-s+2, 1);
+}
+
+/* use complementary color to show the pointer */
+inline static void
+highlight_pointer(const int where) {
+       complement_pos(sel_cons, where);
+}
+
+/* remove the current selection highlight, if any,
+   from the console holding the selection. */
+void
+clear_selection(void) {
+       highlight_pointer(-1); /* hide the pointer */
+       if (sel_start != -1) {
+               highlight(sel_start, sel_end);
+               sel_start = -1;
+       }
+}
+
+/*
+ * User settable table: what characters are to be considered alphabetic?
+ * 256 bits
+ */
+static unsigned long inwordLut[8]={
+  0x00000000, /* control chars     */
+  0x03FF0000, /* digits            */
+  0x87FFFFFE, /* uppercase and '_' */
+  0x07FFFFFE, /* lowercase         */
+  0x00000000,
+  0x00000000,
+  0xFF7FFFFF, /* latin-1 accented letters, not multiplication sign */
+  0xFF7FFFFF  /* latin-1 accented letters, not division sign */
+};
+
+static inline int inword(const unsigned char c) {
+       return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+}
+
+/* set inwordLut contents. Invoked by ioctl(). */
+int sel_loadlut(const int arg)
+{
+       int i = verify_area(VERIFY_READ, (char *) arg, 36);
+       if (i)
+               return i;
+       memcpy_fromfs(inwordLut, (unsigned long *)(arg+4), 32);
+       return 0;
+}
+
+/* does screen address p correspond to character at LH/RH edge of screen? */
+static inline int atedge(const int p)
+{
+       return (!(p % video_size_row) || !((p + 2) % video_size_row));
+}
+
+/* constrain v such that v <= u */
+static inline unsigned short limit(const unsigned short v, const unsigned short u)
+{
+/* gcc miscompiles the ?: operator, so don't use it.. */
+       if (v > u)
+               return u;
+       return v;
+}
+
+/* set the current selection. Invoked by ioctl(). */
+int set_selection(const int arg, struct tty_struct *tty)
+{
+       int sel_mode, new_sel_start, new_sel_end, spc;
+       char *bp, *obp;
+       int i, ps, pe;
+
+       do_unblank_screen();
+
+       { unsigned short *args, xs, ys, xe, ye;
+
+         args = (unsigned short *)(arg + 1);
+         xs = get_fs_word(args++) - 1;
+         ys = get_fs_word(args++) - 1;
+         xe = get_fs_word(args++) - 1;
+         ye = get_fs_word(args++) - 1;
+         sel_mode = get_fs_word(args);
+
+         xs = limit(xs, video_num_columns - 1);
+         ys = limit(ys, video_num_lines - 1);
+         xe = limit(xe, video_num_columns - 1);
+         ye = limit(ye, video_num_lines - 1);
+         ps = ys * video_size_row + (xs << 1);
+         pe = ye * video_size_row + (xe << 1);
+
+         if (sel_mode == 4) {
+             /* useful for screendump without selection highlights */
+             clear_selection();
+             return 0;
+         }
+
+         if (mouse_reporting() && (sel_mode & 16)) {
+             mouse_report(tty, sel_mode & 15, xs, ys);
+             return 0;
+         }
+        }
+
+       if (ps > pe)    /* make sel_start <= sel_end */
+       {
+               int tmp = ps;
+               ps = pe;
+               pe = tmp;
+       }
+
+       if (sel_cons != fg_console) {
+               clear_selection();
+               sel_cons = fg_console;
+       }
+
+       switch (sel_mode)
+       {
+               case 0: /* character-by-character selection */
+                       new_sel_start = ps;
+                       new_sel_end = pe;
+                       break;
+               case 1: /* word-by-word selection */
+                       spc = isspace(sel_pos(ps));
+                       for (new_sel_start = ps; ; ps -= 2)
+                       {
+                               if ((spc && !isspace(sel_pos(ps))) ||
+                                   (!spc && !inword(sel_pos(ps))))
+                                       break;
+                               new_sel_start = ps;
+                               if (!(ps % video_size_row))
+                                       break;
+                       }
+                       spc = isspace(sel_pos(pe));
+                       for (new_sel_end = pe; ; pe += 2)
+                       {
+                               if ((spc && !isspace(sel_pos(pe))) ||
+                                   (!spc && !inword(sel_pos(pe))))
+                                       break;
+                               new_sel_end = pe;
+                               if (!((pe + 2) % video_size_row))
+                                       break;
+                       }
+                       break;
+               case 2: /* line-by-line selection */
+                       new_sel_start = ps - ps % video_size_row;
+                       new_sel_end = pe + video_size_row
+                                   - pe % video_size_row - 2;
+                       break;
+               case 3:
+                       highlight_pointer(pe);
+                       return 0;
+               default:
+                       return -EINVAL;
+       }
+
+       /* remove the pointer */
+       highlight_pointer(-1);
+
+       /* select to end of line if on trailing space */
+       if (new_sel_end > new_sel_start &&
+               !atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) {
+               for (pe = new_sel_end + 2; ; pe += 2)
+                       if (!isspace(sel_pos(pe)) || atedge(pe))
+                               break;
+               if (isspace(sel_pos(pe)))
+                       new_sel_end = pe;
+       }
+       if (sel_start == -1)    /* no current selection */
+               highlight(new_sel_start, new_sel_end);
+       else if (new_sel_start == sel_start)
+       {
+               if (new_sel_end == sel_end)     /* no action required */
+                       return 0;
+               else if (new_sel_end > sel_end) /* extend to right */
+                       highlight(sel_end + 2, new_sel_end);
+               else                            /* contract from right */
+                       highlight(new_sel_end + 2, sel_end);
+       }
+       else if (new_sel_end == sel_end)
+       {
+               if (new_sel_start < sel_start)  /* extend to left */
+                       highlight(new_sel_start, sel_start - 2);
+               else                            /* contract from left */
+                       highlight(sel_start, new_sel_start - 2);
+       }
+       else    /* some other case; start selection from scratch */
+       {
+               clear_selection();
+               highlight(new_sel_start, new_sel_end);
+       }
+       sel_start = new_sel_start;
+       sel_end = new_sel_end;
+
+       if (sel_buffer)
+               kfree(sel_buffer);
+       sel_buffer = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+       if (!sel_buffer) {
+               printk("selection: kmalloc() failed\n");
+               clear_selection();
+               return -ENOMEM;
+       }
+
+       obp = bp = sel_buffer;
+       for (i = sel_start; i <= sel_end; i += 2) {
+               *bp = sel_pos(i);
+               if (!isspace(*bp++))
+                       obp = bp;
+               if (! ((i + 2) % video_size_row)) {
+                       /* strip trailing blanks from line and add newline,
+                          unless non-space at end of line. */
+                       if (obp != bp) {
+                               bp = obp;
+                               *bp++ = '\r';
+                       }
+                       obp = bp;
+               }
+       }
+       sel_buffer_lth = bp - sel_buffer;
+       return 0;
+}
+
+/* Insert the contents of the selection buffer into the queue of the
+   tty associated with the current console. Invoked by ioctl(). */
+int paste_selection(struct tty_struct *tty)
+{
+       struct wait_queue wait = { current, NULL };
+       char    *bp = sel_buffer;
+       int     c = sel_buffer_lth;
+       int     l;
+       struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
+       
+       if (!bp || !c)
+               return 0;
+       do_unblank_screen();
+       current->state = TASK_INTERRUPTIBLE;
+       add_wait_queue(&vt->paste_wait, &wait);
+       while (c) {
+               if (test_bit(TTY_THROTTLED, &tty->flags)) {
+                       schedule();
+                       continue;
+               }
+               l = MIN(c, tty->ldisc.receive_room(tty));
+               tty->ldisc.receive_buf(tty, bp, 0, l);
+               c -= l;
+               bp += l;
+       }
+       current->state = TASK_RUNNING;
+       return 0;
+}
diff --git a/drivers/char/selection.h b/drivers/char/selection.h
new file mode 100644 (file)
index 0000000..338887e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * selection.h
+ *
+ * Interface between console.c, tty_io.c, vt.c, vc_screen.c and selection.c
+ */
+extern int sel_cons;
+
+extern void clear_selection(void);
+extern int set_selection(const int arg, struct tty_struct *tty);
+extern int paste_selection(struct tty_struct *tty);
+extern int sel_loadlut(const int arg);
+extern int mouse_reporting(void);
+extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
+
+extern unsigned long video_num_columns;
+extern unsigned long video_num_lines;
+extern unsigned long video_size_row;
+
+extern void do_unblank_screen(void);
+extern unsigned short *screen_pos(int currcons, int w_offset, int viewed);
+extern unsigned short screen_word(int currcons, int offset, int viewed);
+extern void complement_pos(int currcons, int offset);
+extern void invert_screen(int currcons, int offset, int count, int shift);
+
+#define reverse_video_char(a)  (((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77))
+#define reverse_video_short(a) (((a) & 0x88ff) | \
+       (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4))
+/* this latter line used to have masks 0xf000 and 0x0f00, but selection
+   requires a self-inverse operation; moreover, the old version looks wrong */
+
+extern void getconsxy(int currcons, char *p);
+extern void putconsxy(int currcons, char *p);
+
+/* how to access screen memory */
+#ifdef __alpha__
+static inline void scr_writew(unsigned short val, unsigned short * addr)
+{
+       if ((long) addr < 0)
+               *addr = val;
+       else
+               writew(val, (unsigned long) addr);
+}
+
+static inline unsigned short scr_readw(unsigned short * addr)
+{
+       if ((long) addr < 0)
+               return *addr;
+       return readw((unsigned long) addr);
+}
+
+#else
+
+static inline void scr_writew(unsigned short val, unsigned short * addr)
+{
+       *addr = val;
+}
+
+static inline unsigned short scr_readw(unsigned short * addr)
+{
+       return *addr;
+}
+
+#endif
index 126081b3860105e621f75358e6e36475da3f5784..3c78d892d88c2b23c726620cc29416d46754b6b5 100644 (file)
@@ -60,6 +60,7 @@
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
+#include "selection.h"
 
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
 #define TTY_PARANOIA_CHECK
 #define CHECK_TTY_COUNT
 
-#ifdef CONFIG_SELECTION
-extern int set_selection(const int arg, struct tty_struct *tty);
-extern int paste_selection(struct tty_struct *tty);
-extern int sel_loadlut(const int arg);
-extern int mouse_reporting(void);
-extern int shift_state;
-#endif /* CONFIG_SELECTION */
-extern int do_screendump(unsigned long arg, int mode);
 extern void do_blank_screen(int nopowersave);
 extern void do_unblank_screen(void);
 extern void set_vesa_blanking(const unsigned long arg);
@@ -1247,6 +1240,7 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on)
        return 0;       
 }
 
+#if 0
 /*
  * XXX does anyone use this anymore?!?
  */
@@ -1278,6 +1272,7 @@ static int do_get_ps_info(unsigned long arg)
                        put_fs_long(0, (unsigned long *)(ts->present+n));
        return(0);                      
 }
+#endif
 
 static int tty_ioctl(struct inode * inode, struct file * file,
                     unsigned int cmd, unsigned long arg)
@@ -1452,21 +1447,23 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                return retval;
                        switch (retval = get_fs_byte((char *)arg))
                        {
-                               case 0: 
-                                       return do_screendump(arg,0);
+                               case 0:
+                               case 8:
+                               case 9:
+                                       printk("TIOCLINUX (0/8/9) ioctl is gone - use /dev/vcs\n");
+                                       return -EINVAL;
+#if 0
                                case 1:
                                        printk("Deprecated TIOCLINUX (1) ioctl\n");
                                        return do_get_ps_info(arg);
-#ifdef CONFIG_SELECTION
+#endif
                                case 2:
                                        return set_selection(arg, tty);
                                case 3:
                                        return paste_selection(tty);
-#endif /* CONFIG_SELECTION */
                                case 4:
                                        do_unblank_screen();
                                        return 0;
-#ifdef CONFIG_SELECTION
                                case 5:
                                        return sel_loadlut(arg);
                                case 6:
@@ -1481,16 +1478,13 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                case 7:
                                        put_fs_byte(mouse_reporting(),arg);
                                        return 0;
-#endif /* CONFIG_SELECTION */
-                               case 8: /* second arg is 1 or 2 */
-                               case 9: /* both are explained in console.c */
-                                       return do_screendump(arg,retval-7);
                                case 10:
                                        set_vesa_blanking(arg);
                                        return 0;
                                default: 
                                        return -EINVAL;
                        }
+
                case TIOCTTYGSTRUCT:
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
                                                sizeof(struct tty_struct));
@@ -1742,5 +1736,6 @@ long tty_init(long kmem_start)
        kmem_start = cy_init(kmem_start);
 #endif
        kmem_start = pty_init(kmem_start);
+       kmem_start = vcs_init(kmem_start);
        return kmem_start;
 }
diff --git a/drivers/char/uni_to_437.c b/drivers/char/uni_to_437.c
deleted file mode 100644 (file)
index 46d0f08..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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/vc_screen.c b/drivers/char/vc_screen.c
new file mode 100644 (file)
index 0000000..f5f389c
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * linux/drivers/char/vc_screen.c
+ *
+ * Provide access to virtual console memory.
+ * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
+ * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
+ *            [minor: N]
+ *
+ * /dev/vcsaN: idem, but including attributes, and prefixed with
+ *     the 4 bytes lines,columns,x,y (as screendump used to give)
+ *            [minor: N+128]
+ *
+ * This replaces screendump and part of selection, so that the system
+ * administrator can control access using file system permissions.
+ *
+ * aeb@cwi.nl - efter Friedas begravelse - 950211
+ */
+
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/fs.h>
+#include <asm/segment.h>
+#include "vt_kern.h"
+#include "selection.h"
+
+#define HEADER_SIZE    4
+
+static inline int
+vcs_size(struct inode *inode)
+{
+       int size = video_num_lines * video_num_columns;
+       if (MINOR(inode->i_rdev) & 128)
+               size = 2*size + HEADER_SIZE;
+       return size;
+}
+
+static int
+vcs_lseek(struct inode *inode, struct file *file, off_t offset, int orig)
+{
+       int size = vcs_size(inode);
+
+       switch (orig) {
+               case 0:
+                       file->f_pos = offset;
+                       break;
+               case 1:
+                       file->f_pos += offset;
+                       break;
+               case 2:
+                       file->f_pos = size + offset;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       if (file->f_pos < 0 || file->f_pos > size)
+               return -EINVAL;
+       return file->f_pos;
+}
+
+static int
+vcs_read(struct inode *inode, struct file *file, char *buf, int count)
+{
+       unsigned long p = file->f_pos;
+       unsigned int cons = MINOR(inode->i_rdev);
+       int viewed, attr, size, read;
+       char *buf0;
+       unsigned short *org;
+
+       attr = (cons & 128);
+       cons = (cons & 127);
+       if (cons == 0) {
+               cons = fg_console;
+               viewed = 1;
+       } else {
+               cons--;
+               viewed = 0;
+       }
+       if (!vc_cons_allocated(cons))
+               return -ENXIO;
+
+       size = vcs_size(inode);
+       if (count < 0 || p > size)
+               return -EINVAL;
+       if (count > size - p)
+               count = size - p;
+
+       buf0 = buf;
+       if (!attr) {
+               org = screen_pos(cons, p, viewed);
+               while (count-- > 0)
+                       put_fs_byte(scr_readw(org++) & 0xff, buf++);
+       } else {
+               if (p < HEADER_SIZE) {
+                       char header[HEADER_SIZE];
+                       header[0] = (char) video_num_lines;
+                       header[1] = (char) video_num_columns;
+                       getconsxy(cons, header+2);
+                       while (p < HEADER_SIZE && count-- > 0)
+                           put_fs_byte(header[p++], buf++);
+               }
+               p -= HEADER_SIZE;
+               org = screen_pos(cons, p/2, viewed);
+               if ((p & 1) && count-- > 0)
+                       put_fs_byte(scr_readw(org++) >> 8, buf++);
+               while (count > 1) {
+                       put_fs_word(scr_readw(org++), buf);
+                       buf += 2;
+                       count -= 2;
+               }
+               if (count > 0)
+                       put_fs_byte(scr_readw(org) & 0xff, buf++);
+       }
+       read = buf - buf0;
+       file->f_pos += read;
+       return read;
+}
+
+static int
+vcs_write(struct inode *inode, struct file *file, char *buf, int count)
+{
+       unsigned long p = file->f_pos;
+       unsigned int cons = MINOR(inode->i_rdev);
+       int viewed, attr, size, written;
+       char *buf0;
+       unsigned short *org;
+
+       attr = (cons & 128);
+       cons = (cons & 127);
+       if (cons == 0) {
+               cons = fg_console;
+               viewed = 1;
+       } else {
+               cons--;
+               viewed = 0;
+       }
+       if (!vc_cons_allocated(cons))
+               return -ENXIO;
+
+       size = vcs_size(inode);
+       if (count < 0 || p > size)
+               return -EINVAL;
+       if (count > size - p)
+               count = size - p;
+
+       buf0 = buf;
+       if (!attr) {
+               org = screen_pos(cons, p, viewed);
+               while (count-- > 0) {
+                       scr_writew((scr_readw(org) & 0xff00) |
+                               get_fs_byte(buf++), org);
+                       org++;
+               }
+       } else {
+               if (p < HEADER_SIZE) {
+                       char header[HEADER_SIZE];
+                       getconsxy(cons, header+2);
+                       while (p < HEADER_SIZE && count-- > 0)
+                               header[p++] = get_fs_byte(buf++);
+                       if (!viewed)
+                               putconsxy(cons, header+2);
+               }
+               p -= HEADER_SIZE;
+               org = screen_pos(cons, p/2, viewed);
+               if ((p & 1) && count-- > 0) {
+                       scr_writew((get_fs_byte(buf++) << 8) |
+                                  (scr_readw(org) & 0xff), org);
+                       org++;
+               }
+               while (count > 1) {
+                       scr_writew(get_fs_word(buf), org++);
+                       buf += 2;
+                       count -= 2;
+               }
+               if (count > 0)
+                       scr_writew((scr_readw(org) & 0xff00) |
+                                  get_fs_byte(buf++), org);
+       }
+       written = buf - buf0;
+       file->f_pos += written;
+       return written;
+}
+
+static int
+vcs_open(struct inode *inode, struct file *filp)
+{
+       unsigned int cons = (MINOR(inode->i_rdev) & 127);
+       if(cons && !vc_cons_allocated(cons-1))
+               return -ENXIO;
+       return 0;
+}
+
+static struct file_operations vcs_fops = {
+       vcs_lseek,      /* lseek */
+       vcs_read,       /* read */
+       vcs_write,      /* write */
+       NULL,           /* readdir */
+       NULL,           /* select */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       vcs_open,       /* open */
+       NULL,           /* release */
+       NULL            /* fsync */
+};
+
+long vcs_init(long kmem_start)
+{
+       if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
+               printk("unable to get major %d for vcs device", VCS_MAJOR);
+       return kmem_start;
+}
index baf20f501da6738f7da9b1be85ff40e576c3e5af..d2b79124df8d561d84b7b59975ade6f86d7073ba 100644 (file)
 #include "kbd_kern.h"
 #include "vt_kern.h"
 #include "diacr.h"
+#include "selection.h"
 
 extern struct tty_driver console_driver;
+extern int sel_cons;
 
 #define VT_IS_IN_USE(i)        (console_driver.table[i] && console_driver.table[i]->count)
+#define VT_BUSY(i)     (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
 
 /*
  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
@@ -62,6 +65,9 @@ extern unsigned int keymap_count;
  */
 extern int con_set_trans(char * table);
 extern int con_get_trans(char * table);
+extern void con_clear_unimap(struct unimapinit *ui);
+extern int con_set_unimap(ushort ct, struct unipair *list);
+extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
 extern int con_set_font(char * fontmap);
 extern int con_get_font(char * fontmap);
 
@@ -792,12 +798,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (arg == 0) {
                    /* disallocate all unused consoles, but leave 0 */
                    for (i=1; i<MAX_NR_CONSOLES; i++)
-                     if (! VT_IS_IN_USE(i) && i != fg_console)
+                     if (! VT_BUSY(i))
                        vc_disallocate(i);
                } else {
                    /* disallocate a single console, if possible */
                    arg--;
-                   if (VT_IS_IN_USE(arg) || arg == fg_console)
+                   if (VT_BUSY(arg))
                      return -EBUSY;
                    if (arg)                          /* leave 0 */
                      vc_disallocate(arg);
@@ -836,12 +842,61 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (!perm)
                        return -EPERM;
                return con_set_trans((char *)arg);
-               /* con_set_trans() defined in console.c */
 
        case GIO_SCRNMAP:
                return con_get_trans((char *)arg);
-               /* con_get_trans() defined in console.c */
 
+       case PIO_UNIMAPCLR:
+             { struct unimapinit ui;
+               if (!perm)
+                       return -EPERM;
+               i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
+               if (i)
+                 return i;
+               memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
+               con_clear_unimap(&ui);
+               return 0;
+             }
+
+       case PIO_UNIMAP:
+             { struct unimapdesc *ud;
+               u_short ct;
+               struct unipair *list;
+
+               if (!perm)
+                       return -EPERM;
+               i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
+               if (i == 0) {
+                   ud = (struct unimapdesc *) arg;
+                   ct = get_fs_word(&ud->entry_ct);
+                   list = (struct unipair *) get_fs_long(&ud->entries);
+                   i = verify_area(VERIFY_READ, (void *) list,
+                                   ct*sizeof(struct unipair));
+               }
+               if (i)
+                 return i;
+               return con_set_unimap(ct, list);
+             }
+
+       case GIO_UNIMAP:
+             { struct unimapdesc *ud;
+               u_short ct;
+               struct unipair *list;
+
+               i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
+               if (i == 0) {
+                   ud = (struct unimapdesc *) arg;
+                   ct = get_fs_word(&ud->entry_ct);
+                   list = (struct unipair *) get_fs_long(&ud->entries);
+                   if (ct)
+                     i = verify_area(VERIFY_WRITE, (void *) list,
+                                     ct*sizeof(struct unipair));
+               }
+               if (i)
+                 return i;
+               return con_get_unimap(ct, &(ud->entry_ct), list);
+             }
        default:
                return -ENOIOCTLCMD;
        }
index cfde63f106cd2c4d76256ed32b42e79c748f456e..52f7669d2e1e7caad46d2efb55895bc27bec84a5 100644 (file)
@@ -270,7 +270,7 @@ el1_probe1(struct device *dev, int ioaddr)
     if (autoirq)
        dev->irq = autoirq;
 
-    printk("%s: %s EtherLink at %#x, using %sIRQ %d.\n",
+    printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
           dev->name, mname, dev->base_addr,
           autoirq ? "auto":"assigned ", dev->irq);
           
index b45082228c90f764b2c6ed1c50d7315ecce3e305..cdb34893bb505035b593a681e6e9c023181bb3f1 100644 (file)
@@ -228,7 +228,7 @@ int el3_probe(struct device *dev)
 
        {
                char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
-               printk("%s: 3c509 at %#3.3x tag %d, %s port, address ",
+               printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
                           dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
        }
 
index 1100ad5c78b36277103a2b274622372fcee85ca3..8d0bfa994b79e53814a84bd6e2f1eb0cbb3fb5b0 100644 (file)
@@ -1485,7 +1485,7 @@ ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i,
     error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i));
     if (error == 0) {
       put_fs_long (ppp->dev->base_addr, l);
-      PRINTKN (3,(KERN_INFO "ppp_ioctl: get unit: %d", ppp->dev->base_addr));
+      PRINTKN (3,(KERN_INFO "ppp_ioctl: get unit: %ld", ppp->dev->base_addr));
     }
     break;
 
index 67dd077a7f2a69d9d8746f5ea797d7c044453eaf..664198411aa2d77484d0dc109e80912959bc7e8c 100644 (file)
@@ -1,6 +1,11 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      11 Feb 1995 rev. 1.17 for linux 1.1.91
+ *          Now DEBUG_RESET is disabled by default.
+ *          Register a board even if it does not assert DMA protocol support
+ *          (DPT SK2011B does not report correctly the dmasup bit).
+ *
  *       9 Feb 1995 rev. 1.16 for linux 1.1.90
  *          Use host->wish_block instead of host->block.
  *          New list of Data Out SCSI commands.
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
+#undef  DEBUG_RESET
 
 #define MAX_TARGET 8
 #define MAX_IRQ 16
@@ -390,9 +396,9 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    if (*port_base & EISA_RANGE) {
 
-      if (!info.haaval || info.ata || info.drqvld || !info.dmasup) {
-         printk("%s: unusable EISA board found (%d%d%d%d), detaching.\n", 
-                name, info.haaval, info.ata, info.drqvld, info.dmasup);
+      if (!info.haaval || info.ata || info.drqvld) {
+         printk("%s: unusable EISA board found (%d%d%d), detaching.\n", 
+                name, info.haaval, info.ata, info.drqvld);
          return FALSE;
          }
 
@@ -401,9 +407,9 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       }
    else {
 
-      if (!info.haaval || info.ata || !info.drqvld || !info.dmasup) {
-         printk("%s: unusable ISA board found (%d%d%d%d), detaching.\n",
-                name, info.haaval, info.ata, info.drqvld, info.dmasup);
+      if (!info.haaval || info.ata || !info.drqvld) {
+         printk("%s: unusable ISA board found (%d%d%d), detaching.\n",
+                name, info.haaval, info.ata, info.drqvld);
          return FALSE;
          }
 
@@ -411,6 +417,9 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       dma_channel = dma_channel_table[3 - info.drqx];
       }
 
+   if (!info.dmasup)
+      printk("%s: warning, DMA protocol support not asserted.\n", name);
+
    if (subversion == ESA && !info.irq_tr)
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
@@ -799,7 +808,11 @@ int eata2x_reset (Scsi_Cmnd *SCarg) {
       }
 
    printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
+
+#if defined (DEBUG_RESET)
    do_trace = TRUE;
+#endif
+
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
index bca8489ac117066bd5b91c23160abcf9c4472a00..9652b7f3487942da8a1c6e2eb72374a335fabc71 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <linux/scsicam.h>
 
-#define EATA_VERSION "1.16.00"
+#define EATA_VERSION "1.17.00"
 
 int eata2x_detect(Scsi_Host_Template *);
 int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
index af754f4f03b101d90ee3b4270e4a3a8dfac6e86b..ee97845ac3ccc81b6a797a91a6392bf5caf53656 100644 (file)
  * Thanks also to Greg Hosler who did a lot of testing and  *
  * found quite a number of bugs during the development.     *
  ************************************************************
- *  last change: 95/01/30                                   *
+ *  last change: 95/02/13       OS: Linux 1.1.91 or higher  *
  ************************************************************/
 
-/* Look in eata_dma.h for configuration information */
+/* Look in eata_dma.h for configuration and revision information */
 
 #ifdef MODULE
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include "eata_dma.h"
+#include "../block/blk.h"
 #include "scsi.h"
 #include "sd.h"
+#include "hosts.h"
+#include <linux/scsicam.h>
+#include "eata_dma.h"
 
-#if 0
-#include "eata_dma_proc.c"
+#if EATA_DMA_PROC  
+#include "eata_dma_proc.h"  /* If you're interested send me a mail */ 
+ulong  reads[13];           /* /proc/scsi probably won't get       */ 
+ulong  writes[13];          /* into the kernel before pl. 1.3      */
 #endif
 
 static uint ISAbases[] =
@@ -85,7 +90,7 @@ static unchar reg_IRQL[] =
 static struct eata_sp status[MAXIRQ];  /* Statuspacket array   */
 
 static uint internal_command_finished = TRUE;
-
+static unchar HBA_interpret = FALSE;
 static struct geom_emul geometry;      /* Drive 1 & 2 geometry */
 
 static ulong int_counter = 0;
@@ -96,6 +101,10 @@ void eata_scsi_done (Scsi_Cmnd * SCpnt)
     return;
 }      
 
+#if EATA_DMA_PROC 
+#include "eata_dma_proc.c"
+#endif
+
 int eata_release(struct Scsi_Host *sh)
 {
   if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
@@ -235,7 +244,10 @@ void eata_int_handler(int irq, struct pt_regs * regs)
  
        restore_flags(flags);
        if(cmd->scsi_done != eata_scsi_done) cmd->scsi_done(cmd);
-       else internal_command_finished = TRUE;
+       else {
+           internal_command_finished = TRUE;
+           HBA_interpret = FALSE;
+       }
        save_flags(flags);
        cli();
     }
@@ -337,7 +349,7 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
        cp->DataIn = TRUE;      /* Input mode  */
     }
 
-    if (done == (void *) eata_scsi_done) 
+    if (done == (void *) eata_scsi_done && HBA_interpret == TRUE
         cp->Interpret = TRUE;   /* Interpret command */
    
     if (cmd->use_sg) {
@@ -699,7 +711,7 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
        return (FALSE);
     }
 
-    if(gc->HAA_valid == FALSE || ntohl(gc->len) == 0x1c || ntohl(gc->len) == 0x1e) 
+    if(gc->HAA_valid == FALSE || ntohl(gc->len) <= 0x1e) 
         gc->MAX_CHAN = 0;
 
     if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
@@ -746,7 +758,6 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
                   "This might be a PM2012 with a defective Firmware\n");
     }
 
-    
     size = sizeof(hostdata) + ((sizeof(struct eata_ccb) * ntohs(gc->queuesiz))/
                               (gc->MAX_CHAN + 1));
 
@@ -824,11 +835,14 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
        else
            hd->primary = TRUE;
 
-       if (hd->bustype != 'I')
+       if (hd->bustype != 'I') {
            sh->unchecked_isa_dma = FALSE;
-       else
+           sh->wish_block = FALSE;        
+       }
+       else {
            sh->unchecked_isa_dma = TRUE;   /* We're doing ISA DMA */
-
+           sh->wish_block = TRUE;          /* This will reduce performance */
+       }
        if((hd->primary == TRUE) && (i == 0) && HARDCODED){                  
          geometry.drv[0].heads = HEADS0;          
          geometry.drv[0].sectors = SECTORS0;      
index dd746620523ea02bc901a854c66c83ab31e7177a..723e2a6d3f07283cdb08e19550d07c0dc057d56a 100644 (file)
@@ -2,21 +2,16 @@
 * Header file for eata_dma.c Linux EATA-DMA SCSI driver *
 * (c) 1993,94,95 Michael Neuffer                        *
 *********************************************************
-* last change: 95/01/30                                 *
+* last change: 95/02/13                                 *
 ********************************************************/
 
 
 #ifndef _EATA_DMA_H
 #define _EATA_DMA_H
 
-#include "../block/blk.h"
-#include "scsi.h"
-#include "hosts.h"
-#include <linux/scsicam.h>
-
 #define VER_MAJOR 2
 #define VER_MINOR 3
-#define VER_SUB   "0a"
+#define VER_SUB   "1a"
 
 /************************************************************************
  * Here you can configure your drives that are using a non-standard     *
@@ -44,6 +39,7 @@
  ************************************************************************/
 
 #define CHECKPAL        0        /* EISA pal checking on/off            */
+#define EATA_DMA_PROC   0        /* proc-fs support                     */
 
 /************************************************************************
  * Debug options.                                                       * 
@@ -132,19 +128,22 @@ int eata_release(struct Scsi_Host *);
 #define C_P_L_CURRENT_MAX 10  /* Until this limit in the mm is removed    
                               * Kernels < 1.1.86 died horrible deaths
                               * if you used values >2. The memory management
-                              * of pl.86 seems to cope with 10. 
+                              * since pl1.1.86 seems to cope with up to 10
+                              * queued commands per device. 
                               */
 #define C_P_L_DIV          4  /* 1 <= C_P_L_DIV <= 8            
                               * You can use this parameter to fine-tune
                               * the driver. Depending on the number of 
-                              * devices and their ability to queue commands
-                              * you will get the best results with a value
+                              * devices and their speed and ability to queue 
+                              * commands, you will get the best results with a
+                              * value
                               * ~= numdevices-(devices_unable_to_queue_commands/2)
-                              * The reason for this is that the disk driver tents 
-                              * to flood the queue, so that other drivers have 
-                              * problems to queue commands themselves. This can 
-                              * for example result in the effect that the tape
-                              * stops during disk accesses. 
+                              * The reason for this is that the disk driver 
+                              * tends to flood the queue, so that other 
+                              * drivers have problems to queue commands 
+                              * themselves. This can for example result in 
+                              * the effect that the tape stops during disk 
+                              * accesses. 
                               */
 
 #define FREE       0
index 930b11a1311691d58528116fe1415ee03501e52f..d6b5337eb71a956659fab68749f70a479d1cec05 100644 (file)
@@ -216,9 +216,6 @@ int next_scsi_host = 0;
 void
 scsi_unregister(struct Scsi_Host * sh){
        struct Scsi_Host * shpnt;
-       int j;
-
-       j = sh->extra_bytes;
 
        if(scsi_hostlist == sh)
                scsi_hostlist = sh->next;
@@ -227,8 +224,14 @@ scsi_unregister(struct Scsi_Host * sh){
                while(shpnt->next != sh) shpnt = shpnt->next;
                shpnt->next = shpnt->next->next;
        };
+
+        /* If we are removing the last host registered, it is safe to reuse
+           its host number (this avoids "holes" at boot time) (DB) */
+        if (max_scsi_hosts == next_scsi_host && !scsi_loadable_module_flag)
+           max_scsi_hosts--;
+
        next_scsi_host--;
-       scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + j);
+       scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + sh->extra_bytes);
 }
 
 /* We call this when we come across a new host adapter. We only do this
index 6f27ade60fb83a5a0572c7bef190c73e6737ad8d..3b944ff49d701985fa91202c6a28ef6ce462034f 100644 (file)
@@ -307,12 +307,15 @@ void scan_scsis (struct Scsi_Host * shpnt)
   struct Scsi_Device_Template * sdtpnt;
   Scsi_Cmnd  SCmd;
 
+  memset(&SCmd, 0,  sizeof(SCmd));
   ++in_scan_scsis;
   lun = 0;
   type = -1;
   SCmd.next = NULL;
   SCmd.prev = NULL;
   SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), GFP_ATOMIC);
+  SCmd.device = SDpnt;  /* This was really needed! (DB) */
+  memset(SDpnt, 0, sizeof(Scsi_Device));
   SDtail = scsi_devices;
   if(scsi_devices) {
     while(SDtail->next) SDtail = SDtail->next;
@@ -1913,36 +1916,51 @@ int scsi_free(void *obj, unsigned int len)
    pool */
 
 static unsigned long scsi_init_memory_start = 0;
+static unsigned long scsi_memory_lower_value = 0;
+static unsigned long scsi_memory_upper_value = 0;
 int scsi_loadable_module_flag; /* Set after we scan builtin drivers */
 
 void * scsi_init_malloc(unsigned int size, int priority)
 {
   unsigned long retval;
-  if(scsi_loadable_module_flag) {
+#if 0 /* Use the statically allocated memory instead of kmalloc  (DB) */
+  if(scsi_loadable_module_flag && !(priority & GFP_DMA))
+#else
+  if(scsi_loadable_module_flag)
+#endif
     retval = (unsigned long) kmalloc(size, priority);
-  else {
+  else {
     /*
      * Keep all memory aligned on 16-byte boundaries. Some host adaptors
      * (e.g. BusLogic BT-445S) require DMA buffers to be aligned that way.
      */
     size = (size + 15) & ~15;
-    retval = scsi_init_memory_start;
-    scsi_init_memory_start += size;
-  }
+
+    if(scsi_loadable_module_flag &&
+       (scsi_init_memory_start + size) > scsi_memory_upper_value) {
+       retval = 0;
+       printk("scsi_init_malloc: no more statically allocated memory.\n");
+       }
+    else {
+       retval = scsi_init_memory_start;
+       scsi_init_memory_start += size;
+       }
+    }
   return (void *) retval;
 }
 
 
 void scsi_init_free(char * ptr, unsigned int size)
-{ /* FIXME - not right.  We need to compare addresses to see whether this was
-     kmalloc'd or not */
-  if((unsigned long) ptr > scsi_init_memory_start) {
-    kfree(ptr);
-  } else {
-    size = (size + 15) & ~15; /* Use the same alignment as scsi_init_malloc(). */
+{ /* We need to compare addresses to see whether this was kmalloc'd or not */
+
+  if((unsigned long) ptr >= scsi_init_memory_start ||
+     (unsigned long) ptr <  scsi_memory_lower_value) kfree(ptr);
+  else {
+    size = (size + 15) & ~15; /* Use the same alignment as scsi_init_malloc() */
+
     if(((unsigned long) ptr) + size == scsi_init_memory_start)
       scsi_init_memory_start = (unsigned long) ptr;
-  }
+    }
 }
 
 /*
@@ -1967,6 +1985,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
        scsi_loadable_module_flag = 0;
        /* Align everything on 16-byte boundaries. */
        scsi_init_memory_start = (memory_start + 15) & ~ 15;
+       scsi_memory_lower_value = scsi_init_memory_start;
 
        timer_table[SCSI_TIMER].fn = scsi_main_timeout;
        timer_table[SCSI_TIMER].expires = 0;
@@ -2068,7 +2087,20 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
            (*sdtpnt->finish)();
 
        scsi_loadable_module_flag = 1;
+
+#if 0   /* This allocates statically some extra memory to be used for modules,
+           until the kmalloc problem is fixed (DB) */
+
+        scsi_memory_upper_value = scsi_init_memory_start + 
+                     2 * (scsi_init_memory_start - scsi_memory_lower_value);
+
+        printk ("scsi memory: lower %p, upper %p.\n", 
+             (void *)scsi_memory_lower_value, (void *)scsi_memory_upper_value);
+
+       return scsi_memory_upper_value;
+#else
        return scsi_init_memory_start;
+#endif
        }
 
 static void print_inquiry(unsigned char *data)
@@ -2292,7 +2324,8 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt)
      commands */
 
   for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next)
-    if(sdpnt->host->hostt == tpnt && *sdpnt->host->hostt->usage_count) return;
+    if(sdpnt->host->hostt == tpnt && sdpnt->host->hostt->usage_count
+                                 && *sdpnt->host->hostt->usage_count) return;
 
   for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
     {
index f1ec868eca36de6296acf307bcdc1267751ab269..463d2d87d4c5f760bfc86ede9c95fa5d301ea553 100644 (file)
@@ -15,7 +15,8 @@
 
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
-#define IOCTL_TIMEOUT 2000
+/* In fact, it is very slow if it has to spin up first */
+#define IOCTL_TIMEOUT 3000
 
 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 
index 3f5d07a6df5bdc83284150ece43f34cf7e6fce53..a0848e094b89a99cd6e40a4f5886e510c2376b53 100644 (file)
@@ -54,7 +54,7 @@
 
 #define ST_BLOCK_SIZE 1024
 
-#define ST_MAX_BUFFERS 2
+#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
 
 #define ST_BUFFER_BLOCKS 32
 
@@ -1948,7 +1948,7 @@ static void st_init()
   }
 
   /* Allocate the buffers */
-  st_nbr_buffers = st_template.dev_noticed;
+  st_nbr_buffers = st_template.dev_noticed + ST_EXTRA_DEVS;
   if (st_nbr_buffers > st_max_buffers)
     st_nbr_buffers = st_max_buffers;
   st_buffers = (ST_buffer **) scsi_init_malloc(st_nbr_buffers * 
index 6364116e4d4a89104c4f5751eac2c479352c81cb..35ad391968567691b1f3663c6b29053a11b9768f 100644 (file)
@@ -1,6 +1,10 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      11 Feb 1995 rev. 1.17 for linux 1.1.91
+ *          U14F qualified to run with 32 sglists.
+ *          Now DEBUG_RESET is disabled by default.
+ *
  *       9 Feb 1995 rev. 1.16 for linux 1.1.90
  *          Use host->wish_block instead of host->block.
  *
@@ -69,8 +73,8 @@
  *
  *  Here a sample configuration using two U14F boards:
  *
- U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 16, Mbox 16, CmdLun 2, C1.
- U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 16, Mbox 16, CmdLun 2, C1.
+ U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, Mbox 16, CmdLun 2, C1.
+ U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, Mbox 16, CmdLun 2, C1.
  *
  *  The boot controller must have its BIOS enabled, while other boards can
  *  have their BIOS disabled, or enabled to an higher address.
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
+#undef  DEBUG_RESET
 
 #define MAX_TARGET 8
 #define MAX_IRQ 16
 #define MAX_BOARDS 4
 #define MAX_MAILBOXES 16
-#define MAX_SGLIST 16
+#define MAX_SGLIST 32
+#define MAX_SAFE_SGLIST 16
 #define MAX_CMD_PER_LUN 2
 
 #define FALSE 0
@@ -427,7 +433,6 @@ static inline int port_detect(ushort *port_base, unsigned int j,
    if (HD(j)->subversion == ESA) {
       sh[j]->dma_channel = NO_DMA;
       sh[j]->unchecked_isa_dma = FALSE;
-      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
       sprintf(BN(j), "U34F%d", j);
       }
    else {
@@ -435,8 +440,7 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
 #if defined (HAVE_OLD_U14F_FIRMWARE)
       sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
-#else
-      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
+      sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 #endif
 
       sh[j]->dma_channel = dma_channel;
@@ -456,6 +460,7 @@ static inline int port_detect(ushort *port_base, unsigned int j,
          printk("%s: firmware %s is outdated, BIOS rev. should be 2.01.\n", 
                 BN(j), &HD(j)->board_id[32]);
          sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
          }
       }
 
@@ -737,7 +742,11 @@ int u14_34f_reset(Scsi_Cmnd * SCarg) {
 
    outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR);
    printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
+
+#if defined (DEBUG_RESET)
    do_trace = TRUE;
+#endif
+
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
index d97d491a0f25061485ee411f10c81849123b49ed..169da55de4f39dd0afa685081696b2caada8625d 100644 (file)
@@ -10,7 +10,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, int, int *);
 
-#define U14_34F_VERSION "1.16.00"
+#define U14_34F_VERSION "1.17.00"
 
 #define ULTRASTOR_14_34F {                                            \
                 NULL, /* Ptr for modules */                           \
@@ -31,6 +31,6 @@ int u14_34f_biosparam(Disk *, int, int *);
                 0,   /* cmd_per_lun, reset by detect */               \
                0,   /* number of boards present */                   \
                 1,   /* unchecked isa dma, reset by detect */         \
-                0,   /* use_clustering, reset by detect */            \
+                ENABLE_CLUSTERING                                     \
                 }
 #endif
index 1d93f89ffc87b1bd90a768f04f59d0aa9bb9eb1e..3cc827f666e0bdeb78b807750ebfb0cf49a87349 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/config.h>
 
 #include <linux/unistd.h>
-typedef int (*sysfun_p)();
+typedef int (*sysfun_p)(int);
 extern sysfun_p sys_call_table[];
 #define SYS(name)      (sys_call_table[__NR_##name])
 
index 7b7a246dce5761dafab05d2dce8412106469d777..a06f3267dda400be4944734b023b10fbff6bf332 100644 (file)
  *  Converted file_lock_table to a linked list from an array, which eliminates
  *  the limits on how many active file locks are open - Chad Page
  *  (pageone@netcom.com), November 27, 1994 
+ * 
+ *  Removed dependency on file descriptors. dup()'ed file descriptors now
+ *  get the same locks as the original file descriptors, and a close() on
+ *  any file descriptor removes ALL the locks on the file for the current
+ *  process. Since locks still depend on the process id, locks are inherited
+ *  after an exec() but not after a fork(). This agrees with POSIX, and both
+ *  BSD and SVR4 practice.
+ *  Andy Walker (andy@keo.kvaerner.no), February 14, 1994
+ *
  */
 
 #define DEADLOCK_DETECTION
 
 #define OFFSET_MAX     ((off_t)0x7fffffff)     /* FIXME: move elsewhere? */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
-                      unsigned int fd);
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l);
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl);
 static int overlap(struct file_lock *fl1, struct file_lock *fl2);
-static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd);
-static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl,
-                                    unsigned int fd);
+static int lock_it(struct file *filp, struct file_lock *caller);
+static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl);
 static void free_lock(struct file_lock **fl);
+static void free_list_garbage_collect(void);
 #ifdef DEADLOCK_DETECTION
 int locks_deadlocked(int my_pid,int blocked_pid);
 #endif
 
+#define FREE_LIST_GARBAGE_COLLECT 20
+
 static struct file_lock *file_lock_table = NULL;
 static struct file_lock *file_lock_free_list = NULL;
+static int free_list_cnt = 0;
 
 int fcntl_getlk(unsigned int fd, struct flock *l)
 {
@@ -60,7 +71,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
        memcpy_fromfs(&flock, l, sizeof(flock));
        if (flock.l_type == F_UNLCK)
                return -EINVAL;
-       if (!copy_flock(filp, &file_lock, &flock, fd))
+       if (!copy_flock(filp, &file_lock, &flock))
                return -EINVAL;
 
        for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -102,7 +113,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
        if (error)
                return error;
        memcpy_fromfs(&flock, l, sizeof(flock));
-       if (!copy_flock(filp, &file_lock, &flock, fd))
+       if (!copy_flock(filp, &file_lock, &flock))
                return -EINVAL;
        switch (file_lock.fl_type) {
        case F_RDLCK :
@@ -159,7 +170,7 @@ repeat:
         * Lock doesn't conflict with any other lock ...
         */
 
-       return lock_it(filp, &file_lock, fd);
+       return lock_it(filp, &file_lock);
 }
 
 #ifdef DEADLOCK_DETECTION
@@ -196,8 +207,7 @@ int locks_deadlocked(int my_pid,int blocked_pid)
  * This function is called when the file is closed.
  */
 
-void fcntl_remove_locks(struct task_struct *task, struct file *filp,
-                        unsigned int fd)
+void fcntl_remove_locks(struct task_struct *task, struct file *filp)
 {
        struct file_lock *fl;
        struct file_lock **before;
@@ -205,12 +215,12 @@ void fcntl_remove_locks(struct task_struct *task, struct file *filp,
        /* Find first lock owned by caller ... */
 
        before = &filp->f_inode->i_flock;
-       while ((fl = *before) && (task != fl->fl_owner || fd != fl->fl_fd))
+       while ((fl = *before) && task != fl->fl_owner)
                before = &fl->fl_next;
 
        /* The list is sorted by owner and fd ... */
 
-       while ((fl = *before) && task == fl->fl_owner && fd == fl->fl_fd)
+       while ((fl = *before) && task == fl->fl_owner)
                free_lock(before);
 }
 
@@ -219,8 +229,7 @@ void fcntl_remove_locks(struct task_struct *task, struct file *filp,
  * Result is a boolean indicating success.
  */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
-                      unsigned int fd)
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l)
 {
        off_t start;
 
@@ -243,7 +252,6 @@ static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
        if (l->l_len == 0 || (fl->fl_end = start + l->l_len - 1) < 0)
                fl->fl_end = OFFSET_MAX;
        fl->fl_owner = current;
-       fl->fl_fd = fd;
        fl->fl_wait = NULL;             /* just for cleanliness */
        return 1;
 }
@@ -254,8 +262,7 @@ static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
 
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
 {
-       if (   caller_fl->fl_owner == sys_fl->fl_owner
-            && caller_fl->fl_fd == sys_fl->fl_fd)
+       if (caller_fl->fl_owner == sys_fl->fl_owner)
                return 0;
        if (!overlap(caller_fl, sys_fl))
                return 0;
@@ -293,7 +300,7 @@ static int overlap(struct file_lock *fl1, struct file_lock *fl2)
  * To all purists: Yes, I use a few goto's. Just pass on to the next function.
  */
 
-static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd)
+static int lock_it(struct file *filp, struct file_lock *caller)
 {
        struct file_lock *fl;
        struct file_lock *left = 0;
@@ -306,18 +313,14 @@ static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd)
         */
 
        before = &filp->f_inode->i_flock;
-       while ((fl = *before) &&
-           (caller->fl_owner != fl->fl_owner ||
-            caller->fl_fd != fl->fl_fd))
+       while ((fl = *before) && caller->fl_owner != fl->fl_owner)
                before = &fl->fl_next;
 
        /*
         * Look up all locks of this owner.
         */
 
-       while (   (fl = *before)
-               && caller->fl_owner == fl->fl_owner
-               && caller->fl_fd == fl->fl_fd) {
+       while ((fl = *before) && caller->fl_owner == fl->fl_owner) {
                /*
                 * Detect adjacent or overlapping regions (if same lock type)
                 */
@@ -417,7 +420,7 @@ next_lock:
                        return 0;
 #endif
                }
-               if (! (caller = alloc_lock(before, caller, fd)))
+               if (! (caller = alloc_lock(before, caller)))
                        return -ENOLCK;
        }
        if (right) {
@@ -427,7 +430,7 @@ next_lock:
                         * have to allocate one more lock (in this case, even
                         * F_UNLCK may fail!).
                         */
-                       if (! (left = alloc_lock(before, right, fd))) {
+                       if (! (left = alloc_lock(before, right))) {
                                if (! added)
                                        free_lock(before);
                                return -ENOLCK;
@@ -446,10 +449,8 @@ next_lock:
  *  Modified to create a new node if no free entries available - Chad Page
  *
  */
-
 static struct file_lock *alloc_lock(struct file_lock **pos,
-                                   struct file_lock *fl,
-                                    unsigned int     fd)
+                                   struct file_lock *fl)
 {
        struct file_lock *tmp;
 
@@ -468,6 +469,7 @@ static struct file_lock *alloc_lock(struct file_lock **pos,
        {
                /* remove from free list */
                file_lock_free_list = tmp->fl_next;
+               free_list_cnt--;
        }
 
        if (tmp->fl_owner != NULL)
@@ -477,7 +479,6 @@ static struct file_lock *alloc_lock(struct file_lock **pos,
        *pos = tmp;
 
        tmp->fl_owner = current;        /* FIXME: needed? */
-       tmp->fl_fd = fd;                /* FIXME: needed? */
        tmp->fl_wait = NULL;
 
        tmp->fl_type = fl->fl_type;
@@ -506,5 +507,15 @@ static void free_lock(struct file_lock **fl_p)
        file_lock_free_list = fl;
        fl->fl_owner = NULL;                    /* for sanity checks */
 
+       free_list_cnt++;
+       if (free_list_cnt == FREE_LIST_GARBAGE_COLLECT)
+               free_list_garbage_collect();
+
        wake_up(&fl->fl_wait);
 }
+
+static void free_list_garbage_collect(void)
+{
+       /* Do nothing for now */
+       return;
+}
index 35dd432ed694b28c5293713afe28b0bda37204b7..89d44484117f4d3d5e6942d0252387beae1fdb9e 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/errno.h>
 #include <linux/locks.h>
 
-extern int close_fp(struct file *filp, unsigned int fd);
+extern int close_fp(struct file *filp);
 
 static int nfs_notify_change(struct inode *, struct iattr *);
 static void nfs_put_inode(struct inode *);
@@ -54,8 +54,7 @@ static void nfs_put_inode(struct inode * inode)
 
 void nfs_put_super(struct super_block *sb)
 {
-        /* No locks should be open on this, so 0 should be safe as a fd. */
-       close_fp(sb->u.nfs_sb.s_server.file, 0);
+       close_fp(sb->u.nfs_sb.s_server.file);
        lock_super(sb);
        sb->s_dev = 0;
        unlock_super(sb);
index 33b67ead34da8c5cd5beebb12d592df5b8f6b357..5962a6b5090ee48294d3226a347493c552721ead 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -20,7 +20,7 @@
 
 #include <asm/segment.h>
 
-extern void fcntl_remove_locks(struct task_struct *, struct file *, unsigned int fd);
+extern void fcntl_remove_locks(struct task_struct *, struct file *);
 
 asmlinkage int sys_ustat(int dev, struct ustat * ubuf)
 {
@@ -477,7 +477,7 @@ asmlinkage int sys_creat(const char * pathname, int mode)
        return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 }
 
-int close_fp(struct file *filp, unsigned int fd)
+int close_fp(struct file *filp)
 {
        struct inode *inode;
 
@@ -487,7 +487,7 @@ int close_fp(struct file *filp, unsigned int fd)
        }
        inode = filp->f_inode;
        if (inode)
-               fcntl_remove_locks(current, filp, fd);
+               fcntl_remove_locks(current, filp);
        if (filp->f_count > 1) {
                filp->f_count--;
                return 0;
@@ -511,7 +511,7 @@ asmlinkage int sys_close(unsigned int fd)
        if (!(filp = current->files->fd[fd]))
                return -EBADF;
        current->files->fd[fd] = NULL;
-       return (close_fp (filp, fd));
+       return (close_fp (filp));
 }
 
 /*
index 0ed2175742890864c5ea38d9438b19c9db2d01ce..124641b966430724e3a204cd7b594bd3183a55dd 100644 (file)
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *  linux/fs/proc/array.c
  *
@@ -334,22 +335,31 @@ static struct task_struct ** get_task(pid_t pid)
        return NULL;
 }
 
-static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
+static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
 {
-       pgd_t *dir;
-       pte_t *table, pte;
+       pgd_t *page_dir;
+       pmd_t *page_middle;
+       pte_t pte;
 
-       if (!p || !*p || ptr >= TASK_SIZE)
+       if (!p || ptr >= TASK_SIZE)
                return 0;
-       dir = PAGE_DIR_OFFSET(*p,ptr);
-       if (pgd_none(*dir))
+       page_dir = pgd_offset(p,ptr);
+       if (pgd_none(*page_dir))
                return 0;
-       if (pgd_bad(*dir)) {
-               printk("bad page directory entry %08lx\n", pgd_val(*dir));
+       if (pgd_bad(*page_dir)) {
+               printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
+               pgd_clear(page_dir);
                return 0;
        }
-       table = (pte_t *) (pgd_page(*dir) + PAGE_PTR(ptr));
-       pte = *table;
+       page_middle = pmd_offset(page_dir,ptr);
+       if (pmd_none(*page_middle))
+               return 0;
+       if (pmd_bad(*page_middle)) {
+               printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
+               pmd_clear(page_middle);
+               return 0;
+       }
+       pte = *pte_offset(page_middle,ptr);
        if (!pte_present(pte))
                return 0;
        return pte_page(pte) + (ptr & ~PAGE_MASK);
@@ -364,7 +374,7 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long
        if (start >= end)
                return result;
        for (;;) {
-               addr = get_phys_addr(p, start);
+               addr = get_phys_addr(*p, start);
                if (!addr)
                        goto ready;
                do {
@@ -511,55 +521,109 @@ static int get_stat(int pid, char * buffer)
                sigcatch,
                wchan);
 }
+               
+static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
+       int * pages, int * shared, int * dirty, int * total)
+{
+       pte_t * pte;
+       unsigned long end;
+
+       if (pmd_none(*pmd))
+               return;
+       if (pmd_bad(*pmd)) {
+               printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+               pmd_clear(pmd);
+               return;
+       }
+       pte = pte_offset(pmd, address);
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       do {
+               pte_t page = *pte;
+
+               address += PAGE_SIZE;
+               pte++;
+               if (pte_none(page))
+                       continue;
+               ++*total;
+               if (!pte_present(page))
+                       continue;
+               ++*pages;
+               if (pte_dirty(page))
+                       ++*dirty;
+               if (pte_page(page) >= high_memory)
+                       continue;
+               if (mem_map[MAP_NR(pte_page(page))] > 1)
+                       ++*shared;
+       } while (address < end);
+}
+
+static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
+       int * pages, int * shared, int * dirty, int * total)
+{
+       pmd_t * pmd;
+       unsigned long end;
+
+       if (pgd_none(*pgd))
+               return;
+       if (pgd_bad(*pgd)) {
+               printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+               pgd_clear(pgd);
+               return;
+       }
+       pmd = pmd_offset(pgd, address);
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       do {
+               statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address < end);
+}
+
+static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
+       int * pages, int * shared, int * dirty, int * total)
+{
+       while (address < end) {
+               statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
+               address = (address + PGDIR_SIZE) & PGDIR_MASK;
+               pgd++;
+       }
+}
 
 static int get_statm(int pid, char * buffer)
 {
        struct task_struct ** p = get_task(pid);
-       pgd_t *pagedir;
-       pte_t *pte;
-       int i, j, tpag;
        int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
 
        if (!p || !*p)
                return 0;
-       tpag = (*p)->mm->end_code / PAGE_SIZE;
        if ((*p)->state != TASK_ZOMBIE) {
-         pagedir = PAGE_DIR_OFFSET(*p, 0);
-         for (i = 0; i < 0x300; ++i) {
-           if (pgd_none(pagedir[i])) {
-             tpag -= PTRS_PER_PAGE;
-             continue;
-           }
-           if (pgd_bad(pagedir[i])) {
-               printk("bad page table dir %08lx\n", pgd_val(pagedir[i]));
-               pgd_clear(pagedir+i);
-               tpag -= PTRS_PER_PAGE;
-               continue;
-           }
-           pte = (pte_t *) pgd_page(pagedir[i]);
-           for (j = 0; j < PTRS_PER_PAGE; j++, pte++) {
-             if (!pte_none(*pte)) {
-               ++size;
-               if (pte_present(*pte)) {
-                 ++resident;
-                 if (tpag > 0)
-                   ++trs;
-                 else
-                   ++drs;
-                 if (i >= 15 && i < 0x2f0) {
-                   ++lrs;
-                   if (pte_dirty(*pte))
-                     ++dt;
-                   else
-                     --drs;
-                 }
-                 if (pte_page(*pte) < high_memory && mem_map[MAP_NR(pte_page(*pte))] > 1)
-                   ++share;
+               struct vm_area_struct * vma = (*p)->mm->mmap;
+
+               while (vma) {
+                       pgd_t *pgd = pgd_offset(*p, vma->vm_start);
+                       int pages = 0, shared = 0, dirty = 0, total = 0;
+
+                       statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
+                       resident += pages;
+                       share += shared;
+                       dt += dirty;
+                       size += total;
+                       if (vma->vm_flags & VM_EXECUTABLE)
+                               trs += pages;   /* text */
+                       else if (vma->vm_flags & VM_GROWSDOWN)
+                               drs += pages;   /* stack */
+                       else if (vma->vm_end > 0x60000000)
+                               lrs += pages;   /* library */
+                       else
+                               drs += pages;
+                       vma = vma->vm_next;
                }
-             }
-             --tpag;
-           }
-         }
        }
        return sprintf(buffer,"%d %d %d %d %d %d %d\n",
                       size, resident, share, trs, lrs, drs, dt);
index 902e0679661d933b0ed710ec573b7f196fa6b715..7fe10ab55c5ee1fb7c4360aa6f3775beedeedc2e 100644 (file)
@@ -81,7 +81,6 @@ extern unsigned long rdusp(void);
 
 #define halt() __asm__ __volatile__(".long 0");
 
-#define move_to_user_mode()    printk("Null move_to_user_mode\n")
 #define switch_to(x)           panic("switch_to() not yet done")
 
 #ifndef mb
index 6c758e44c1780c4bdbb23280373e7f0055a00391..2843e36866ef83084edbdd18c7d4372daa419e5b 100644 (file)
@@ -132,12 +132,18 @@ extern inline int pte_none(pte_t pte)             { return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
 extern inline int pte_inuse(pte_t *ptep)       { return mem_map[MAP_NR(ptep)] > 1; }
 extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+       if (!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
+               mem_map[MAP_NR(ptep)]++;
+}
 
 extern inline int pmd_none(pmd_t pmd)          { return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)           { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
 extern inline int pmd_present(pmd_t pmd)       { return pmd_val(pmd) & _PAGE_PRESENT; }
 extern inline int pmd_inuse(pmd_t *pmdp)       { return 0; }
 extern inline void pmd_clear(pmd_t * pmdp)     { pmd_val(*pmdp) = 0; }
+extern inline void pmd_reuse(pmd_t * pmdp)     { }
 
 #ifdef THREE_LEVEL
 /*
@@ -150,6 +156,11 @@ extern inline int pgd_bad(pgd_t pgd)               { return 0; }
 extern inline int pgd_present(pgd_t pgd)       { return 1; }
 extern inline int pgd_inuse(pgd_t * pgdp)      { return mem_map[MAP_NR(pgdp)] > 1; }
 extern inline void pgd_clear(pgd_t * pgdp)     { }
+extern inline void pgd_reuse(pgd_t * pgdp)
+{
+       if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
+               mem_map[MAP_NR(pgdp)]++;
+}
 #else
 /*
  * These are the old (and incorrect) ones needed for code that doesn't
index df01e6cc81d3db237f2a7f963c76b08d1744a5b3..1b766070ecdcceae76f83a8487784f7d3ae71603 100644 (file)
@@ -3,21 +3,6 @@
 
 #include <asm/segment.h>
 
-#define move_to_user_mode() \
-__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
-       "pushl %0\n\t" \
-       "pushl %%eax\n\t" \
-       "pushfl\n\t" \
-       "pushl %1\n\t" \
-       "pushl $1f\n\t" \
-       "iret\n" \
-       "1:\tmovl %0,%%eax\n\t" \
-       "mov %%ax,%%ds\n\t" \
-       "mov %%ax,%%es\n\t" \
-       "mov %%ax,%%fs\n\t" \
-       "mov %%ax,%%gs" \
-       : /* no outputs */ :"i" (USER_DS), "i" (USER_CS):"ax")
-
 /*
  * Entry into gdt where to find first TSS. GDT layout:
  *   0 - nul
index da4830d90c8248eaf58ad81ee9970d493a0fdc61..24beefff38bedda2ee4f557468fb9fcab1150304 100644 (file)
@@ -269,7 +269,6 @@ struct file_lock {
        struct file_lock *fl_next;      /* singly linked list */
        struct file_lock *fl_nextlink;
        struct task_struct *fl_owner;   /* NULL if on free list, for sanity checks */
-        unsigned int fl_fd;             /* File descriptor for this lock */
        struct wait_queue *fl_wait;
        char fl_type;
        char fl_whence;
index 56d6539c4d16339486e15eb91c5782526356c479..cb8c4ed03d0408f1b3f175213c8e3dae202b3f74 100644 (file)
@@ -24,7 +24,7 @@
  *  4 - /dev/tty*
  *  5 - /dev/tty; /dev/cua*
  *  6 - lp
- *  7 -                                               UNUSED
+ *  7 - /dev/vcs*
  *  8 -                        scsi disk
  *  9 - scsi tape
  * 10 - mice
@@ -57,7 +57,7 @@
 #define TTY_MAJOR      4
 #define TTYAUX_MAJOR   5
 #define LP_MAJOR       6
-/* unused: 7 */
+#define VCS_MAJOR      7
 #define SCSI_DISK_MAJOR        8
 #define SCSI_TAPE_MAJOR        9
 #define MOUSE_MAJOR    10
index 43ac7c16d2feb38055afa2f699b00f2ac2daf483..11da5fba71b9f0b83ff95378a1b2f89645ccfdca 100644 (file)
@@ -185,7 +185,7 @@ extern void do_no_page(struct vm_area_struct * vma, unsigned long address, int w
 extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem);
 extern void mem_init(unsigned long start_mem, unsigned long end_mem);
 extern void show_mem(void);
-extern void oom(struct task_struct * task);
+extern void oom(struct task_struct * tsk);
 extern void si_meminfo(struct sysinfo * val);
 
 /* vmalloc.c */
index 5dec5968383275f1fc2c904b0c6fb571af5df834..49f2b20ecc53f38cbb82873024fdd4e80bc27ca2 100644 (file)
@@ -278,6 +278,10 @@ extern long lp_init(long);
 extern long con_init(long);
 extern long pty_init(long);
 extern long tty_init(long);
+extern long vcs_init(long);
+#ifdef CONFIG_CYCLADES
+extern long cy_init(long);
+#endif
 
 extern int tty_paranoia_check(struct tty_struct *tty, dev_t device,
                              const char *routine);
index 8cf70504bdae2e54572c67d9ba2714f1468e9dcc..abbb512656b7427de78d8b36c02dae610efecfd0 100644 (file)
@@ -420,7 +420,6 @@ asmlinkage void start_kernel(void)
 
        printk(linux_banner);
 
-       move_to_user_mode();
        if (!fork())            /* we count on this going ok */
                init();
 /*
index 46ebd2b09afb147ec23143a04120665e3f5f37a0..345c037536c757c421000d0583ac0601f4bd9103 100644 (file)
@@ -67,7 +67,7 @@ extern int sys_tz;
 extern int request_dma(unsigned int dmanr, char * deviceID);
 extern void free_dma(unsigned int dmanr);
 
-extern int close_fp(struct file *filp, unsigned int fd);
+extern int close_fp(struct file *filp);
 extern void (* iABI_hook)(struct pt_regs * regs);
 
 struct symbol_table symbol_table = {
index c86b7db404b4b70ca0e5e6a338f8cd80882407ae..24a3372109ac9a7dcd36078ef30e179d0e570e5e 100644 (file)
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *     linux/mm/filemmap.c
  *
@@ -28,7 +29,7 @@
  * though.
  */
 
-static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address,
+static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address,
        unsigned long page, int no_share)
 {
        struct inode * inode = area->vm_inode;
@@ -61,12 +62,13 @@ static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned lon
  * - the "swapout()" function needs to swap out the page to
  *   the shared file instead of using the swap device.
  */
-static inline void file_mmap_sync_page(struct vm_area_struct * vma,
+static void filemap_sync_page(struct vm_area_struct * vma,
        unsigned long offset,
        unsigned long page)
 {
        struct buffer_head * bh;
 
+       printk("msync: %ld: [%08lx]\n", offset, page);
        bh = buffer_pages[MAP_NR(page)];
        if (bh) {
                /* whee.. just mark the buffer heads dirty */
@@ -78,60 +80,94 @@ static inline void file_mmap_sync_page(struct vm_area_struct * vma,
                return;
        }
        /* we'll need to go fetch the buffer heads etc.. RSN */
-       printk("msync: %ld: [%08lx]\n", offset, page);
        printk("Can't handle non-shared page yet\n");
        return;
 }
 
-static void file_mmap_sync(struct vm_area_struct * vma, unsigned long start,
+static inline void filemap_sync_pte(pte_t * pte, struct vm_area_struct *vma,
+       unsigned long address, unsigned int flags)
+{
+       pte_t page = *pte;
+
+       if (!pte_present(page))
+               return;
+       if (!pte_dirty(page))
+               return;
+       if (flags & MS_INVALIDATE) {
+               pte_clear(pte);
+       } else {
+               mem_map[MAP_NR(pte_page(page))]++;
+               *pte = pte_mkclean(page);
+       }
+       filemap_sync_page(vma, address - vma->vm_start, pte_page(page));
+       free_page(pte_page(page));
+}
+
+static inline void filemap_sync_pte_range(pmd_t * pmd,
+       unsigned long address, unsigned long size, 
+       struct vm_area_struct *vma, unsigned long offset, unsigned int flags)
+{
+       pte_t * pte;
+       unsigned long end;
+
+       if (pmd_none(*pmd))
+               return;
+       if (pmd_bad(*pmd)) {
+               printk("filemap_sync_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+               pmd_clear(pmd);
+               return;
+       }
+       pte = pte_offset(pmd, address);
+       offset += address & PMD_MASK;
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       do {
+               filemap_sync_pte(pte, vma, address + offset, flags);
+               address += PAGE_SIZE;
+               pte++;
+       } while (address < end);
+}
+
+static inline void filemap_sync_pmd_range(pgd_t * pgd,
+       unsigned long address, unsigned long size, 
+       struct vm_area_struct *vma, unsigned int flags)
+{
+       pmd_t * pmd;
+       unsigned long offset, end;
+
+       if (pgd_none(*pgd))
+               return;
+       if (pgd_bad(*pgd)) {
+               printk("filemap_sync_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+               pgd_clear(pgd);
+               return;
+       }
+       pmd = pmd_offset(pgd, address);
+       offset = address & PMD_MASK;
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       do {
+               filemap_sync_pte_range(pmd, address, end - address, vma, offset, flags);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address < end);
+}
+
+static void filemap_sync(struct vm_area_struct * vma, unsigned long address,
        size_t size, unsigned int flags)
 {
        pgd_t * dir;
-       unsigned long poff, pcnt;
-
-       size = size >> PAGE_SHIFT;
-       dir = PAGE_DIR_OFFSET(current,start);
-       poff = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
-       start -= vma->vm_start;
-       pcnt = PTRS_PER_PAGE - poff;
-       if (pcnt > size)
-               pcnt = size;
-
-       for ( ; size > 0; ++dir, size -= pcnt, pcnt = (size > PTRS_PER_PAGE ? PTRS_PER_PAGE : size)) {
-               pte_t *page_table;
-               unsigned long pc;
-
-               if (pgd_none(*dir)) {
-                       poff = 0;
-                       start += pcnt*PAGE_SIZE;
-                       continue;
-               }
-               if (pgd_bad(*dir)) {
-                       printk("file_mmap_sync: bad page directory entry %08lx.\n", pgd_val(*dir));
-                       pgd_clear(dir);
-                       poff = 0;
-                       start += pcnt*PAGE_SIZE;
-                       continue;
-               }
-               page_table = poff + (pte_t *) pgd_page(*dir);
-               poff = 0;
-               for (pc = pcnt; pc--; page_table++, start += PAGE_SIZE) {
-                       pte_t pte;
-
-                       pte = *page_table;
-                       if (!pte_present(pte))
-                               continue;
-                       if (!pte_dirty(pte))
-                               continue;
-                       if (flags & MS_INVALIDATE) {
-                               pte_clear(page_table);
-                       } else {
-                               mem_map[MAP_NR(pte_page(pte))]++;
-                               *page_table = pte_mkclean(pte);
-                       }
-                       file_mmap_sync_page(vma, start, pte_page(pte));
-                       free_page(pte_page(pte));
-               }
+       unsigned long end = address + size;
+
+       dir = pgd_offset(current, address);
+       while (address < end) {
+               filemap_sync_pmd_range(dir, address, end - address, vma, flags);
+               address = (address + PGDIR_SIZE) & PGDIR_MASK;
+               dir++;
        }
        invalidate();
        return;
@@ -140,17 +176,17 @@ static void file_mmap_sync(struct vm_area_struct * vma, unsigned long start,
 /*
  * This handles area unmaps..
  */
-static void file_mmap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
+static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
 {
-       file_mmap_sync(vma, start, len, MS_ASYNC);
+       filemap_sync(vma, start, len, MS_ASYNC);
 }
 
 /*
  * This handles complete area closes..
  */
-static void file_mmap_close(struct vm_area_struct * vma)
+static void filemap_close(struct vm_area_struct * vma)
 {
-       file_mmap_sync(vma, vma->vm_start, vma->vm_end - vma->vm_start, MS_ASYNC);
+       filemap_sync(vma, vma->vm_start, vma->vm_end - vma->vm_start, MS_ASYNC);
 }
 
 /*
@@ -160,7 +196,7 @@ static void file_mmap_close(struct vm_area_struct * vma)
  * so we have to either write it out or just forget it. We currently
  * forget it..
  */
-void file_mmap_swapout(struct vm_area_struct * vma,
+void filemap_swapout(struct vm_area_struct * vma,
        unsigned long offset,
        pte_t *page_table)
 {
@@ -175,14 +211,14 @@ void file_mmap_swapout(struct vm_area_struct * vma,
  */
 static struct vm_operations_struct file_shared_mmap = {
        NULL,                   /* open */
-       file_mmap_close,        /* close */
-       file_mmap_unmap,        /* unmap */
+       filemap_close,          /* close */
+       filemap_unmap,          /* unmap */
        NULL,                   /* protect */
-       file_mmap_sync,         /* sync */
+       filemap_sync,           /* sync */
        NULL,                   /* advise */
-       file_mmap_nopage,       /* nopage */
+       filemap_nopage,         /* nopage */
        NULL,                   /* wppage */
-       file_mmap_swapout,      /* swapout */
+       filemap_swapout,        /* swapout */
        NULL,                   /* swapin */
 };
 
@@ -199,7 +235,7 @@ static struct vm_operations_struct file_private_mmap = {
        NULL,                   /* protect */
        NULL,                   /* sync */
        NULL,                   /* advise */
-       file_mmap_nopage,       /* nopage */
+       filemap_nopage,         /* nopage */
        NULL,                   /* wppage */
        NULL,                   /* swapout */
        NULL,                   /* swapin */
@@ -221,9 +257,11 @@ int generic_mmap(struct inode * inode, struct file * file, struct vm_area_struct
                if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) {
                        static int nr = 0;
                        ops = &file_shared_mmap;
+#ifndef SHARED_MMAP_REALLY_WORKS /* it doesn't, yet */
                        if (nr++ < 5)
                                printk("%s tried to do a shared writeable mapping\n", current->comm);
                        return -EINVAL;
+#endif
                }
        }
        if (!IS_RDONLY(inode)) {
index d229b5bcb1cb877e4d333afa2069c79c77e03b09..dfbc863c2dcb6cc204ec9a461318b2eebe3c7245 100644 (file)
@@ -222,7 +222,7 @@ int clone_page_tables(struct task_struct * tsk)
        pgd_t * pg_dir;
 
        pg_dir = pgd_offset(current, 0);
-       mem_map[MAP_NR(pg_dir)]++;
+       pgd_reuse(pg_dir);
        SET_PAGE_DIR(tsk, pg_dir);
        return 0;
 }
@@ -265,6 +265,7 @@ static inline int copy_one_pmd(pmd_t * old_pmd, pmd_t * new_pmd)
        }
        old_pte = pte_offset(old_pmd, 0);
        if (pte_inuse(old_pte)) {
+               pte_reuse(old_pte);
                *new_pmd = *old_pmd;
                return 0;
        }
@@ -293,6 +294,7 @@ static inline int copy_one_pgd(pgd_t * old_pgd, pgd_t * new_pgd)
        }
        old_pmd = pmd_offset(old_pgd, 0);
        if (pmd_inuse(old_pmd)) {
+               pmd_reuse(old_pmd);
                *new_pgd = *old_pgd;
                return 0;
        }
index 8d53c0f32f564cba126e27611122b09a55f18238..c16f86880e93add5e231d754921056026e175fcc 100644 (file)
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *     linux/mm/mprotect.c
  *
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
+static inline void change_pte_range(pmd_t * pmd, unsigned long address,
+       unsigned long size, pgprot_t newprot)
+{
+       pte_t * pte;
+       unsigned long end;
+
+       if (pmd_none(*pmd))
+               return;
+       if (pmd_bad(*pmd)) {
+               printk("change_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+               pmd_clear(pmd);
+               return;
+       }
+       pte = pte_offset(pmd, address);
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       do {
+               pte_t entry = *pte;
+               if (pte_present(entry))
+                       *pte = pte_modify(entry, newprot);
+               address += PAGE_SIZE;
+               pte++;
+       } while (address < end);
+}
+
+static inline void change_pmd_range(pgd_t * pgd, unsigned long address,
+       unsigned long size, pgprot_t newprot)
+{
+       pmd_t * pmd;
+       unsigned long end;
+
+       if (pgd_none(*pgd))
+               return;
+       if (pgd_bad(*pgd)) {
+               printk("change_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+               pgd_clear(pgd);
+               return;
+       }
+       pmd = pmd_offset(pgd, address);
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       do {
+               change_pte_range(pmd, address, end - address, newprot);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address < end);
+}
+
 static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot)
 {
        pgd_t *dir;
-       pte_t *page_table, entry;
-       unsigned long offset;
-       int nr;
-
-       dir = PAGE_DIR_OFFSET(current, start);
-       offset = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
-       nr = (end - start) >> PAGE_SHIFT;
-       while (nr > 0) {
-               if (pgd_none(*dir)) {
-                       dir++;
-                       nr = nr - PTRS_PER_PAGE + offset;
-                       offset = 0;
-                       continue;
-               }
-               if (pgd_bad(*dir)) {
-                       printk("Bad page dir entry %08lx\n", pgd_val(*dir));
-                       pgd_clear(dir);
-                       dir++;
-                       nr = nr - PTRS_PER_PAGE + offset;
-                       offset = 0;
-                       continue;
-               }
-               page_table = offset + (pte_t *) pgd_page(*dir);
-               offset = PTRS_PER_PAGE - offset;
-               if (offset > nr)
-                       offset = nr;
-               nr = nr - offset;
-               do {
-                       entry = *page_table;
-                       if (pte_present(entry))
-                               *page_table = pte_modify(entry, newprot);
-                       ++page_table;
-               } while (--offset);
+
+       dir = pgd_offset(current, start);
+       while (start < end) {
+               change_pmd_range(dir, start, end - start, newprot);
+               start = (start + PGDIR_SIZE) & PGDIR_MASK;
                dir++;
        }
+       invalidate();
        return;
 }
 
index f557aa914b6a2a870233f012c925f946fcc8162a..1464d26e4d47835f825c557c657dbec7934c122b 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *  linux/mm/swap.c
  *
@@ -387,11 +388,89 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned offset, p
  */
 #define SWAP_RATIO     128
 
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir,
+       unsigned long address, unsigned long size, unsigned long offset)
+{
+       pte_t * pte;
+       unsigned long end;
+
+       if (pmd_none(*dir))
+               return 0;
+       if (pmd_bad(*dir)) {
+               printk("swap_out_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+               pmd_clear(dir);
+               return 0;
+       }
+       pte = pte_offset(dir, address);
+       offset += address & PMD_MASK;
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       do {
+               switch (try_to_swap_out(vma, offset+address-vma->vm_start, pte)) {
+                       case 0:
+                               break;
+
+                       case 1:
+                               vma->vm_task->mm->rss--;
+                               /* continue with the following page the next time */
+                               vma->vm_task->mm->swap_address = address + offset + PAGE_SIZE;
+                               return 1;
+
+                       default:
+                               vma->vm_task->mm->rss--;
+                               break;
+               }
+               address += PAGE_SIZE;
+               pte++;
+       } while (address < end);
+       return 0;
+}
+
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir,
+       unsigned long address, unsigned long size)
+{
+       pmd_t * pmd;
+       unsigned long offset, end;
+
+       if (pgd_none(*dir))
+               return 0;
+       if (pgd_bad(*dir)) {
+               printk("swap_out_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+               pgd_clear(dir);
+               return 0;
+       }
+       pmd = pmd_offset(dir, address);
+       offset = address & PGDIR_MASK;
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       do {
+               if (swap_out_pmd(vma, pmd, address, end - address, offset))
+                       return 1;
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address < end);
+       return 0;
+}
+
+static int swap_out_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+       unsigned long start, unsigned long end)
+{
+       while (start < end) {
+               if (swap_out_pgd(vma, pgdir, start, end - start))
+                       return 1;
+               start = (start + PGDIR_SIZE) & PGDIR_MASK;
+               pgdir++;
+       }
+       return 0;
+}
+
 static int swap_out_process(struct task_struct * p)
 {
-       pgd_t *pgdir;
        unsigned long address;
-       unsigned long offset;
        struct vm_area_struct* vma;
 
        /*
@@ -409,60 +488,14 @@ static int swap_out_process(struct task_struct * p)
        if (address < vma->vm_start)
                address = vma->vm_start;
 
-       pgdir = PAGE_DIR_OFFSET(p, address);
-       offset = address & ~PGDIR_MASK;
-       address &= PGDIR_MASK;
-       for ( ; address < TASK_SIZE ; pgdir++, address = address + PGDIR_SIZE, offset = 0) {
-               pte_t *pg_table;
-
-               if (pgd_none(*pgdir))
-                       continue;
-               if (pgd_bad(*pgdir)) {
-                       printk("Bad page directory at address %08lx: %08lx\n", address, pgd_val(*pgdir));
-                       pgd_clear(pgdir);
-                       continue;
-               }
-               pg_table = (pte_t *) pgd_page(*pgdir);
-               if (mem_map[MAP_NR((unsigned long) pg_table)] & MAP_PAGE_RESERVED)
-                       continue;
-               pg_table += offset >> PAGE_SHIFT;
-
-               /*
-                * Go through this page table.
-                */
-               for( ; offset < ~PGDIR_MASK ; pg_table++, offset += PAGE_SIZE) {
-                       /*
-                        * Update vma again..
-                        */
-                       for (;;) {
-                               if (address+offset < vma->vm_end)
-                                       break;
-                               vma = vma->vm_next;
-                               if (!vma)
-                                       return 0;
-                       }
-
-                       switch(try_to_swap_out(vma, offset+address-vma->vm_start, pg_table)) {
-                               case 0:
-                                       break;
-
-                               case 1:
-                                       p->mm->rss--;
-                                       /* continue with the following page the next time */
-                                       p->mm->swap_address = address + offset + PAGE_SIZE;
-                                       return 1;
-
-                               default:
-                                       p->mm->rss--;
-                                       break;
-                       }
-               }
+       for (;;) {
+               if (swap_out_vma(vma, pgd_offset(p, address), address, vma->vm_end))
+                       return 1;
+               vma = vma->vm_next;
+               if (!vma)
+                       return 0;
+               address = vma->vm_start;
        }
-       /*
-        * Finish work with this process, if we reached the end of the page
-        * directory.
-        */
-       return 0;
 }
 
 static int swap_out(unsigned int priority)
@@ -748,77 +781,157 @@ void show_free_areas(void)
 /*
  * Trying to stop swapping from a file is fraught with races, so
  * we repeat quite a bit here when we have to pause. swapoff()
- * isn't exactly timing-critical, so who cares?
+ * isn't exactly timing-critical, so who cares (but this is /really/
+ * inefficient, ugh).
+ *
+ * We return 1 after having slept, which makes the process start over
+ * from the beginning for this process..
  */
-static int try_to_unuse(unsigned int type)
+static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address,
+       pte_t *dir, unsigned int type, unsigned long page)
 {
-       int nr;
-       unsigned long tmp = 0;
-       struct task_struct *p;
+       pte_t pte = *dir;
+
+       if (pte_none(pte))
+               return 0;
+       if (pte_present(pte)) {
+               unsigned long page = pte_page(pte);
+               if (page >= high_memory)
+                       return 0;
+               if (!in_swap_cache(page))
+                       return 0;
+               if (SWP_TYPE(in_swap_cache(page)) != type)
+                       return 0;
+               delete_from_swap_cache(page);
+               *dir = pte_mkdirty(pte);
+               return 0;
+       }
+       if (SWP_TYPE(pte_val(pte)) != type)
+               return 0;
+       read_swap_page(pte_val(pte), (char *) page);
+       if (pte_val(*dir) != pte_val(pte)) {
+               free_page(page);
+               return 1;
+       }
+       *dir = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+       ++vma->vm_task->mm->rss;
+       swap_free(pte_val(pte));
+       return 1;
+}
+
+static inline int unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
+       unsigned long address, unsigned long size, unsigned long offset,
+       unsigned int type, unsigned long page)
+{
+       pte_t * pte;
+       unsigned long end;
+
+       if (pmd_none(*dir))
+               return 0;
+       if (pmd_bad(*dir)) {
+               printk("unuse_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+               pmd_clear(dir);
+               return 0;
+       }
+       pte = pte_offset(dir, address);
+       offset += address & PMD_MASK;
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       do {
+               if (unuse_pte(vma, offset+address-vma->vm_start, pte, type, page))
+                       return 1;
+               address += PAGE_SIZE;
+               pte++;
+       } while (address < end);
+       return 0;
+}
+
+static inline int unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
+       unsigned long address, unsigned long size,
+       unsigned int type, unsigned long page)
+{
+       pmd_t * pmd;
+       unsigned long offset, end;
+
+       if (pgd_none(*dir))
+               return 0;
+       if (pgd_bad(*dir)) {
+               printk("unuse_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+               pgd_clear(dir);
+               return 0;
+       }
+       pmd = pmd_offset(dir, address);
+       offset = address & PGDIR_MASK;
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       do {
+               if (unuse_pmd(vma, pmd, address, end - address, offset, type, page))
+                       return 1;
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address < end);
+       return 0;
+}
+
+static int unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+       unsigned long start, unsigned long end,
+       unsigned int type, unsigned long page)
+{
+       while (start < end) {
+               if (unuse_pgd(vma, pgdir, start, end - start, type, page))
+                       return 1;
+               start = (start + PGDIR_SIZE) & PGDIR_MASK;
+               pgdir++;
+       }
+       return 0;
+}
+
+static int unuse_process(struct task_struct * p, unsigned int type, unsigned long page)
+{
+       struct vm_area_struct* vma;
+
+       /*
+        * Go through process' page directory.
+        */
+       vma = p->mm->mmap;
+       while (vma) {
+               pgd_t * pgd = pgd_offset(p, vma->vm_start);
+               if (unuse_vma(vma, pgd, vma->vm_start, vma->vm_end, type, page))
+                       return 1;
+               vma = vma->vm_next;
+       }
+       return 0;
+}
 
-       nr = 0; 
 /*
- * When we have to sleep, we restart the whole algorithm from the same
- * task we stopped in. That at least rids us of all races.
+ * To avoid races, we repeat for each process after having
+ * swapped something in. That gets rid of a few pesky races,
+ * and "swapoff" isn't exactly timing critical.
  */
-repeat:
-       for (; nr < NR_TASKS ; nr++) {
-               pgd_t * page_dir;
-               int i;
-
-               p = task[nr];
-               if (!p)
-                       continue;
-               page_dir = PAGE_DIR_OFFSET(p, 0);
-               for (i = 0 ; i < PTRS_PER_PAGE ; page_dir++, i++) {
-                       int j;
-                       pte_t *page_table;
+static int try_to_unuse(unsigned int type)
+{
+       int nr;
+       unsigned long page = get_free_page(GFP_KERNEL);
 
-                       if (pgd_none(*page_dir))
-                               continue;
-                       if (pgd_bad(*page_dir)) {
-                               printk("bad page directory entry [%d] %08lx\n", i, pgd_val(*page_dir));
-                               pgd_clear(page_dir);
+       if (!page)
+               return -ENOMEM;
+       nr = 0;
+       while (nr < NR_TASKS) {
+               if (task[nr]) {
+                       if (unuse_process(task[nr], type, page)) {
+                               page = get_free_page(GFP_KERNEL);
+                               if (!page)
+                                       return -ENOMEM;
                                continue;
                        }
-                       page_table = (pte_t *) pgd_page(*page_dir);
-                       if (mem_map[MAP_NR((unsigned long) page_table)] & MAP_PAGE_RESERVED)
-                               continue;
-                       for (j = 0 ; j < PTRS_PER_PAGE ; page_table++, j++) {
-                               pte_t pte;
-                               pte = *page_table;
-                               if (pte_none(pte))
-                                       continue;
-                               if (pte_present(pte)) {
-                                       unsigned long page = pte_page(pte);
-                                       if (page >= high_memory)
-                                               continue;
-                                       if (!in_swap_cache(page))
-                                               continue;
-                                       if (SWP_TYPE(in_swap_cache(page)) != type)
-                                               continue;
-                                       delete_from_swap_cache(page);
-                                       *page_table = pte_mkdirty(pte);
-                                       continue;
-                               }
-                               if (SWP_TYPE(pte_val(pte)) != type)
-                                       continue;
-                               if (!tmp) {
-                                       if (!(tmp = __get_free_page(GFP_KERNEL)))
-                                               return -ENOMEM;
-                                       goto repeat;
-                               }
-                               read_swap_page(pte_val(pte), (char *) tmp);
-                               if (pte_val(*page_table) != pte_val(pte))
-                                       goto repeat;
-                               *page_table = pte_mkwrite(pte_mkdirty(mk_pte(tmp, PAGE_COPY)));
-                               ++p->mm->rss;
-                               swap_free(pte_val(pte));
-                               tmp = 0;
-                       }
                }
+               nr++;
        }
-       free_page(tmp);
+       free_page(page);
        return 0;
 }
 
index ecd9fe970dd237d48c856963aca014ee5d823ede..45d8d42e77cd2ed5875bc23bfd63e60c7f6a585c 100644 (file)
@@ -841,7 +841,7 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
        /*
         *      Find an entry
         */
-       entry = arp_lookup(paddr, 0);
+       entry = arp_lookup(paddr, 1);
 
        if (entry != NULL)      /* It exists */
        {
index b95112f7870ed3737162b535efe492522c4cbe38..c4ed6e198e330a7c1296c03207b1dffa6e6a7a35 100644 (file)
@@ -28,6 +28,7 @@
  *             Alan Cox        :       100 backlog just doesn't cut it when
  *                                     you start doing multicast video 8)
  *             Alan Cox        :       Rewrote net_bh and list manager.
+ *             Alan Cox        :       Fix ETH_P_ALL echoback lengths.
  *
  *     Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
  *     the rest as well commented in the end.
@@ -398,6 +399,11 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
                                struct sk_buff *skb2;
                                if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
                                        break;
+                               /*
+                                *      The protocol knows this has (for other paths) been taken off
+                                *      and adds it back.
+                                */
+                               skb2->len-=skb->dev->hard_header_len;
                                ptype->func(skb2, skb->dev, ptype);
                                nitcount--;
                        }
index 20496b28e6f1bd093e715e578abded3db38d4fca..5d2345691b0f354c84c7f4273b982e35de7e5793 100644 (file)
@@ -2052,19 +2052,6 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
        if(level!=SOL_IP)
                return -EOPNOTSUPP;
 
-#ifdef CONFIG_IP_MULTICAST
-       if(optname==IP_MULTICAST_TTL)
-       {
-               unsigned char ucval;
-               ucval=get_fs_byte((unsigned char *)optval);
-               printk("MC TTL %d\n", ucval);
-               if(ucval<1||ucval>255)
-                       return -EINVAL;
-               sk->ip_mc_ttl=(int)ucval;
-               return 0;
-       }
-#endif
-
        switch(optname)
        {
                case IP_TOS:
@@ -2082,19 +2069,16 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        sk->ip_ttl=val;
                        return 0;
 #ifdef CONFIG_IP_MULTICAST
-#ifdef GCC_WORKS
                case IP_MULTICAST_TTL: 
                {
                        unsigned char ucval;
 
                        ucval=get_fs_byte((unsigned char *)optval);
-                       printk("MC TTL %d\n", ucval);
                        if(ucval<1||ucval>255)
                                 return -EINVAL;
                        sk->ip_mc_ttl=(int)ucval;
                        return 0;
                }
-#endif
                case IP_MULTICAST_LOOP: 
                {
                        unsigned char ucval;