]> git.neil.brown.name Git - history.git/commitdiff
Import 0.99.14y 0.99.14y
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:21 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:21 +0000 (15:09 -0500)
37 files changed:
Makefile
drivers/block/README.sbpcd [new file with mode: 0644]
drivers/block/ll_rw_blk.c
drivers/block/sbpcd.c
drivers/char/console.c
drivers/char/defkeymap.c
drivers/char/kbd_kern.h [new file with mode: 0644]
drivers/char/keyboard.c
drivers/char/mem.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vt.c
fs/fifo.c
fs/inode.c
fs/pipe.c
fs/proc/array.c
fs/proc/root.c
fs/super.c
include/linux/kd.h
include/linux/kernel_stat.h [new file with mode: 0644]
include/linux/keyboard.h
include/linux/sys.h
include/linux/timex.h
include/linux/unistd.h
kernel/irq.c
kernel/sched.c
kernel/time.c
mm/swap.c
net/inet/packet.c
net/inet/skbuff.c
net/inet/sock.c
net/inet/sock.h
net/inet/tcp.c
net/inet/tcp.h
net/inet/timer.c
net/socket.c
net/unix/sock.c

index 85ac1c87a9e6e1f16b1eb26fdd06c82abfe54966..287c8170efa16051ebde90c9b1d5901a6909b8f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 14
-ALPHA = x
+ALPHA = y
 
 all:   Version zImage
 
diff --git a/drivers/block/README.sbpcd b/drivers/block/README.sbpcd
new file mode 100644 (file)
index 0000000..5b5dd1c
--- /dev/null
@@ -0,0 +1,214 @@
+This is release 1.2 of the SoundBlaster Pro (Matsushita, Kotobuki,
+Panasonic, CreativeLabs, Aztech) CD-ROM driver for Linux.
+
+The driver is able to drive the whole family of IDE-style
+Matsushita/Kotobuki/Panasonic drives (the "double speed" versions
+like CR-562 and CR-563, too), and it will work with the soundcard
+interfaces (SB Pro, SB 16, Galaxy, SoundFX, ...) and/or with
+the "no-sound" cards (Panasonic CI-101P, LaserMate, Aztech, ...).
+The interface type has to get configured, because the behavior 
+is different.
+
+The driver respects different drive firmware releases - my drive
+is a 2.11, but it should work with "old" drives <2.01 ... >3.00
+and with "new" drives (which count the releases around 0.75 or
+1.00).
+
+Up to 4 drives are supported. CR-52x and CR-56x drives can be mixed,
+but the CR-521 ones are hard-wired to drive ID 0. The drives have
+to use different drive IDs, but the same controller (it will be a
+little bit harder to support up to four interface cards - but I plan
+to do it the day somebody wishes to connect a fifth drive).
+Each drive has to get a unique minor number (0...3), corresponding
+to it's drive ID. The drive IDs may be selected freely from 0 to 3 -
+they must not be in consecutive order.
+
+If this driver doesn't work with your equipment, mail me a
+description, please.
+
+The driver supports reading of data from the CD and playing of
+audio tracks. The audio part should run with WorkMan, xcdplayer,
+with the "non-X11" products CDplayer and WorkBone - tell me if
+it is not compatible with other software.
+
+MultiSession is supported, "ManySession" (see below) alternatively.
+Photo CDs should work, too. At ftp.gwdg.de:/pub/linux/hpcdtoppm
+is a package to convert photo CD image files.
+
+I did not have a chance to play with XA or mixed mode CDs yet.
+Send one over, if you would like sbpcd to support that.
+
+The transfer rate will reach 150 kB/sec with standard drives and
+the full 300 kB/sec with double-speed drives.
+
+This release is part of the standard kernel and consists of
+- this README file
+- the driver file linux/drivers/block/sbpcd.c
+- the header file linux/include/linux/sbpcd.h.
+
+
+To install:
+-----------
+
+1. Setup your hardware parameters. Though the driver does "auto-probing"
+   now, this step is recommended for every-day use.
+   a. Go into /usr/src/linux/include/linux/sbpcd.h and configure
+      it for your hardware (near the beginning):
+      a1. Set it up for the appropriate type of interface board.
+          Most "compatible" sound boards (for example "Highscreen",
+          "SoundFX" and "Galaxy") need the "SBPRO 0" setup. The
+          "no-sound" board from OmniCd needs the "SBPRO 1" setup.
+          sbpcd.c holds some examples in it's auto-probe list.
+      a2. Tell the address of your CDROM_PORT.
+   b. Additionally for 2.a1 and 2.a2, the setup may be done during
+      boot time (via the "kernel command line" or "LILO option"):
+          sbpcd=0x230,SoundBlaster
+      or
+          sbpcd=0x320,LaserMate
+      (these strings are case sensitive!).
+
+2. Do a "make config" and select "yes" for Matsushita CD-ROM
+   support and for ISO9660 FileSystem support.
+   SCSI and/or SCSI CD-ROM support is not needed.
+
+3. Then do a "make dep", then make the kernel image ("make zlilo"
+   or else).
+
+4. Make the device file(s). The driver uses definitely and exclusive
+   the MAJOR 25, so do
+
+        mknod /dev/sbpcd b 25 0       (if you have only drive #0)
+and/or
+        mknod /dev/sbpcd0 b 25 0
+        mknod /dev/sbpcd1 b 25 1
+        mknod /dev/sbpcd2 b 25 2
+        mknod /dev/sbpcd3 b 25 3
+
+   to make the node(s).
+   Take care that you create a node with the same MINOR as your drive
+   id is. So, if the DOS driver tells you have drive id #3, you have to
+        mknod /dev/<any_name> b 25 3
+   
+   If you further make a link like
+        ln -s sbpcd /dev/cdrom
+   you can use the name /dev/cdrom, too.
+
+5. Reboot with the new kernel.
+
+You should now be able to do "mount -t iso9660 /dev/sbpcd /mnt"
+and see the contents of your CD in the /mnt directory, and/or
+hear music with "workman -c /dev/sbpcd &".
+
+
+Things of interest:
+-------------------
+
+The driver is configured to try the SoundBlaster Pro type of
+interface at I/O port 0x0230 first. If this is not appropriate,
+sbpcd.h should get changed (you will find the right place -
+just at the beginning).
+
+No DMA and no IRQ is used, so the IRQ adjusting is not necessary,
+and the IRQ line stays free for the SB Pro sound drivers.
+
+To reduce or increase the amount of kernel messages, edit
+sbpcd.c and change the initialization of the variable
+"sbpcd_debug". This is the way to get rid of the initial
+warning message block, too.
+
+With "#define MANY_SESSION 1" (sbpcd.c), the driver can use
+"many-session" CDs. This will work only with "new" drives like 
+CR-562 or CR-563. That is NOT multisession - it is a CD
+with multiple independent sessions, each containing block
+addresses as if it were the only session. With this feature
+enabled, the driver will read the LAST session. Without it,
+the FIRST session gets read.
+If you would like the support of reading "in-between" sessions,
+drop me a mail and some food for the soul. :-)
+Those "many-session" CDs can get made by CDROM writers like
+Philips CDD 521.
+With this feature enabled, it is impossible to read true
+multisession CDs.
+
+
+Auto-probing at boot time:
+--------------------------
+
+The driver does auto-probing at all well-known interface card
+addresses now. The idea to do that came from Adam J. Richter 
+(YGGDRASIL).
+
+This auto-probing looks first at the configured address resp.
+the address submitted by the kernel command line. With this,
+it is possible to use this driver within installation boot
+floppies, and for any non-standard address, too.
+
+Auto-probing will make an assumption about the interface type 
+("SBPRO" or not), based upon the address. That assumption may
+be wrong (initialization will be o.k., but you will get I/O
+errors during mount). In that case, use the "kernel command 
+line" feature and specify address & type at boot time to find 
+out the right setup.
+
+SBPCD's auto-probing happens before the initialization of the
+net drivers. That makes a hang possible if an ethernet card
+gets touched.
+
+For every-day use, address and type should get configured
+within sbpcd.h. That will stop the auto-probing due to success
+with the first try.
+
+
+Setting up address and interface type:
+--------------------------------------
+
+If your I/O port address is not 0x0230 or if you use a "no-sound"
+interface other than OmniCD, you have to look for the #defines
+near the beginning of sbpcd.h and configure them: set SBPRO to
+0 or 1, and change CDROM_PORT to the address of your CDROM I/O port.
+
+Most of the "SoundBlaster compatible" cards behave like the
+no-sound interfaces! 
+
+With "original" SB Pro cards, an initial setting of CD_volume
+through the sound cards MIXER register gets done. That happens
+at the end of "sbpcd_init". If you are using a "compatible"
+sound card of type "LaserMate", you can change that code to get
+it done with your card, too...
+
+
+Using audio CDs:
+----------------
+
+Workman, WorkBone, xcdplayer and cdplayer should work good now,
+even with the double-speed drives.
+
+The program CDplayer likes to talk to "/dev/mcd" only, xcdplayer
+wants "/dev/rsr0", workman loves "/dev/sr0" - so, do the appropriate
+links for using them without the need of supplying parameters.
+
+
+Known problems:
+---------------
+
+Currently, the detection of disk change or removal does not
+work as good as it should.
+
+Further, I do not know if this driver can live together with a
+SCSI CD-ROM driver and/or device, but I hope so. 
+
+
+
+Bug reports, comments, wishes, donations (technical information
+is a donation, too :-) etc. to
+                         emoenke@gwdg.de
+ or to                   eberhard_moenkeberg@rollo.central.de
+ or to my FIDO address:  Eberhard Moenkeberg, 2:2437/210.27
+
+
+SnailMail address, preferable for CD editors if they want to submit
+a free "cooperation" copy:
+                         Eberhard Moenkeberg
+                         Reinholdstr. 14
+                         D-37083 Goettingen
+                         Germany
index 7ea4f88ccadfe50014c8d8a911662bf33d46ce23..5e42788dd5dad201e8a3ee73c693509cecb4d456 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/config.h>
@@ -406,6 +407,10 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
                if (bh[i]) {
                        bh[i]->b_req = 1;
                        make_request(major, rw, bh[i]);
+                       if (rw == READ || rw == READA)
+                               kstat.pgpgin++;
+                       else
+                               kstat.pgpgout++;
                }
        }
        if (plugged) {
index 43df7eb3f4f8e0e679a8151c7c4c57569391bfc7..3312e7f298df31bc7695443418d63e767becebec 100644 (file)
@@ -5,7 +5,7 @@
  *            and for "no-sound" interfaces like Lasermate and the
  *            Panasonic CI-101P.
  *
- *  NOTE:     This is release 1.0.
+ *  NOTE:     This is release 1.2.
  *            It works with my SbPro & drive CR-521 V2.11 from 2/92
  *            and with the new CR-562-B V0.75 on a "naked" Panasonic
  *            CI-101P interface. And vice versa. 
  *  1.1  Do SpinUp for new drives, too.
  *       Revised for clean compile under "old" kernels (pl9).
  *
+ *  1.2  Found the "workman with double-speed drive" bug: use the driver's
+ *       audio_state, not what the drive is reporting with ReadSubQ.
+ *
+ *
+ *
  *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
  *     elaborated speed-up experiments (and the fabulous results!), for
  *     the "push" towards load-free wait loops, and for the extensive mail
  *
  *                  The FTP-home of this driver is 
  *                  ftp.gwdg.de:/pub/linux/cdrom/drivers/sbpcd/.
- *                  I will serve tsx-11.mit.edu, sunsite.unc.edu and
- *                  ftp.funet.fi, too.
- *
  *
  *                  If you change this software, you should mail a .diff
- *                  file with some description lines to emoenke.gwdg.de.
+ *                  file with some description lines to emoenke@gwdg.de.
  *                  I want to know about it.
  *
  *                  If you are the editor of a Linux CD, you should
- *                  add sbpcd.c into your boot floppy kernel and send
- *                  me one of your CDs for free.
+ *                  enable sbpcd.c within your boot floppy kernel and
+ *                  send me one of your CDs for free.
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
 #define MAJOR_NR MATSUSHITA_CDROM_MAJOR
 #include "blk.h"
 
-#define VERSION "1.1"
+#define VERSION "1.2"
 
 #define SBPCD_DEBUG
 
 #define MANY_SESSION 0
 #define CDMKE
 #undef  FUTURE
-#define WORKMAN 1 /* some testing stuff to make it better */
+#define WORKMAN 0 /* some testing stuff to make it better */
 
 /*==========================================================================*/
 /*==========================================================================*/
@@ -2057,7 +2059,6 @@ static int sbpcd_ioctl(struct inode *inode,struct file *file,
 
     case CDROMPLAYMSF:
       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYMSF entered.\n"));
-#if WORKMAN
       if (DS[d].audio_state==audio_playing)
        {
          i=xx_Pause_Resume(1);
@@ -2067,9 +2068,6 @@ static int sbpcd_ioctl(struct inode *inode,struct file *file,
          DS[d].pos_audio_start=DS[d].SubQ_run_tot;
          i=xx_Seek(DS[d].pos_audio_start,1);
        }
-#else
-      if (DS[d].audio_state==audio_playing) return (-EINVAL);
-#endif
       st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
       if (st) return (st);
       memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
@@ -2203,8 +2201,21 @@ static int sbpcd_ioctl(struct inode *inode,struct file *file,
       st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
       if (st)  return (st);
       memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
+#if 0
       if (DS[d].SubQ_audio==0x80) DS[d].SubQ_audio=CDROM_AUDIO_NO_STATUS;
-      SC.cdsc_audiostatus=DS[d].SubQ_audio;
+#endif
+      switch (DS[d].audio_state)
+       {
+       case audio_playing:
+         SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+         break;
+       case audio_pausing:
+         SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
+         break;
+       default:
+         SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
+         break;
+       }
       SC.cdsc_adr=DS[d].SubQ_ctl_adr;
       SC.cdsc_ctrl=DS[d].SubQ_ctl_adr>>4;
       SC.cdsc_trk=bcd2bin(DS[d].SubQ_trk);
index 2a72deb585294ffb225fb838e96cd89783165a08..efdeb13634f94efccef4d0d9f142ed0f585c7904 100644 (file)
  *     'void update_screen(int new_console)'
  *     'void blank_screen(void)'
  *     'void unblank_screen(void)'
+ *
+ *      'int  con_get_font(char *)' 
+ *      'int  con_set_font(char *)' 
+ *      'int  con_get_trans(char *)'
+ *      'int  con_set_trans(char *)'
  * 
  * Hopefully this will be a rather complete VT102 implementation.
  *
  *   Chars, and VT100 enhancements by Peter MacDonald.
  *
  * Copy and paste function by Andrew Haylett.
+ *
+ * User definable mapping table and font loading by Eugene G. Crosser,
+ * <crosser@pccross.msk.su>
+ *
+ * Code to check for different video-cards mostly by Galen Hunt,
+ * <g-hunt@ee.utah.edu>
+ *
  */
 
+#define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
+
 /*
  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  * (to put a word in video IO), but this will work even for keyboard
  * interrupt, as we use trap-gates. Hopefully all is well.
  */
 
-/*
- * Code to check for different video-cards mostly by Galen Hunt,
- * <g-hunt@ee.utah.edu>
- */
-
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/tty.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kd.h>
-#include <linux/keyboard.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 
+#include "kbd_kern.h"
 #include "vt_kern.h"
 
 #ifdef CONFIG_SELECTION
@@ -128,7 +137,6 @@ static struct {
        unsigned long   vc_ques         : 1;
        unsigned long   vc_need_wrap    : 1;
        unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
-       unsigned char   vc_kbdmode;
        unsigned char * vc_translate;
        unsigned char * vc_G0_charset;
        unsigned char * vc_G1_charset;
@@ -186,16 +194,15 @@ static int console_blanked = 0;
 #define        s_reverse       (vc_cons[currcons].vc_s_reverse)
 #define        ulcolor         (vc_cons[currcons].vc_ulcolor)
 #define        halfcolor       (vc_cons[currcons].vc_halfcolor)
-#define kbdmode                (vc_cons[currcons].vc_kbdmode)
 #define tab_stop       (vc_cons[currcons].vc_tab_stop)
 #define vcmode         (vt_cons[currcons].vc_mode)
 #define vtmode         (vt_cons[currcons].vt_mode)
 #define vtpid          (vt_cons[currcons].vt_pid)
 #define vtnewvt                (vt_cons[currcons].vt_newvt)
 
-#define set_kbd(x) set_vc_kbd_flag(kbd_table+currcons,x)
-#define clr_kbd(x) clr_vc_kbd_flag(kbd_table+currcons,x)
-#define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x)
+#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
+#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
+#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 
 #define decarm         VC_REPEAT
 #define decckm         VC_CKMODE
@@ -261,12 +268,31 @@ static unsigned char * translations[] = {
        "\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 };
@@ -940,10 +966,8 @@ static void reset_terminal(int currcons, int do_clear)
        clr_kbd(decckm);
        clr_kbd(kbdapplic);
        clr_kbd(lnm);
-       kbd_table[currcons].flags =
-               (kbd_table[currcons].flags & ~LED_MASK) |
-               (kbd_table[currcons].default_flags & LED_MASK);
-       kbdmode         = 0;
+       kbd_table[currcons].lockstate = 0;
+       kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
        set_leds();
 
        default_attr(currcons);
@@ -1256,6 +1280,8 @@ void con_write(struct tty_struct * tty)
                                        G0_charset = NORM_TRANS;
                                else if (c == 'U')
                                        G0_charset = NULL_TRANS;
+                               else if (c == 'K')
+                                       G0_charset = USER_TRANS;
                                if (charset == 0)
                                        translate = G0_charset;
                                state = ESnormal;
@@ -1267,6 +1293,8 @@ void con_write(struct tty_struct * tty)
                                        G1_charset = NORM_TRANS;
                                else if (c == 'U')
                                        G1_charset = NULL_TRANS;
+                               else if (c == 'K')
+                                       G1_charset = USER_TRANS;
                                if (charset == 1)
                                        translate = G1_charset;
                                state = ESnormal;
@@ -1793,3 +1821,132 @@ static void clear_selection()
        }
 }
 #endif /* CONFIG_SELECTION */
+
+/*
+ * PIO_FONT support.
+ */
+
+#define colourmap ((char *)0xa0000)
+#define blackwmap ((char *)0xb0000)
+#define cmapsz 8192
+#define seq_port_reg (0x3c4)
+#define seq_port_val (0x3c5)
+#define gr_port_reg (0x3ce)
+#define gr_port_val (0x3cf)
+
+static int set_get_font(char * arg, int set)
+{
+#ifdef CAN_LOAD_EGA_FONTS
+       int i;
+       char *charmap;
+
+       /* no use to "load" CGA... */
+
+       if (video_type == VIDEO_TYPE_EGAC)
+               charmap = colourmap;
+       else if (video_type == VIDEO_TYPE_EGAM)
+               charmap = blackwmap;
+       else
+               return -EINVAL;
+
+       i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
+       if (i)
+               return i;
+
+       cli();
+       outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
+       outb_p( 0x01, seq_port_val );   /* Synchronous reset */
+       outb_p( 0x02, seq_port_reg );
+       outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
+       outb_p( 0x04, seq_port_reg );
+       outb_p( 0x07, seq_port_val );   /* Sequential addressing */
+       outb_p( 0x00, seq_port_reg );
+       outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
+
+       outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
+       outb_p( 0x02, gr_port_val );    /* select map 2 */
+       outb_p( 0x05, gr_port_reg );
+       outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
+       outb_p( 0x06, gr_port_reg );
+       outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
+       sti();
+
+       if (set)
+               for (i=0; i<cmapsz ; i++)
+                       *(charmap+i) = get_fs_byte(arg+i);
+       else
+               for (i=0; i<cmapsz ; i++)
+                       put_fs_byte(*(charmap+i), arg+i);
+
+       cli();
+       outb_p( 0x00, seq_port_reg );   /* Frist, the sequencer */
+       outb_p( 0x01, seq_port_val );   /* Synchronous reset */
+       outb_p( 0x02, seq_port_reg );
+       outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
+       outb_p( 0x04, seq_port_reg );
+       outb_p( 0x03, seq_port_val );   /* odd-even addressing */
+       outb_p( 0x00, seq_port_reg );
+       outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
+
+       outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
+       outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
+       outb_p( 0x05, gr_port_reg );
+       outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
+       outb_p( 0x06, gr_port_reg );
+       outb_p( 0x0e, gr_port_val );    /* map starts at b800:0000 */
+       sti();
+
+       return 0;
+#else
+       return -EINVAL;
+#endif
+}
+
+/*
+ * Load font into the EGA/VGA character generator. arg points to a 8192
+ * byte map, 32 bytes per character. Only first H of them are used for
+ * 8xH fonts (0 < H <= 32).
+ */
+
+int con_set_font (char *arg)
+{
+       return set_get_font (arg,1);
+}
+
+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;
+}
index 171931e4e9af9852d4c209ef64b04918ffc76d53..61100e7bddf416391f19e1c75c1a39e8f6c7e95f 100644 (file)
@@ -9,11 +9,11 @@ u_short key_map[NR_KEYMAPS][NR_KEYS] = {
        {
        0x0200, 0x001b, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 
        0x0037, 0x0038, 0x0039, 0x0030, 0x002d, 0x003d, 0x007f, 0x0009, 
-       0x0071, 0x0077, 0x0065, 0x0072, 0x0074, 0x0079, 0x0075, 0x0069, 
-       0x006f, 0x0070, 0x005b, 0x005d, 0x0201, 0x0702, 0x0061, 0x0073, 
-       0x0064, 0x0066, 0x0067, 0x0068, 0x006a, 0x006b, 0x006c, 0x003b, 
-       0x0027, 0x0060, 0x0700, 0x005c, 0x007a, 0x0078, 0x0063, 0x0076, 
-       0x0062, 0x006e, 0x006d, 0x002c, 0x002e, 0x002f, 0x0700, 0x030c, 
+       0x0b71, 0x0b77, 0x0b65, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, 
+       0x0b6f, 0x0b70, 0x005b, 0x005d, 0x0201, 0x0702, 0x0b61, 0x0b73, 
+       0x0b64, 0x0b66, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x003b, 
+       0x0027, 0x0060, 0x0700, 0x005c, 0x0b7a, 0x0b78, 0x0b63, 0x0b76, 
+       0x0b62, 0x0b6e, 0x0b6d, 0x002c, 0x002e, 0x002f, 0x0700, 0x030c, 
        0x0703, 0x0020, 0x0207, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 
        0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0208, 0x0209, 0x0307, 
        0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 
@@ -26,11 +26,11 @@ u_short key_map[NR_KEYMAPS][NR_KEYS] = {
        }, {
        0x0200, 0x001b, 0x0021, 0x0040, 0x0023, 0x0024, 0x0025, 0x005e, 
        0x0026, 0x002a, 0x0028, 0x0029, 0x005f, 0x002b, 0x007f, 0x0009, 
-       0x0051, 0x0057, 0x0045, 0x0052, 0x0054, 0x0059, 0x0055, 0x0049, 
-       0x004f, 0x0050, 0x007b, 0x007d, 0x0201, 0x0702, 0x0041, 0x0053, 
-       0x0044, 0x0046, 0x0047, 0x0048, 0x004a, 0x004b, 0x004c, 0x003a, 
-       0x0022, 0x007e, 0x0700, 0x007c, 0x005a, 0x0058, 0x0043, 0x0056, 
-       0x0042, 0x004e, 0x004d, 0x003c, 0x003e, 0x003f, 0x0700, 0x030c, 
+       0x0b51, 0x0b57, 0x0b45, 0x0b52, 0x0b54, 0x0b59, 0x0b55, 0x0b49, 
+       0x0b4f, 0x0b50, 0x007b, 0x007d, 0x0201, 0x0702, 0x0b41, 0x0b53, 
+       0x0b44, 0x0b46, 0x0b47, 0x0b48, 0x0b4a, 0x0b4b, 0x0b4c, 0x003a, 
+       0x0022, 0x007e, 0x0700, 0x007c, 0x0b5a, 0x0b58, 0x0b43, 0x0b56, 
+       0x0b42, 0x0b4e, 0x0b4d, 0x003c, 0x003e, 0x003f, 0x0700, 0x030c, 
        0x0703, 0x0020, 0x0207, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 
        0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0208, 0x0203, 0x0307, 
        0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 
@@ -43,11 +43,11 @@ u_short key_map[NR_KEYMAPS][NR_KEYS] = {
        }, {
        0x0200, 0x0200, 0x0200, 0x0040, 0x0200, 0x0024, 0x0200, 0x0200, 
        0x007b, 0x005b, 0x005d, 0x007d, 0x005c, 0x0200, 0x0200, 0x0200, 
-       0x0071, 0x0077, 0x0065, 0x0072, 0x0074, 0x0079, 0x0075, 0x0069, 
-       0x006f, 0x0070, 0x0200, 0x007e, 0x0201, 0x0702, 0x0061, 0x0073, 
-       0x0064, 0x0066, 0x0067, 0x0068, 0x006a, 0x006b, 0x006c, 0x0200, 
-       0x0200, 0x0200, 0x0700, 0x0200, 0x007a, 0x0078, 0x0063, 0x0076, 
-       0x0062, 0x006e, 0x006d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, 
+       0x0b71, 0x0b77, 0x0b65, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, 
+       0x0b6f, 0x0b70, 0x0200, 0x007e, 0x0201, 0x0702, 0x0b61, 0x0b73, 
+       0x0b64, 0x0b66, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x0200, 
+       0x0200, 0x0200, 0x0700, 0x0200, 0x0b7a, 0x0b78, 0x0b63, 0x0b76, 
+       0x0b62, 0x0b6e, 0x0b6d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, 
        0x0703, 0x0200, 0x0207, 0x050c, 0x050d, 0x050e, 0x050f, 0x0510, 
        0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0208, 0x0202, 0x0307, 
        0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 
@@ -60,11 +60,11 @@ u_short key_map[NR_KEYMAPS][NR_KEYS] = {
        }, {
        0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 
        0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 
-       0x0051, 0x0057, 0x0045, 0x0052, 0x0054, 0x0059, 0x0055, 0x0049, 
-       0x004f, 0x0050, 0x0200, 0x0200, 0x0201, 0x0702, 0x0041, 0x0053, 
-       0x0044, 0x0046, 0x0047, 0x0048, 0x004a, 0x004b, 0x004c, 0x0200, 
-       0x0200, 0x0200, 0x0700, 0x0200, 0x005a, 0x0058, 0x0043, 0x0056, 
-       0x0042, 0x004e, 0x004d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, 
+       0x0b51, 0x0b57, 0x0b45, 0x0b52, 0x0b54, 0x0b59, 0x0b55, 0x0b49, 
+       0x0b4f, 0x0b50, 0x0200, 0x0200, 0x0201, 0x0702, 0x0b41, 0x0b53, 
+       0x0b44, 0x0b46, 0x0b47, 0x0b48, 0x0b4a, 0x0b4b, 0x0b4c, 0x0200, 
+       0x0200, 0x0200, 0x0700, 0x0200, 0x0b5a, 0x0b58, 0x0b43, 0x0b56, 
+       0x0b42, 0x0b4e, 0x0b4d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, 
        0x0703, 0x0200, 0x0207, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 
        0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0208, 0x0200, 0x0307, 
        0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 
diff --git a/drivers/char/kbd_kern.h b/drivers/char/kbd_kern.h
new file mode 100644 (file)
index 0000000..4f85272
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef _KBD_KERN_H
+#define _KBD_KERN_H
+
+#include <linux/interrupt.h>
+#define set_leds() mark_bh(KEYBOARD_BH)
+
+#include <linux/keyboard.h>
+
+/*
+ * kbd->xxx contains the VC-local things (flag settings etc..)
+ *
+ * Note: externally visible are LED_SCR, LED_NUM, LED_CAP defined in kd.h
+ *       The code in KDGETLED / KDSETLED depends on the internal and
+ *       external order being the same.
+ *
+ * Note: lockstate is used as index in the array key_map.
+ */
+struct kbd_struct {
+        unsigned char ledstate;                /* 3 bits */
+       unsigned char default_ledstate;
+#define VC_SCROLLOCK   0       /* scroll-lock mode */
+#define VC_NUMLOCK     1       /* numeric lock mode */
+#define VC_CAPSLOCK    2       /* capslock mode */
+
+       unsigned char lockstate;        /* 4 bits - must be in 0..15 */
+#define VC_SHIFTLOCK   KG_SHIFT        /* shift lock mode */
+#define VC_ALTGRLOCK   KG_ALTGR        /* altgr lock mode */
+#define VC_CTRLLOCK    KG_CTRL         /* control lock mode */
+#define VC_ALTLOCK     KG_ALT          /* alt lock mode */
+
+       unsigned char modeflags;
+#define VC_APPLIC      0       /* application key mode */
+#define VC_CKMODE      1       /* cursor key mode */
+#define VC_REPEAT      2       /* keyboard repeat */
+#define VC_CRLF                3       /* 0 - enter sends CR, 1 - enter sends CRLF */
+#define VC_META                4       /* 0 - meta, 1 - meta=prefix with ESC */
+#define VC_PAUSE       5       /* pause key pressed - unused */
+#define VC_RAW         6       /* raw (scancode) mode */
+#define VC_MEDIUMRAW   7       /* medium raw (keycode) mode */
+};
+
+extern struct kbd_struct kbd_table[];
+
+
+extern unsigned long kbd_init(unsigned long);
+
+extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+       return ((kbd->ledstate >> flag) & 1);
+}
+
+extern inline int vc_kbd_lock(struct kbd_struct * kbd, int flag)
+{
+       return ((kbd->lockstate >> flag) & 1);
+}
+
+extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+       return ((kbd->modeflags >> flag) & 1);
+}
+
+extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+       kbd->ledstate |= 1 << flag;
+}
+
+extern inline void set_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+{
+       kbd->lockstate |= 1 << flag;
+}
+
+extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+       kbd->modeflags |= 1 << flag;
+}
+
+extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+       kbd->ledstate &= ~(1 << flag);
+}
+
+extern inline void clr_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+{
+       kbd->lockstate &= ~(1 << flag);
+}
+
+extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+       kbd->modeflags &= ~(1 << flag);
+}
+
+extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+       kbd->ledstate ^= 1 << flag;
+}
+
+extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+{
+       kbd->lockstate ^= 1 << flag;
+}
+
+extern inline void chg_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+       kbd->modeflags ^= 1 << flag;
+}
+
+#endif
index adec0e5e2a4bf90b3522f4207da9634d6986152a..9bad94db48af85567dad4bd29ad145cfd6bdf3cb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/chr_drv/keyboard.c
  *
- * Keyboard driver for Linux v0.96 using Latin-1.
+ * Keyboard driver for Linux v0.99 using Latin-1.
  *
  * Written for linux by Johan Myreen as a translation from
  * the assembly version by Linus (with diacriticals added)
@@ -17,7 +17,6 @@
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
-#include <linux/keyboard.h>
 #include <linux/interrupt.h>
 #include <linux/config.h>
 #include <linux/signal.h>
 
 #include <asm/bitops.h>
 
+#include "kbd_kern.h"
 #include "diacr.h"
 
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
-#ifndef KBD_DEFFLAGS
-
-#ifdef CONFIG_KBD_META
-#define KBD_META (1 << VC_META)
-#else
-#define KBD_META 0
+#ifndef KBD_DEFMODE
+#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
 #endif
 
-#ifdef CONFIG_KBD_NUML
-#define KBD_NUML (1 << VC_NUMLOCK)
-#else
-#define KBD_NUML 0
+#ifndef KBD_DEFLEDS
+#define KBD_DEFLEDS (1 << VC_NUMLOCK)
 #endif
 
-#define KBD_DEFFLAGS (KBD_NUML | (1 << VC_REPEAT) | KBD_META)
+#ifndef KBD_DEFLOCK
+#define KBD_DEFLOCK 0
 #endif
 
 /*
@@ -90,32 +85,26 @@ struct kbd_struct kbd_table[NR_CONSOLES];
 static struct kbd_struct * kbd = kbd_table;
 static struct tty_struct * tty = NULL;
 
+/* used only by send_data - set by keyboard_interrupt */
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
 
 typedef void (*k_hand)(unsigned char value, char up_flag);
+typedef void (k_handfn)(unsigned char value, char up_flag);
 
-static void do_self(unsigned char value, char up_flag);
-static void do_fn(unsigned char value, char up_flag);
-static void do_spec(unsigned char value, char up_flag);
-static void do_pad(unsigned char value, char up_flag);
-static void do_dead(unsigned char value, char up_flag);
-static void do_cons(unsigned char value, char up_flag);
-static void do_cur(unsigned char value, char up_flag);
-static void do_shift(unsigned char value, char up_flag);
-static void do_meta(unsigned char value, char up_flag);
-static void do_ascii(unsigned char value, char up_flag);
-static void do_lock(unsigned char value, char up_flag);
+static k_handfn
+        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
+       do_meta, do_ascii, do_lock, do_lowercase;
 
 static k_hand key_handler[] = {
        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
-       do_meta, do_ascii, do_lock
+       do_meta, do_ascii, do_lock, do_lowercase
 };
 
 /* maximum values each key_handler can handle */
 const int max_vals[] = {
        255, NR_FUNC - 1, 14, 17, 4, 255, 3, NR_SHIFT,
-       255, 9, 3
+       255, 9, 3, 255
 };
 
 const int NR_TYPES = SIZE(max_vals);
@@ -219,7 +208,7 @@ static void keyboard_interrupt(int int_pt_regs)
        }
        tty = TTY_TABLE(0);
        kbd = kbd_table + fg_console;
-       if ((raw_mode = vc_kbd_flag(kbd,VC_RAW))) {
+       if ((raw_mode = vc_kbd_mode(kbd,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
@@ -301,7 +290,7 @@ static void keyboard_interrupt(int int_pt_regs)
        if (raw_mode)
                goto end_kbd_intr;
 
-       if (vc_kbd_flag(kbd, VC_MEDIUMRAW)) {
+       if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
                put_queue(scancode + up_flag);
                goto end_kbd_intr;
        }
@@ -320,13 +309,24 @@ static void keyboard_interrupt(int int_pt_regs)
         *  with slow applications and under heavy loads.
         */
        if (!rep || 
-           (vc_kbd_flag(kbd,VC_REPEAT) && tty &&
+           (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
             (L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q)))))
        {
                u_short key_code;
+               u_char type;
+
+               /* the XOR below used to be an OR */
+               int shift_final = shift_state ^ kbd->lockstate;
 
-               key_code = key_map[shift_state][scancode];
-               (*key_handler[key_code >> 8])(key_code & 0xff, up_flag);
+               key_code = key_map[shift_final][scancode];
+               type = KTYP(key_code);
+
+               if (type == KT_LETTER) {
+                   type = KT_LATIN;
+                   if (vc_kbd_led(kbd,VC_CAPSLOCK))
+                       key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode];
+               }
+               (*key_handler[type])(key_code & 0xff, up_flag);
        }
 
 end_kbd_intr:
@@ -379,7 +379,7 @@ static void applkey(int key, char mode)
 static void enter(void)
 {
        put_queue(13);
-       if (vc_kbd_flag(kbd,VC_CRLF))
+       if (vc_kbd_mode(kbd,VC_CRLF))
                put_queue(10);
 }
 
@@ -387,14 +387,14 @@ static void caps_toggle(void)
 {
        if (rep)
                return;
-       chg_vc_kbd_flag(kbd,VC_CAPSLOCK);
+       chg_vc_kbd_led(kbd,VC_CAPSLOCK);
 }
 
 static void caps_on(void)
 {
        if (rep)
                return;
-       set_vc_kbd_flag(kbd,VC_CAPSLOCK);
+       set_vc_kbd_led(kbd,VC_CAPSLOCK);
 }
 
 static void show_ptregs(void)
@@ -419,30 +419,34 @@ static void hold(void)
 {
        if (rep || !tty)
                return;
-       /* pressing scroll lock 1st time sends ^S, ChN */
-       /* pressing scroll lock 2nd time sends ^Q, ChN */
-       /* now done directly without regard to ISIG -- jlc */
-       if (!vc_kbd_flag(kbd, VC_SCROLLOCK))
-               stop_tty(tty);
-       else
+
+       /*
+        * Note: SCROLLOCK wil be set (cleared) by stop_tty (start_tty);
+        * these routines are also activated by ^S/^Q.
+        * (And SCROLLOCK can also be set by the ioctl KDSETLED.)
+        */
+       if (tty->stopped)
                start_tty(tty);
+       else
+               stop_tty(tty);
 }
 
-static void num(void)
-{
 #if 0
-       if (k_down[KG_CTRL]) {
-               /* pause key pressed, sends E1 1D 45, ChN */
-               chg_vc_kbd_flag(kbd,VC_PAUSE);
-               return;
-       }
+/* unused at present - and the VC_PAUSE bit is not used anywhere either */
+static void pause(void)
+{
+       chg_vc_kbd_mode(kbd,VC_PAUSE);
+}
 #endif
-       if (vc_kbd_flag(kbd,VC_APPLIC)) {
+
+static void num(void)
+{
+       if (vc_kbd_mode(kbd,VC_APPLIC)) {
                applkey('P', 1);
                return;
        }
        if (!rep)       /* no autorepeat for numlock, ChN */
-               chg_vc_kbd_flag(kbd,VC_NUMLOCK);
+               chg_vc_kbd_led(kbd,VC_NUMLOCK);
 }
 
 static void lastcons(void)
@@ -494,6 +498,11 @@ static void do_spec(unsigned char value, char up_flag)
                return;
        fn_table[value]();
 }
+
+static void do_lowercase(unsigned char value, char up_flag)
+{
+        printk("keyboard.c: do_lowercase was called - impossible\n");
+}
   
 static void do_self(unsigned char value, char up_flag)
 {
@@ -509,13 +518,6 @@ static void do_self(unsigned char value, char up_flag)
                 return;
         }
 
-       /* kludge... but works for ISO 8859-1 */
-       if (vc_kbd_flag(kbd,VC_CAPSLOCK))
-               if ((value >= 'a' && value <= 'z')
-                   || (value >= 224 && value <= 254)) {
-                       value -= 32;
-               }
-
        put_queue(value);
 }
 
@@ -591,12 +593,12 @@ static void do_pad(unsigned char value, char up_flag)
                return;         /* no action, if this is a key release */
 
        /* kludge... shift forces cursor/number keys */
-       if (vc_kbd_flag(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
+       if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
                applkey(app_map[value], 1);
                return;
        }
 
-       if (!vc_kbd_flag(kbd,VC_NUMLOCK))
+       if (!vc_kbd_led(kbd,VC_NUMLOCK))
                switch (value) {
                        case KVAL(K_PCOMMA):
                        case KVAL(K_PDOT):
@@ -630,12 +632,12 @@ static void do_pad(unsigned char value, char up_flag)
                                do_fn(KVAL(K_PGUP), 0);
                                return;
                        case KVAL(K_P5):
-                               applkey('G', vc_kbd_flag(kbd, VC_APPLIC));
+                               applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
                                return;
                }
 
        put_queue(pad_chars[value]);
-       if (value == KVAL(K_PENTER) && vc_kbd_flag(kbd, VC_CRLF))
+       if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
                put_queue(10);
 }
 
@@ -645,7 +647,7 @@ static void do_cur(unsigned char value, char up_flag)
        if (up_flag)
                return;
 
-       applkey(cur_chars[value], vc_kbd_flag(kbd,VC_CKMODE));
+       applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 }
 
 static void do_shift(unsigned char value, char up_flag)
@@ -658,7 +660,7 @@ static void do_shift(unsigned char value, char up_flag)
        /* kludge... */
        if (value == KVAL(K_CAPSSHIFT)) {
                value = KVAL(K_SHIFT);
-               clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
+               clr_vc_kbd_led(kbd, VC_CAPSLOCK);
        }
 
        if (up_flag) {
@@ -711,7 +713,7 @@ static void do_meta(unsigned char value, char up_flag)
        if (up_flag)
                return;
 
-       if (vc_kbd_flag(kbd, VC_META)) {
+       if (vc_kbd_mode(kbd, VC_META)) {
                put_queue('\033');
                put_queue(value);
        } else
@@ -729,30 +731,11 @@ static void do_ascii(unsigned char value, char up_flag)
                npadch = (npadch * 10 + value) % 1000;
 }
 
-/* done stupidly to avoid coding in any dependencies of
-lock values, shift values and kbd flags bit positions */
 static void do_lock(unsigned char value, char up_flag)
 {
        if (up_flag || rep)
                return;
-       switch (value) {
-               case KVAL(K_SHIFTLOCK):
-                       chg_vc_kbd_flag(kbd, VC_SHIFTLOCK);
-                       do_shift(KG_SHIFT, !vc_kbd_flag(kbd, VC_SHIFTLOCK));
-                       break;
-               case KVAL(K_CTRLLOCK):
-                       chg_vc_kbd_flag(kbd, VC_CTRLLOCK);
-                       do_shift(KG_CTRL, !vc_kbd_flag(kbd, VC_CTRLLOCK));
-                       break;
-               case KVAL(K_ALTLOCK):
-                       chg_vc_kbd_flag(kbd, VC_ALTLOCK);
-                       do_shift(KG_ALT, !vc_kbd_flag(kbd, VC_ALTLOCK));
-                       break;
-               case KVAL(K_ALTGRLOCK):
-                       chg_vc_kbd_flag(kbd, VC_ALTGRLOCK);
-                       do_shift(KG_ALTGR, !vc_kbd_flag(kbd, VC_ALTGRLOCK));
-                       break;
-       }
+       chg_vc_kbd_lock(kbd, value);
 }
 
 /*
@@ -799,7 +782,7 @@ static int send_data(unsigned char data)
 static void kbd_bh(void * unused)
 {
        static unsigned char old_leds = 0xff;
-       unsigned char leds = kbd_table[fg_console].flags & LED_MASK;
+       unsigned char leds = kbd_table[fg_console].ledstate;
 
        if (leds != old_leds) {
                old_leds = leds;
@@ -874,8 +857,10 @@ unsigned long kbd_init(unsigned long kmem_start)
 
        kbd = kbd_table + 0;
        for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
-               kbd->flags = KBD_DEFFLAGS;
-               kbd->default_flags = KBD_DEFFLAGS;
+               kbd->ledstate = KBD_DEFLEDS;
+               kbd->default_ledstate = KBD_DEFLEDS;
+               kbd->lockstate = KBD_DEFLOCK;
+               kbd->modeflags = KBD_DEFMODE;
        }
 
        bh_base[KEYBOARD_BH].routine = kbd_bh;
index 7fa9dee25bd0013483f38377a76d6ef80c7f29cb..9d461363d93ad38205cc2e164c360a28ee89714c 100644 (file)
@@ -90,6 +90,8 @@ static int mmap_mem(struct inode * inode, struct file * file,
 
        if (off & 0xfff || off + len < off)
                return -ENXIO;
+       if (x86 > 3 && off >= high_memory)
+               prot |= PAGE_PCD;
        if (remap_page_range(addr, off, len, prot))
                return -EAGAIN;
 /* try to create a dummy vmm-structure so that the rest of the kernel knows we are here */
index c2da44d8c419818114392f3a2d24c8adb39d06fd..29976010b60ce4721575b60912d016192b74d896 100644 (file)
 #include <linux/kd.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/keyboard.h>
 #include <linux/malloc.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
+#include "kbd_kern.h"
 #include "vt_kern.h"
 
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
@@ -390,7 +390,8 @@ void complete_change_console(unsigned int new_console)
                 * to account for and tracking tty count may be undesirable.
                 */
                        vt_cons[new_console].vc_mode = KD_TEXT;
-                       clr_vc_kbd_flag(kbd_table + new_console, VC_RAW);
+                       clr_vc_kbd_mode(kbd_table + new_console, VC_RAW);
+                       clr_vc_kbd_mode(kbd_table + new_console, VC_MEDIUMRAW);
                        vt_cons[new_console].vt_mode.mode = VT_AUTO;
                        vt_cons[new_console].vt_mode.waitv = 0;
                        vt_cons[new_console].vt_mode.relsig = 0;
@@ -475,7 +476,8 @@ void change_console(unsigned int new_console)
                 * to account for and tracking tty count may be undesirable.
                 */
                vt_cons[fg_console].vc_mode = KD_TEXT;
-               clr_vc_kbd_flag(kbd_table + fg_console, VC_RAW);
+               clr_vc_kbd_mode(kbd_table + fg_console, VC_RAW);
+               clr_vc_kbd_mode(kbd_table + fg_console, VC_MEDIUMRAW);
                vt_cons[fg_console].vt_mode.mode = VT_AUTO;
                vt_cons[fg_console].vt_mode.waitv = 0;
                vt_cons[fg_console].vt_mode.relsig = 0;
@@ -515,7 +517,7 @@ void stop_tty(struct tty_struct *tty)
        if (tty->stop)
                (tty->stop)(tty);
        if (IS_A_CONSOLE(tty->line)) {
-               set_vc_kbd_flag(kbd_table + fg_console, VC_SCROLLOCK);
+               set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
                set_leds();
        }
 }
@@ -532,11 +534,11 @@ void start_tty(struct tty_struct *tty)
        }
        if (tty->start)
                (tty->start)(tty);
+       TTY_WRITE_FLUSH(tty);
        if (IS_A_CONSOLE(tty->line)) {
-               clr_vc_kbd_flag(kbd_table + fg_console, VC_SCROLLOCK);
+               clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
                set_leds();
        }
-       TTY_WRITE_FLUSH(tty);
 }
 
 /* Perform OPOST processing.  Returns -1 when the write_q becomes full
index c443c3aece6a2e7e739666c1c2b44dc7663637cb..1f4b50e44b259faf8984138c48890ff5d031448d 100644 (file)
@@ -192,25 +192,27 @@ static int set_termios_2(struct tty_struct * tty, struct termios * termios)
                tty->erasing = 0;
        }
        sti();
-       if (canon_change && !(tty->termios->c_lflag & ICANON) &&
-           !EMPTY(&tty->secondary))
+       if (canon_change && !L_ICANON(tty) && !EMPTY(&tty->secondary))
                /* Get characters left over from canonical mode. */
                wake_up_interruptible(&tty->secondary.proc_list);
 
        /* see if packet mode change of state */
 
-       /* The BSD man page pty.4 says that TIOCPKT_NOSTOP should be sent
-          if the new state differs from ^S/^Q, but that's a bad way of
-          detecting a new flow control scheme.  Instead, a status byte
-          is only sent if IXON has changed. */
-       if (tty->link && tty->link->packet &&
-           (old_termios.c_iflag ^ tty->termios->c_iflag) & IXON) {
-               tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
-               if (tty->termios->c_iflag & IXON)
-                       tty->ctrl_status |= TIOCPKT_DOSTOP;
-               else
-                       tty->ctrl_status |= TIOCPKT_NOSTOP;
-               wake_up_interruptible(&tty->link->secondary.proc_list);
+       if (tty->link && tty->link->packet) {
+               int old_flow = ((old_termios.c_iflag & IXON) &&
+                               (old_termios.c_cc[VSTOP] == '\023') &&
+                               (old_termios.c_cc[VSTART] == '\021'));
+               int new_flow = (I_IXON(tty) &&
+                               STOP_CHAR(tty) == '\023' &&
+                               START_CHAR(tty) == '\021');
+               if (old_flow != new_flow) {
+                       tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
+                       if (new_flow)
+                               tty->ctrl_status |= TIOCPKT_DOSTOP;
+                       else
+                               tty->ctrl_status |= TIOCPKT_NOSTOP;
+                       wake_up_interruptible(&tty->link->secondary.proc_list);
+               }
        }
 
        unset_locked_termios(tty->termios, &old_termios,
@@ -376,8 +378,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                return retval;
                        if (cmd == TCSETSF || cmd == TCSETSW) {
                                if (cmd == TCSETSF)
-                                       flush_input(tty);
-                               wait_until_sent(tty);
+                                       flush_input(termios_tty);
+                               wait_until_sent(termios_tty);
                        }
                        return set_termios(termios_tty, (struct termios *) arg,
                                           termios_dev);
@@ -391,8 +393,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                return retval;
                        if (cmd == TCSETAF || cmd == TCSETAW) {
                                if (cmd == TCSETAF)
-                                       flush_input(tty);
-                               wait_until_sent(tty);
+                                       flush_input(termios_tty);
+                               wait_until_sent(termios_tty);
                        }
                        return set_termio(termios_tty, (struct termio *) arg,
                                          termios_dev);
@@ -484,7 +486,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
                        put_fs_long(termios_tty->pgrp, (pid_t *) arg);
                        return 0;
                case TIOCSPGRP:
-                       retval = check_change(tty, dev);
+                       retval = check_change(termios_tty, termios_dev);
                        if (retval)
                                return retval;
                        if ((current->tty < 0) ||
@@ -496,7 +498,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                return -EINVAL;
                        if (session_of_pgrp(pgrp) != current->session)
                                return -EPERM;
-                       termios_tty->pgrp = pgrp;                       
+                       termios_tty->pgrp = pgrp;
                        return 0;
                case TIOCOUTQ:
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
index 28b5e4053c432950bae45bb04f78f19420fa280c..2fb3731da57f63f6e32797130db110851feeb51f 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/tty.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
-#include <linux/keyboard.h>
 #include <linux/kd.h>
 #include <linux/vt.h>
 #include <linux/string.h>
@@ -19,6 +18,7 @@
 #include <asm/io.h>
 #include <asm/segment.h>
 
+#include "kbd_kern.h"
 #include "vt_kern.h"
 #include "diacr.h"
 
@@ -44,6 +44,14 @@ extern void change_console(unsigned int new_console);
 extern void complete_change_console(unsigned int new_console);
 extern int vt_waitactive(void);
 
+/*
+ * routines to load custom translation table and EGA/VGA font from console.c
+ */
+extern int con_set_trans(char * table);
+extern int con_get_trans(char * table);
+extern int con_set_font(char * fontmap);
+extern int con_get_font(char * fontmap);
+
 /*
  * these are the valid i/o ports we're allowed to change. they map all the
  * video ports
@@ -209,30 +217,57 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                return -EINVAL;
 
        case KDSKBMODE:
-               if (arg == K_RAW) {
-                       set_vc_kbd_flag(kbd, VC_RAW);
-                       clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
-               } else if (arg == K_XLATE) {
-                       clr_vc_kbd_flag(kbd, VC_RAW);
-                       clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
+               switch(arg) {
+                 case K_RAW:
+                       set_vc_kbd_mode(kbd, VC_RAW);
+                       clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
+                       break;
+                 case K_MEDIUMRAW:
+                       clr_vc_kbd_mode(kbd, VC_RAW);
+                       set_vc_kbd_mode(kbd, VC_MEDIUMRAW);
+                       break;
+                 case K_XLATE:
+                       clr_vc_kbd_mode(kbd, VC_RAW);
+                       clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
                        compute_shiftstate();
-               } else if (arg == K_MEDIUMRAW) {
-                       clr_vc_kbd_flag(kbd, VC_RAW);
-                       set_vc_kbd_flag(kbd, VC_MEDIUMRAW);
-               } else
+                       break;
+                 default:
                        return -EINVAL;
+               }
                flush_input(tty);
                return 0;
 
        case KDGKBMODE:
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
                if (!i) {
-                       ucval = vc_kbd_flag(kbd, VC_RAW);
-                       if (vc_kbd_flag(kbd, VC_MEDIUMRAW))
-                               put_fs_long(K_MEDIUMRAW, (unsigned long *) arg);
-                       else
-                               put_fs_long(ucval ? K_RAW : K_XLATE,
-                                       (unsigned long *) arg);
+                       ucval = (vc_kbd_mode(kbd, VC_RAW) ? K_RAW :
+                                vc_kbd_mode(kbd, VC_MEDIUMRAW) ? K_MEDIUMRAW :
+                                K_XLATE);
+                       put_fs_long(ucval, (unsigned long *) arg);
+               }
+               return i;
+
+       /* this could be folded into KDSKBMODE, but for compatibility
+          reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
+       case KDSKBMETA:
+               switch(arg) {
+                 case K_METABIT:
+                       clr_vc_kbd_mode(kbd, VC_META);
+                       break;
+                 case K_ESCPREFIX:
+                       set_vc_kbd_mode(kbd, VC_META);
+                       break;
+                 default:
+                       return -EINVAL;
+               }
+               return 0;
+
+       case KDGKBMETA:
+               i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
+               if (!i) {
+                       ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
+                                K_METABIT);
+                       put_fs_long(ucval, (unsigned long *) arg);
                }
                return i;
 
@@ -258,7 +293,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                u_char s;
                u_short v;
 
-               i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
+               i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
                if (i)
                        return i;
                if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
@@ -377,31 +412,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
                if (i)
                        return i;
-               ucval = 0;
-               if (vc_kbd_flag(kbd, VC_SCROLLOCK))
-                       ucval |= LED_SCR;
-               if (vc_kbd_flag(kbd, VC_NUMLOCK))
-                       ucval |= LED_NUM;
-               if (vc_kbd_flag(kbd, VC_CAPSLOCK))
-                       ucval |= LED_CAP;
-               put_fs_byte(ucval, (char *) arg);
+               put_fs_byte(kbd->ledstate, (char *) arg);
                return 0;
 
        case KDSETLED:
                if (arg & ~7)
                        return -EINVAL;
-               if (arg & LED_SCR)
-                       set_vc_kbd_flag(kbd, VC_SCROLLOCK);
-               else
-                       clr_vc_kbd_flag(kbd, VC_SCROLLOCK);
-               if (arg & LED_NUM)
-                       set_vc_kbd_flag(kbd, VC_NUMLOCK);
-               else
-                       clr_vc_kbd_flag(kbd, VC_NUMLOCK);
-               if (arg & LED_CAP)
-                       set_vc_kbd_flag(kbd, VC_CAPSLOCK);
-               else
-                       clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
+               kbd->ledstate = arg;
                set_leds();
                return 0;
 
@@ -552,6 +569,22 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 
                return 0;
 
+       case PIO_FONT:
+               return con_set_font((char *)arg);
+               /* con_set_font() defined in console.c */
+
+       case GIO_FONT:
+               return con_get_font((char *)arg);
+               /* con_get_font() defined in console.c */
+
+       case PIO_SCRNMAP:
+               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 */
+
        default:
                return -EINVAL;
        }
index 50e0b8cb21171371b9ee7f3ca19305ad1d369a3f..ecd9bc232e18c56a008514ed5f83b2498a8a3cfd 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -24,7 +24,7 @@ static int fifo_open(struct inode * inode,struct file * filp)
         */
                filp->f_op = &connecting_fifo_fops;
                if (!PIPE_READERS(*inode)++)
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) {
                        PIPE_RD_OPENERS(*inode)++;
                        while (!PIPE_WRITERS(*inode)) {
@@ -35,14 +35,14 @@ static int fifo_open(struct inode * inode,struct file * filp)
                                interruptible_sleep_on(&PIPE_WAIT(*inode));
                        }
                        if (!--PIPE_RD_OPENERS(*inode))
-                               wake_up(&PIPE_WAIT(*inode));
+                               wake_up_interruptible(&PIPE_WAIT(*inode));
                }
                while (PIPE_WR_OPENERS(*inode))
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                if (PIPE_WRITERS(*inode))
                        filp->f_op = &read_fifo_fops;
                if (retval && !--PIPE_READERS(*inode))
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                break;
        
        case 2:
@@ -57,7 +57,7 @@ static int fifo_open(struct inode * inode,struct file * filp)
                }
                filp->f_op = &write_fifo_fops;
                if (!PIPE_WRITERS(*inode)++)
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                if (!PIPE_READERS(*inode)) {
                        PIPE_WR_OPENERS(*inode)++;
                        while (!PIPE_READERS(*inode)) {
@@ -68,12 +68,12 @@ static int fifo_open(struct inode * inode,struct file * filp)
                                interruptible_sleep_on(&PIPE_WAIT(*inode));
                        }
                        if (!--PIPE_WR_OPENERS(*inode))
-                               wake_up(&PIPE_WAIT(*inode));
+                               wake_up_interruptible(&PIPE_WAIT(*inode));
                }
                while (PIPE_RD_OPENERS(*inode))
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                if (retval && !--PIPE_WRITERS(*inode))
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                break;
        
        case 3:
@@ -85,11 +85,11 @@ static int fifo_open(struct inode * inode,struct file * filp)
         */
                filp->f_op = &rdwr_fifo_fops;
                if (!PIPE_READERS(*inode)++)
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                while (PIPE_WR_OPENERS(*inode))
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                if (!PIPE_WRITERS(*inode)++)
-                       wake_up(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(&PIPE_WAIT(*inode));
                while (PIPE_RD_OPENERS(*inode))
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                break;
index d8437b1fc42f05a95dbcb4cf14650e6896f394b0..0db43c984112fc3b33f60bdda4a6c22fbf485979 100644 (file)
 
 #include <asm/system.h>
 
-static struct inode * hash_table[NR_IHASH];
+static struct inode_hash_entry {
+       struct inode * inode;
+       int updating;
+} hash_table[NR_IHASH];
+
 static struct inode * first_inode;
 static struct wait_queue * inode_wait = NULL;
 static int nr_inodes = 0, nr_free_inodes = 0;
@@ -22,7 +26,7 @@ static inline int const hashfn(dev_t dev, unsigned int i)
        return (dev ^ i) % NR_IHASH;
 }
 
-static inline struct inode ** const hash(dev_t dev, int i)
+static inline struct inode_hash_entry * const hash(dev_t dev, int i)
 {
        return hash_table + hashfn(dev, i);
 }
@@ -49,23 +53,23 @@ static void remove_inode_free(struct inode *inode)
 
 void insert_inode_hash(struct inode *inode)
 {
-       struct inode **h;
+       struct inode_hash_entry *h;
        h = hash(inode->i_dev, inode->i_ino);
 
-       inode->i_hash_next = *h;
+       inode->i_hash_next = h->inode;
        inode->i_hash_prev = NULL;
        if (inode->i_hash_next)
                inode->i_hash_next->i_hash_prev = inode;
-       *h = inode;
+       h->inode = inode;
 }
 
 static void remove_inode_hash(struct inode *inode)
 {
-       struct inode **h;
+       struct inode_hash_entry *h;
        h = hash(inode->i_dev, inode->i_ino);
 
-       if (*h == inode)
-               *h = inode->i_hash_next;
+       if (h->inode == inode)
+               h->inode = inode->i_hash_next;
        if (inode->i_hash_next)
                inode->i_hash_next->i_hash_prev = inode->i_hash_prev;
        if (inode->i_hash_prev)
@@ -309,7 +313,7 @@ void iput(struct inode * inode)
                return;
        }
        if (inode->i_pipe)
-               wake_up(&PIPE_WAIT(*inode));
+               wake_up_interruptible(&PIPE_WAIT(*inode));
 repeat:
        if (inode->i_count>1) {
                inode->i_count--;
@@ -421,39 +425,27 @@ struct inode * iget(struct super_block * sb,int nr)
 
 struct inode * __iget(struct super_block * sb, int nr, int crossmntp)
 {
-       struct inode * inode, * empty;
+       static struct wait_queue * update_wait = NULL;
+       struct inode_hash_entry * h;
+       struct inode * inode;
+       struct inode * empty = NULL;
 
        if (!sb)
                panic("VFS: iget with sb==NULL");
-       empty = get_empty_inode();
+       h = hash(sb->s_dev, nr);
 repeat:
-       inode = *(hash(sb->s_dev,nr));
-       while (inode) {
-               if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
-                       inode = inode->i_hash_next;
-                       continue;
-               }
-               wait_on_inode(inode);
-               if (inode->i_dev != sb->s_dev || inode->i_ino != nr)
-                       goto repeat;
-               if (!inode->i_count)
-                       nr_free_inodes--;
-               inode->i_count++;
-               if (crossmntp && inode->i_mount) {
-                       struct inode * tmp = inode->i_mount;
-                       iput(inode);
-                       inode = tmp;
-                       if (!inode->i_count)
-                               nr_free_inodes--;
-                       inode->i_count++;
-                       wait_on_inode(inode);
-               }
+       for (inode = h->inode; inode ; inode = inode->i_hash_next)
+               if (inode->i_dev == sb->s_dev && inode->i_ino == nr)
+                       goto found_it;
+       if (!empty) {
+               h->updating++;
+               empty = get_empty_inode();
+               if (!--h->updating)
+                       wake_up(&update_wait);
                if (empty)
-                       iput(empty);
-               return inode;
-       }
-       if (!empty)
+                       goto repeat;
                return (NULL);
+       }
        inode = empty;
        inode->i_sb = sb;
        inode->i_dev = sb->s_dev;
@@ -462,6 +454,31 @@ repeat:
        put_last_free(inode);
        insert_inode_hash(inode);
        read_inode(inode);
+       goto return_it;
+
+found_it:
+       if (!inode->i_count)
+               nr_free_inodes--;
+       inode->i_count++;
+       wait_on_inode(inode);
+       if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
+               printk("Whee.. inode changed from under us. Tell Linus\n");
+               iput(inode);
+               goto repeat;
+       }
+       if (crossmntp && inode->i_mount) {
+               struct inode * tmp = inode->i_mount;
+               tmp->i_count++;
+               iput(inode);
+               inode = tmp;
+               wait_on_inode(inode);
+       }
+       if (empty)
+               iput(empty);
+
+return_it:
+       while (h->updating)
+               sleep_on(&update_wait);
        return inode;
 }
 
index 2e94ba154cf6d8ea04f723feade3fa56f103444f..64784cbe8af1203a153b8a8238dd2e8b2ae635f8 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -60,7 +60,7 @@ static int pipe_read(struct inode * inode, struct file * filp, char * buf, int c
                buf += chars;
        }
        PIPE_LOCK(*inode)--;
-       wake_up(&PIPE_WAIT(*inode));
+       wake_up_interruptible(&PIPE_WAIT(*inode));
        if (read)
                return read;
        if (PIPE_WRITERS(*inode))
@@ -109,7 +109,7 @@ static int pipe_write(struct inode * inode, struct file * filp, char * buf, int
                        buf += chars;
                }
                PIPE_LOCK(*inode)--;
-               wake_up(&PIPE_WAIT(*inode));
+               wake_up_interruptible(&PIPE_WAIT(*inode));
                free = 1;
        }
        return written;
@@ -206,7 +206,7 @@ static int connect_read(struct inode * inode, struct file * filp, char * buf, in
                        break;
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
-               wake_up(& PIPE_WAIT(*inode));
+               wake_up_interruptible(& PIPE_WAIT(*inode));
                if (current->signal & ~current->blocked)
                        return -ERESTARTSYS;
                interruptible_sleep_on(& PIPE_WAIT(*inode));
@@ -246,20 +246,20 @@ static int connect_select(struct inode * inode, struct file * filp, int sel_type
 static void pipe_read_release(struct inode * inode, struct file * filp)
 {
        PIPE_READERS(*inode)--;
-       wake_up(&PIPE_WAIT(*inode));
+       wake_up_interruptible(&PIPE_WAIT(*inode));
 }
 
 static void pipe_write_release(struct inode * inode, struct file * filp)
 {
        PIPE_WRITERS(*inode)--;
-       wake_up(&PIPE_WAIT(*inode));
+       wake_up_interruptible(&PIPE_WAIT(*inode));
 }
 
 static void pipe_rdwr_release(struct inode * inode, struct file * filp)
 {
        PIPE_READERS(*inode)--;
        PIPE_WRITERS(*inode)--;
-       wake_up(&PIPE_WAIT(*inode));
+       wake_up_interruptible(&PIPE_WAIT(*inode));
 }
 
 /*
index f25bc5614333738bec4989217c41c19ec2462ac1..fc9c06a284d2402f5647771e63305c8052b7c144 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/kernel_stat.h>
 #include <linux/tty.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
@@ -85,6 +86,33 @@ static int get_loadavg(char * buffer)
                LOAD_INT(c), LOAD_FRAC(c));
 }
 
+static int get_kstat(char * buffer)
+{
+        return sprintf(buffer, "cpu  %u,%u,%u,%lu\n"
+                               "disk %u,%u,%u,%u\n"
+                               "page %u,%u\n"
+                               "swap %u,%u\n"
+                               "intr %u\n"
+                               "ctxt %u\n"
+                               "btime %lu\n",
+                kstat.cpu_user,
+                kstat.cpu_nice,
+                kstat.cpu_system,
+                jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+                kstat.dk_drive[0],
+                kstat.dk_drive[1],
+                kstat.dk_drive[2],
+                kstat.dk_drive[3],
+                kstat.pgpgin,
+                kstat.pgpgout,
+                kstat.pswpin,
+                kstat.pswpout,
+                kstat.interrupts,
+                kstat.context_swtch,
+                xtime.tv_sec - jiffies / HZ);
+}
+
+
 static int get_uptime(char * buffer)
 {
        unsigned long uptime;
@@ -468,6 +496,9 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c
                case 16:
                        length = get_module_list(page);
                        break;
+               case 17:
+                       length = get_kstat(page);
+                       break;
                default:
                        free_page((unsigned long) page);
                        return -EBADF;
index 9d9127de2be4a147d30ae147f367ed2a1d1d696f..1690b431fa9243966180e0dc4b568fd90d5d8bcf 100644 (file)
@@ -66,6 +66,7 @@ static struct proc_dir_entry root_dir[] = {
 #endif
        {14,5,"kcore" },
        {16,7,"modules" },
+       {17,4,"stat" },
 };
 
 #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
index e0b23bc9c0a47ec7cf93bfc33ac59a1e6a7b895b..5232057084eeb50278cafd8071312878cd0008a5 100644 (file)
@@ -210,6 +210,7 @@ static int do_umount(dev_t dev)
                if (!(sb=get_super(dev)))
                        return -ENOENT;
                if (!(sb->s_flags & MS_RDONLY)) {
+                       fsync_dev(dev);
                        retval = do_remount_sb(sb, MS_RDONLY, 0);
                        if (retval)
                                return retval;
index d75150456cada1f0c9af3a22d24d218ac7fc6751..c67c539efeda404e4bfcd46c85c2b75a239ab030 100644 (file)
@@ -90,6 +90,9 @@ struct port_io_arg {
 #define GIO_FONT8x16   0x4B2C  /* gets current 8x16 font used */
 #define PIO_FONT8x16   0x4B2D  /* use supplied 8x16 font */
 
+#define GIO_FONT       0x4B60  /* gets font in expanded form */
+#define PIO_FONT       0x4B61  /* use font in expanded form */
+
 #define MKDIOADDR      32      /* io bitmap size from <linux/sched.h> */
 struct kd_disparam {
        long type;                      /* type of display */
@@ -164,6 +167,12 @@ typedef char scrnmap_t;
 #define KDGKBMODE      0x4B44  /* gets current keyboard mode */
 #define KDSKBMODE      0x4B45  /* sets current keyboard mode */
 
+/* merge with previous pair of ioctls? */
+#define                K_METABIT       0x03
+#define                K_ESCPREFIX     0x04
+#define KDGKBMETA      0x4B62  /* gets meta key handling mode */
+#define KDSKBMETA      0x4B63  /* sets meta key handling mode */
+
 struct kbentry {
        u_char kb_table;
        u_char kb_index;
@@ -194,4 +203,7 @@ struct kbdiacrs {
 #define KDGKBDIACR      0x4B4A  /* read kernel accent table */
 #define KDSKBDIACR      0x4B4B  /* write kernel accent table */
 
+/* note: 0x4B60 and 0x4B61 used above for GIO_FONT and PIO_FONT
+         0x4B62 and 0x4B63 used above for KDGKBMETA and KDSKBMETA */
+
 #endif /* _LINUX_KD_H */
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
new file mode 100644 (file)
index 0000000..2f3e53b
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _LINUX_KERNEL_STAT_H
+#define _LINUX_KERNEL_STAT_H
+
+/*
+ * 'kernel_stat.h' contains the definitions needed for doing
+ * some kernel statistics (cpu usage, context switches ...),
+ * used by rstatd/perfmeter
+ */
+
+#define DK_NDRIVE 4
+
+struct kernel_stat {
+       unsigned int cpu_user, cpu_nice, cpu_system;
+       unsigned int dk_drive[DK_NDRIVE];
+       unsigned int pgpgin, pgpgout;
+       unsigned int pswpin, pswpout;
+       unsigned int interrupts;
+       unsigned int ipackets, opackets;
+       unsigned int ierrors, oerrors;
+       unsigned int collisions;
+       unsigned int context_swtch;
+};
+
+extern struct kernel_stat kstat;
+
+#endif /* _LINUX_KERNEL_STAT_H */
index 9b34bcd4074078e8d78968be66b9d2955e0c2127..b956435270d0f7bfaa7f32baf7cd447ab1945921 100644 (file)
@@ -1,63 +1,10 @@
 #ifndef __LINUX_KEYBOARD_H
 #define __LINUX_KEYBOARD_H
 
-#include <linux/interrupt.h>
-#define set_leds() mark_bh(KEYBOARD_BH)
-
-/*
- * kbd->xxx contains the VC-local things (flag settings etc..)
- * The low 3 local flags are hardcoded to be the led setting..
- */
-struct kbd_struct {
-       unsigned long flags;
-       unsigned long default_flags;
-};
-
-extern struct kbd_struct kbd_table[];
-
-/*
- * These are the local "softflags", giving actual keyboard modes. The
- * three first flags are coded to the led settings.
- */
-#define VC_SCROLLOCK   0       /* scroll-lock mode */
-#define VC_NUMLOCK     1       /* numeric lock mode */
-#define VC_CAPSLOCK    2       /* capslock mode */
-#define VC_APPLIC      3       /* application key mode */
-#define VC_CKMODE      5       /* cursor key mode */
-#define VC_REPEAT      6       /* keyboard repeat */
-#define VC_RAW         7       /* raw (scancode) mode */
-#define VC_CRLF                8       /* 0 - enter sends CR, 1 - enter sends CRLF */
-#define VC_META                9       /* 0 - meta, 1 - meta=prefix with ESC */
-#define VC_PAUSE       10      /* pause key pressed */
-#define VC_MEDIUMRAW   11      /* medium raw (keycode) mode */
-#define VC_SHIFTLOCK   12      /* shift lock mode */
-#define VC_ALTGRLOCK   13      /* altgr lock mode */
-#define VC_CTRLLOCK    14      /* control lock mode */
-#define VC_ALTLOCK     15      /* alt lock mode */
-
-#define LED_MASK       7
-
-extern unsigned long kbd_init(unsigned long);
-
-extern inline int vc_kbd_flag(struct kbd_struct * kbd, int flag)
-{
-       return ((kbd->flags >> flag) & 1);
-}
-
-extern inline void set_vc_kbd_flag(struct kbd_struct * kbd, int flag)
-{
-       kbd->flags |= 1 << flag;
-}
-
-extern inline void clr_vc_kbd_flag(struct kbd_struct * kbd, int flag)
-{
-       kbd->flags &= ~(1 << flag);
-}
-
-extern inline void chg_vc_kbd_flag(struct kbd_struct * kbd, int flag)
-{
-       kbd->flags ^= 1 << flag;
-}
+#define KG_SHIFT       0
+#define KG_CTRL                2
+#define KG_ALT         3
+#define KG_ALTGR       1
 
 #define NR_KEYS 128
 #define NR_KEYMAPS 16
@@ -71,6 +18,7 @@ extern char func_buf[FUNC_BUFSIZE];
 extern char *func_table[NR_FUNC];
 
 #define KT_LATIN       0       /* we depend on this being zero */
+#define KT_LETTER      11      /* symbol that can be acted upon by CapsLock */
 #define KT_FN          1
 #define KT_SPEC                2
 #define KT_PAD         3
@@ -163,11 +111,6 @@ extern char *func_table[NR_FUNC];
 #define K_RIGHT                K(KT_CUR,2)
 #define K_UP           K(KT_CUR,3)
 
-#define KG_SHIFT       0
-#define KG_CTRL                2
-#define KG_ALT         3
-#define KG_ALTGR       1
-
 #define K_SHIFT                K(KT_SHIFT,KG_SHIFT)
 #define K_CTRL         K(KT_SHIFT,KG_CTRL)
 #define K_ALT          K(KT_SHIFT,KG_ALT)
@@ -188,10 +131,10 @@ extern char *func_table[NR_FUNC];
 #define K_ASC8         K(KT_ASCII,8)
 #define K_ASC9         K(KT_ASCII,9)
 
-#define K_SHIFTLOCK    K(KT_LOCK,0)
-#define K_CTRLLOCK     K(KT_LOCK,2)
-#define K_ALTLOCK      K(KT_LOCK,3)
-#define K_ALTGRLOCK    K(KT_LOCK,1)
+#define K_SHIFTLOCK    K(KT_LOCK,KG_SHIFT)
+#define K_CTRLLOCK     K(KT_LOCK,KG_CTRL)
+#define K_ALTLOCK      K(KT_LOCK,KG_ALT)
+#define K_ALTGRLOCK    K(KT_LOCK,KG_ALTGR)
 
 #define MAX_DIACR       256
 #endif
index cb51d7b9982ee734426a373cd58fa03b059c0e62..2f4b029f66ada179afd7b400da192df2996393eb 100644 (file)
@@ -144,6 +144,7 @@ extern int sys_get_kernel_syms(); /* 130 */
 extern int sys_quotactl();
 extern int sys_getpgid();
 extern int sys_fchdir();
+extern int sys_bdflush();
 
 /*
  * These are system calls that will be removed at some time
@@ -167,6 +168,7 @@ extern int sys_fchdir();
  */
 
 #define sys_quotactl   sys_ni_syscall
+#define sys_bdflush    sys_ni_syscall
 
 typedef int (*fn_ptr)();
 
index 1fcb1008d9153a3752119bcef76677513bb20afe..bf4b3900c01bcfc9b25d0579522f4982f7f75768 100644 (file)
@@ -89,6 +89,7 @@ struct timex {
                                 * (read only)
                                 */
        struct timeval time;    /* (read only) */
+       long tick;              /* (modified) usecs between clock ticks */
 };
 
 /*
@@ -100,6 +101,7 @@ struct timex {
 #define ADJ_ESTERROR           0x0008  /* estimated time error */
 #define ADJ_STATUS             0x0010  /* clock status */
 #define ADJ_TIMECONST          0x0020  /* pll time constant */
+#define ADJ_TICK               0x4000  /* tick value */
 #define ADJ_OFFSET_SINGLESHOT  0x8001  /* old-fashioned adjtime */
 
 /*
index 36f48823569e87a0f231b69be139ee36ea288f75..c499a132d6f0853fcd72496fdead59a8bb1999b8 100644 (file)
 #define __NR_quotactl          131
 #define __NR_getpgid           132
 #define __NR_fchdir            133
+#define __NR_bdflush           134
 
 extern int errno;
 
index 0fc155e274de00fadfb86ffb734842ed489dda3c..e38d9e806d83eee0a6240cab493d745d06171def 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/ptrace.h>
 #include <linux/errno.h>
+#include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -200,6 +201,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 {
        struct sigaction * sa = irq + irq_sigaction;
 
+       kstat.interrupts++;
        sa->sa_handler((int) regs);
 }
 
@@ -212,6 +214,7 @@ asmlinkage void do_fast_IRQ(int irq)
 {
        struct sigaction * sa = irq + irq_sigaction;
 
+       kstat.interrupts++;
        sa->sa_handler(irq);
 }
 
index 537420750399df74b48f46c1d5c53738f3fa33af..6d94afd86f7a99d0f552ff91bc0c4effe931dc71 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
+#include <linux/kernel_stat.h>
 #include <linux/sys.h>
 #include <linux/fdreg.h>
 #include <linux/errno.h>
@@ -56,6 +57,7 @@ long time_adj = 0;              /* tick adjust (scaled 1 / HZ) */
 long time_reftime = 0;          /* time at last adjustment (s) */
 
 long time_adjust = 0;
+long time_adjust_step = 0;
 
 int need_resched = 0;
 
@@ -100,6 +102,9 @@ struct {
        short b;
        } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
 
+struct kernel_stat kstat =
+       { 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
 /*
  * int 0x80 entry points.. Moved away from the header file, as
  * iBCS2 may also want to use the '<linux/sys.h>' headers..
@@ -138,7 +143,7 @@ sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
 sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
 sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
 sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
-sys_getpgid, sys_fchdir };
+sys_getpgid, sys_fchdir, sys_bdflush };
 
 /* So we don't have to do any more manual updating.... */
 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
@@ -275,6 +280,8 @@ confuse_gcc2:
                for_each_task(p)
                        p->counter = (p->counter >> 1) + p->priority;
        }
+       if(current != next)
+               kstat.context_swtch++;
        switch_to(next);
        /* Now maybe reload the debug registers */
        if(current->debugreg[7]){
@@ -592,41 +599,38 @@ static void do_timer(struct pt_regs * regs)
        if (time_phase < -FINEUSEC) {
                ltemp = -time_phase >> SHIFT_SCALE;
                time_phase += ltemp << SHIFT_SCALE;
-               xtime.tv_usec += tick - ltemp;
+               xtime.tv_usec += tick + time_adjust_step - ltemp;
        }
        else if (time_phase > FINEUSEC) {
                ltemp = time_phase >> SHIFT_SCALE;
                time_phase -= ltemp << SHIFT_SCALE;
-               xtime.tv_usec += tick + ltemp;
+               xtime.tv_usec += tick + time_adjust_step + ltemp;
        } else
-               xtime.tv_usec += tick;
+               xtime.tv_usec += tick + time_adjust_step;
 
        if (time_adjust)
        {
            /* We are doing an adjtime thing. 
-            */
-
-           /* Limit the amount of the step for *next* tick to be
+            *
+            * Modify the value of the tick for next time.
+            * Note that a positive delta means we want the clock
+            * to run fast. This means that the tick should be bigger
+            *
+            * Limit the amount of the step for *next* tick to be
             * in the range -tickadj .. +tickadj
             */
             if (time_adjust > tickadj)
-              ltemp = tickadj;
+              time_adjust_step = tickadj;
             else if (time_adjust < -tickadj)
-              ltemp = -tickadj;
+              time_adjust_step = -tickadj;
             else
-              ltemp = time_adjust;
+              time_adjust_step = time_adjust;
             
-           /* Reduce the amount of time left by this step */
-           time_adjust -= ltemp;
-
-           /* Modify the value of the tick for next time.
-            * Note that a positive delta means we want the clock
-            * to run fast. This means that the tick should be bigger
-            */
-           tick = 1000000/HZ + ltemp;
+           /* Reduce by this step the amount of time left  */
+           time_adjust -= time_adjust_step;
        }
        else
-           tick = 1000000/HZ;
+           time_adjust_step = 0;
 
        if (xtime.tv_usec >= 1000000) {
            xtime.tv_usec -= 1000000;
@@ -638,6 +642,12 @@ static void do_timer(struct pt_regs * regs)
        calc_load();
        if ((VM_MASK & regs->eflags) || (3 & regs->cs)) {
                current->utime++;
+               if(current != task[0]) {
+                       if(current->priority != 15)
+                               kstat.cpu_nice++;
+                       else
+                               kstat.cpu_user++;
+               }
                /* Update ITIMER_VIRT for current task if not in a system call */
                if (current->it_virt_value && !(--current->it_virt_value)) {
                        current->it_virt_value = current->it_virt_incr;
@@ -645,6 +655,8 @@ static void do_timer(struct pt_regs * regs)
                }
        } else {
                current->stime++;
+               if(current != task[0])
+                       kstat.cpu_system++;
 #ifdef CONFIG_PROFILE
                if (prof_buffer && current != task[0]) {
                        unsigned long eip = regs->eip;
index 0542096bc142a311e020a2cc04cf5ef66b9c78f3..3161e8f9079938feb97aaf3174fa29d3a7c76ca5 100644 (file)
@@ -321,6 +321,11 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
          if (txc.status < TIME_OK || txc.status > TIME_BAD)
            return -EINVAL;
 
+       /* if the quartz is off by more than 10% something is VERY wrong ! */
+       if (txc.mode & ADJ_TICK)
+         if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
+           return -EINVAL;
+
        cli();
 
        /* Save for later - semantics of adjtime is to return old value */
@@ -336,7 +341,7 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
                time_status = txc.status;
 
            if (txc.mode & ADJ_FREQUENCY)
-               time_freq = txc.frequency;
+               time_freq = txc.frequency << (SHIFT_KF - 16);
 
            if (txc.mode & ADJ_MAXERROR)
                time_maxerror = txc.maxerror;
@@ -374,9 +379,12 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
                  else if (time_freq < -ltemp)
                    time_freq = -ltemp;
                }
+           if (txc.mode & ADJ_TICK)
+             tick = txc.tick;
+
        }
        txc.offset         = save_adjust;
-       txc.frequency      = time_freq;
+       txc.frequency      = ((time_freq+1) >> (SHIFT_KF - 16));
        txc.maxerror       = time_maxerror;
        txc.esterror       = time_esterror;
        txc.status         = time_status;
@@ -384,6 +392,7 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
        txc.precision      = time_precision;
        txc.tolerance      = time_tolerance;
        txc.time           = xtime;
+       txc.tick           = tick;
 
        sti();
 
index 8adc9eb3784ccf6bd4d026e5b83358d5b6582154..885abf1d792e1198c2475ef52ce8e1e3fb9b82ff 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/head.h>
 #include <linux/kernel.h>
+#include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/stat.h>
@@ -76,6 +77,10 @@ void rw_swap_page(int rw, unsigned long entry, char * buf)
        }
        while (set_bit(offset,p->swap_lockmap))
                sleep_on(&lock_queue);
+       if (rw == READ)
+               kstat.pswpin++;
+       else
+               kstat.pswpout++;
        if (p->swap_device) {
                ll_rw_page(rw,p->swap_device,offset,buf);
        } else if (p->swap_file) {
index e85edeca48063f4fdfad16c6f3b2f2be64af5dbc..c81209a47bb27fe2eead3ef89c4dd19c4f1feea7 100644 (file)
@@ -74,7 +74,7 @@ packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
   }
   sk->rmem_alloc += skb->mem_len;
   skb_queue_tail(&sk->rqueue,skb);
-  wake_up(sk->sleep);
+  wake_up_interruptible(sk->sleep);
   release_sock(sk);
   return(0);
 }
index 506e95da1d74a3f3a44a274e1e106a5ec32e4386..68f7f36a10e954431eee32ac8d3c2e78b9b0e43d 100644 (file)
@@ -410,7 +410,7 @@ void kfree_skb(struct sk_buff *skb, int rw)
                        else
                                skb->sk->wmem_alloc-=skb->mem_len;
                        if(!skb->sk->dead)
-                       wake_up(skb->sk->sleep);
+                       wake_up_interruptible(skb->sk->sleep);
                        kfree_skbmem(skb->mem_addr,skb->mem_len);
                }
        }
@@ -471,11 +471,11 @@ void skb_kept_by_device(struct sk_buff *skb)
 void skb_device_release(struct sk_buff *skb, int mode)
 {
        unsigned long flags;
+
        save_flags(flags);
-       skb->lock--;
-       if(skb->lock==0)
-       {
-               if(skb->free==1)
+       cli();
+       if (!--skb->lock) {
+               if (skb->free==1)
                        kfree_skb(skb,mode);
        }
        restore_flags(flags);
index 37efd6feda7d5620df5ff47c1648a2c2bde39240..643361dbac08fc6bfc141b9e1a0b225fd373d92e 100644 (file)
@@ -741,13 +741,13 @@ inet_listen(struct socket *sock, int backlog)
 static void def_callback1(struct sock *sk)
 {
        if(!sk->dead)
-               wake_up(sk->sleep);
+               wake_up_interruptible(sk->sleep);
 }
 
 static void def_callback2(struct sock *sk,int len)
 {
        if(!sk->dead)
-               wake_up(sk->sleep);
+               wake_up_interruptible(sk->sleep);
 }
 
 
@@ -870,7 +870,7 @@ inet_create(struct socket *sock, int protocol)
   sk->dead = 0;
   sk->ack_timed = 0;
   sk->send_tmp = NULL;
-  sk->mss = 0; /* we will try not to send any packets smaller than this. */
+  sk->user_mss = 0;
   sk->debug = 0;
 
   /* this is how many unacked bytes we will accept for this socket.  */
index ee6fb0e1fd990bacd1d125ec3809f2e322a283f3..2133f4db650f04af731bedaedbf435c36c26f735 100644 (file)
@@ -101,8 +101,11 @@ struct sock {
   unsigned short               max_unacked;
   unsigned short               window;
   unsigned short               bytes_rcv;
-  unsigned short               mtu;
-  unsigned short               max_window;
+/* mss is min(mtu, max_window) */
+  unsigned short               mtu;       /* mss negotiated in the syn's */
+  volatile unsigned short      mss;       /* current eff. mss - can change */
+  volatile unsigned short      user_mss;  /* mss requested by user in ioctl */
+  volatile unsigned short      max_window;
   unsigned short               num;
   volatile unsigned short      cong_window;
   volatile unsigned short      cong_count;
@@ -110,7 +113,6 @@ struct sock {
   volatile unsigned short      packets_out;
   volatile unsigned short      urg;
   volatile unsigned short      shutdown;
-  unsigned short               mss;
   volatile unsigned long       rtt;
   volatile unsigned long       mdev;
   volatile unsigned long       rto;
index 9c1223b94478ae294c9ba15a8d64ac56971df87a..b0d60745488f5c6a710d71e8d50f1981d458adba 100644 (file)
 
 #define SEQ_TICK 3
 unsigned long seq_offset;
-#define LOCALNET_BIGPACKETS
+#define SUBNETSARELOCAL
 
 static __inline__ int 
 min(unsigned int a, unsigned int b)
@@ -180,14 +180,14 @@ static int tcp_select_window(struct sock *sk)
 
 /*
  * two things are going on here.  First, we don't ever offer a
- * window less than min(sk->mtu, MAX_WINDOW/2).  This is the
+ * window less than min(sk->mss, MAX_WINDOW/2).  This is the
  * receiver side of SWS as specified in RFC1122.
  * Second, we always give them at least the window they
  * had before, in order to avoid retracting window.  This
  * is technically allowed, but RFC1122 advises against it and
  * in practice it causes trouble.
  */
-       if (new_window < min(sk->mtu, MAX_WINDOW/2) ||
+       if (new_window < min(sk->mss, MAX_WINDOW/2) ||
            new_window < sk->window)
          return(sk->window);
        return(new_window);
@@ -420,7 +420,7 @@ tcp_select(struct sock *sk, int sel_type, select_table *wait)
                 * Hack so it will probably be able to write
                 * something if it says it's ok to write.
                 */
-               if (sk->prot->wspace(sk) >= sk->mtu) {
+               if (sk->prot->wspace(sk) >= sk->mss) {
                        release_sock(sk);
                        /* This should cause connect to work ok. */
                        if (sk->state == TCP_SYN_RECV ||
@@ -656,10 +656,7 @@ static struct sk_buff * dequeue_partial(struct sock * sk)
        save_flags(flags);
        cli();
        skb = sk->send_tmp;
-       if (skb) {
-               sk->send_tmp = skb->next;
-               skb->next = NULL;
-       }
+       sk->send_tmp = NULL;
        restore_flags(flags);
        return skb;
 }
@@ -669,7 +666,6 @@ static void enqueue_partial(struct sk_buff * skb, struct sock * sk)
        struct sk_buff * tmp;
        unsigned long flags;
 
-       skb->next = NULL;
        save_flags(flags);
        cli();
        tmp = sk->send_tmp;
@@ -888,6 +884,18 @@ tcp_write(struct sock *sk, unsigned char *from,
                sti();
        }
 
+/*
+ * The following code can result in copy <= if sk->mss is ever
+ * decreased.  It shouldn't be.  sk->mss is min(sk->mtu, sk->max_window).
+ * sk->mtu is constant once SYN processing is finished.  I.e. we
+ * had better not get here until we've seen his SYN and at least one
+ * valid ack.  (The SYN sets sk->mtu and the ack sets sk->max_window.)
+ * But ESTABLISHED should guarantee that.  sk->max_window is by definition
+ * non-decreasing.  Note that any ioctl to set user_mss must be done
+ * before the exchange of SYN's.  If the initial ack from the other
+ * end has a window of 0, max_window and thus mss will both be 0.
+ */
+
        /* Now we need to check if we have a half built packet. */
        if ((skb = dequeue_partial(sk)) != NULL) {
                int hdrlen;
@@ -896,11 +904,9 @@ tcp_write(struct sock *sk, unsigned char *from,
                hdrlen = ((unsigned long)skb->h.th - (unsigned long)skb->data)
                         + sizeof(struct tcphdr);
 
-               /* If sk->mtu has been changed this could cause problems. */
-
                /* Add more stuff to the end of skb->len */
                if (!(flags & MSG_OOB)) {
-                       copy = min(sk->mtu - (skb->len - hdrlen), len);
+                       copy = min(sk->mss - (skb->len - hdrlen), len);
                        /* FIXME: this is really a bug. */
                        if (copy <= 0) {
                          printk("TCP: **bug**: \"copy\" <= 0!!\n");
@@ -915,7 +921,7 @@ tcp_write(struct sock *sk, unsigned char *from,
                        sk->send_seq += copy;
                      }
                enqueue_partial(skb, sk);
-               if ((skb->len - hdrlen) >= sk->mtu || (flags & MSG_OOB)) {
+               if ((skb->len - hdrlen) >= sk->mss || (flags & MSG_OOB)) {
                  tcp_send_partial(sk);
                }
                continue;
@@ -928,24 +934,26 @@ tcp_write(struct sock *sk, unsigned char *from,
         *   silly window prevention, as specified in RFC1122.
         *   (Note that this is diffferent than earlier versions of
         *   SWS prevention, e.g. RFC813.).  What we actually do is 
-        *   use the whole MTU.  Since the results in the right
+        *   use the whole MSS.  Since the results in the right
         *   edge of the packet being outside the window, it will
         *   be queued for later rather than sent.
         */
 
        copy = diff(sk->window_seq, sk->send_seq);
-       if (sk->max_window > 1) {
-         if (copy < (sk->max_window >> 1))
-           copy = sk->mtu;
-       } else  /* no max_window yet, punt this test */
-         copy = sk->mtu;       
-       copy = min(copy, sk->mtu);
+       /* what if max_window == 1?  In that case max_window >> 1 is 0.
+        * however in that case copy == max_window, so it's OK to use 
+        * the window */
+       if (copy < (sk->max_window >> 1))
+         copy = sk->mss;
+       copy = min(copy, sk->mss);
        copy = min(copy, len);
 
   /* We should really check the window here also. */
-       if (sk->packets_out && copy < sk->mtu && !(flags & MSG_OOB)) {
+       if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) {
        /* We will release the socket incase we sleep here. */
          release_sock(sk);
+         /* NB: following must be mtu, because mss can be increased.
+          * mss is always <= mtu */
          skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header + sizeof(*skb), 0, GFP_KERNEL);
          sk->inuse = 1;
          send_tmp = skb;
@@ -1204,6 +1212,14 @@ cleanup_rbuf(struct sock *sk)
         * the user reads some more.
         */
        sk->ack_backlog++;
+/*
+ * It's unclear whether to use sk->mtu or sk->mss here.  They differ only
+ * if the other end is offering a window smaller than the agreed on MSS
+ * (called sk->mtu here).  In theory there's no connection between send
+ * and receive, and so no reason to think that they're going to send
+ * small packets.  For the moment I'm using the hack of reducing the mss
+ * only on the send side, so I'm putting mtu here.
+ */
        if ((sk->prot->rspace(sk) > (sk->window - sk->bytes_rcv + sk->mtu))) {
                /* Send an ack right now. */
                tcp_read_wakeup(sk);
@@ -1741,7 +1757,11 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
 
 
 /*
- *     Look for tcp options. Parses everything but only knows about MSS
+ *     Look for tcp options. Parses everything but only knows about MSS.
+ *      This routine is always called with the packet containing the SYN.
+ *      However it may also be called with the ack to the SYN.  So you
+ *      can't assume this is always the SYN.  It's always called after
+ *      we have set up sk->mtu to our own MTU.
  */
  
 static void
@@ -1749,6 +1769,7 @@ tcp_options(struct sock *sk, struct tcphdr *th)
 {
   unsigned char *ptr;
   int length=(th->doff*4)-sizeof(struct tcphdr);
+  int mss_seen = 0;
     
   ptr = (unsigned char *)(th + 1);
   
@@ -1770,9 +1791,10 @@ tcp_options(struct sock *sk, struct tcphdr *th)
                        switch(opcode)
                        {
                                case TCPOPT_MSS:
-                                       if(opsize==4)
+                                       if(opsize==4 && th->syn)
                                        {
                                                sk->mtu=min(sk->mtu,ntohs(*(unsigned short *)ptr));
+                                               mss_seen = 1;
                                        }
                                        break;
                                /* Add other options here as people feel the urge to implement stuff like large windows */
@@ -1781,7 +1803,11 @@ tcp_options(struct sock *sk, struct tcphdr *th)
                        length-=opsize;
        }
   }
-
+  if (th->syn) {
+    if (! mss_seen)
+      sk->mtu=min(sk->mtu, 536);  /* default MSS if none sent */
+  }
+  sk->mss = min(sk->max_window, sk->mtu);
 }
 
 static inline unsigned long default_mask(unsigned long dst)
@@ -1888,6 +1914,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
   newsk->state = TCP_SYN_RECV;
   newsk->timeout = 0;
   newsk->send_seq = jiffies * SEQ_TICK - seq_offset;
+  newsk->window_seq = newsk->send_seq;
   newsk->rcv_ack_seq = newsk->send_seq;
   newsk->urg =0;
   newsk->retransmits = 0;
@@ -1919,16 +1946,18 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
   newsk->ip_tos=skb->ip_hdr->tos;
 
 /* use 512 or whatever user asked for */
-/* note use of sk->mss, since user has no direct access to newsk */
-  if (sk->mss)
-    newsk->mtu = sk->mss;
+/* note use of sk->user_mss, since user has no direct access to newsk */
+  if (sk->user_mss)
+    newsk->mtu = sk->user_mss;
   else {
-#ifdef LOCALNET_BIGPACKETS
-    if ((saddr & default_mask(saddr)) == (daddr & default_mask(daddr)))
-      newsk->mtu = MAX_WINDOW;
-    else
+#ifdef SUBNETSARELOCAL
+    if ((saddr ^ daddr) & default_mask(saddr))
+#else
+    if ((saddr ^ daddr) & dev->pa_mask)
 #endif
       newsk->mtu = 576 - HEADER_SIZE;
+    else
+      newsk->mtu = MAX_WINDOW;
   }
 /* but not bigger than device MTU */
   newsk->mtu = min(newsk->mtu, dev->mtu - HEADER_SIZE);
@@ -2261,8 +2290,10 @@ tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
          "sk->rcv_ack_seq=%d, sk->window_seq = %d\n",
          ack, ntohs(th->window), sk->rcv_ack_seq, sk->window_seq));
 
-  if (ntohs(th->window) > sk->max_window)
+  if (ntohs(th->window) > sk->max_window) {
        sk->max_window = ntohs(th->window);
+       sk->mss = min(sk->max_window, sk->mtu);
+  }
 
   if (sk->retransmits && sk->timeout == TIME_KEEPOPEN)
        sk->retransmits = 0;
@@ -2804,7 +2835,8 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
        /*
         * This is important.  If we don't have much room left,
         * we need to throw out a few packets so we have a good
-        * window.
+        * window.  Note that mtu is used, not mss, because mss is really
+        * for the send side.  He could be sending us stuff as large as mtu.
         */
        while (sk->prot->rspace(sk) < sk->mtu) {
                skb1 = skb_peek(&sk->rqueue);
@@ -3026,6 +3058,7 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
   sk->inuse = 1;
   sk->daddr = sin.sin_addr.s_addr;
   sk->send_seq = jiffies * SEQ_TICK - seq_offset;
+  sk->window_seq = sk->send_seq;
   sk->rcv_ack_seq = sk->send_seq -1;
   sk->err = 0;
   sk->dummy_th.dest = sin.sin_port;
@@ -3070,16 +3103,17 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
   t1->doff = 6;
 
 /* use 512 or whatever user asked for */
-  if (sk->mss)
-    sk->mtu = sk->mss;
+  if (sk->user_mss)
+    sk->mtu = sk->user_mss;
   else {
-#ifdef LOCALNET_BIGPACKETS
-    if ((sk->saddr & default_mask(sk->saddr)) == 
-       (sk->daddr & default_mask(sk->daddr)))
-      sk->mtu = MAX_WINDOW;
-    else
+#ifdef SUBNETSARELOCAL
+    if ((sk->saddr ^ sk->daddr) & default_mask(sk->saddr))
+#else
+    if ((sk->saddr ^ sk->daddr) & dev->pa_mask)
 #endif
       sk->mtu = 576 - HEADER_SIZE;
+    else
+      sk->mtu = MAX_WINDOW;
   }
 /* but not bigger than device MTU */
   sk->mtu = min(sk->mtu, dev->mtu - HEADER_SIZE);
@@ -3487,7 +3521,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
                        sk->shutdown = SHUTDOWN_MASK;
                        tcp_reset(daddr, saddr,  th, sk->prot, opt, dev);
                        if (!sk->dead) {
-                               wake_up(sk->sleep);
+                               wake_up_interruptible(sk->sleep);
                        }
                        kfree_skb(skb, FREE_READ);
                        release_sock(sk);
@@ -3552,6 +3586,20 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
                                        sk->state_change(sk);
                                }
 
+                               /*
+                                * We've already processed his first
+                                * ack.  In just about all cases that
+                                * will have set max_window.  This is
+                                * to protect us against the possibility
+                                * that the initial window he sent was 0.
+                                * This must occur after tcp_options, which
+                                * sets sk->mtu.
+                                */
+                               if (sk->max_window == 0) {
+                                 sk->max_window = 32;
+                                 sk->mss = min(sk->max_window, sk->mtu);
+                               }
+
                                /*
                                 * Now process the rest like we were
                                 * already in the established state.
@@ -3775,9 +3823,15 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int op
        switch(optname)
        {
                case TCP_MAXSEG:
-                       if(val<200||val>2048 || val>sk->mtu)
+/*                     if(val<200||val>2048 || val>sk->mtu) */
+/*
+ * values greater than interface MTU won't take effect.  however at
+ * the point when this call is done we typically don't yet know
+ * which interface is going to be used
+ */
+                       if(val<1||val>MAX_WINDOW)
                                return -EINVAL;
-                       sk->mss=val;
+                       sk->user_mss=val;
                        return 0;
                case TCP_NODELAY:
                        sk->nonagle=(val==0)?0:1;
@@ -3797,7 +3851,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *o
        switch(optname)
        {
                case TCP_MAXSEG:
-                       val=sk->mss;
+                       val=sk->user_mss;
                        break;
                case TCP_NODELAY:
                        val=sk->nonagle;        /* Until Johannes stuff is in */
index 7c83fbd350f8bd88806dc33aff17bf1165de16f5..bc952568f20c5858c6f5d0cc8c6cb5a3d2497e1a 100644 (file)
@@ -41,7 +41,7 @@
                                 * 90 minutes to time out.
                                 */
 
-#define TCP_TIMEOUT_LEN        (5*60*HZ)/* should be about 5 mins              */
+#define TCP_TIMEOUT_LEN        (15*60*HZ) /* should be about 15 mins           */
 #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to sucessfully 
                                  * close the socket, about 60 seconds  */
 #define TCP_ACK_TIME   3000    /* time to delay before sending an ACK  */
index 73d4b24087afe6f189326946b8974d298f4b28e0..4cd4515818087bc97c437711e7f8087200510ff3 100644 (file)
@@ -101,14 +101,20 @@ net_timer (unsigned long data)
   sk->inuse = 1;
 
   DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
-  if (sk->keepopen)
+  if (sk->wfront && 
+      before(sk->window_seq, sk->wfront->h.seq) &&
+      sk->send_head == NULL &&
+      sk->ack_backlog == 0 &&
+      sk->state != TCP_TIME_WAIT)
+    reset_timer(sk, TIME_PROBE0, sk->rto);
+  else if (sk->keepopen)
     reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
 
   /* Always see if we need to send an ack. */
   if (sk->ack_backlog) {
     sk->prot->read_wakeup (sk);
     if (! sk->dead)
-      wake_up (sk->sleep);
+      wake_up_interruptible (sk->sleep);
   }
 
   /* Now we need to figure out why the socket was on the timer. */
@@ -143,7 +149,7 @@ net_timer (unsigned long data)
        /* Kill the ARP entry in case the hardware has changed. */
        arp_destroy_maybe (sk->daddr);
        if (!sk->dead)
-         wake_up (sk->sleep);
+         wake_up_interruptible (sk->sleep);
        sk->shutdown = SHUTDOWN_MASK;
        reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
        release_sock (sk);
@@ -213,7 +219,7 @@ net_timer (unsigned long data)
          if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) {
            sk->state = TCP_TIME_WAIT;
            if (!sk->dead)
-             wake_up (sk->sleep);
+             wake_up_interruptible (sk->sleep);
            release_sock (sk);
          } else {
            sk->prot->close (sk, 1);
index 6caa65b02d032ba25a26315b8ee6ba1c0fc8343d..805e7c6ec7c3b247280d390cf03d6891c911f2f5 100644 (file)
@@ -222,7 +222,7 @@ static inline void
 sock_release_peer(struct socket *peer)
 {
   peer->state = SS_DISCONNECTING;
-  wake_up(peer->wait);
+  wake_up_interruptible(peer->wait);
 }
 
 
@@ -253,7 +253,7 @@ sock_release(struct socket *sock)
   if (peersock) sock_release_peer(peersock);
   inode = SOCK_INODE(sock);
   sock->state = SS_FREE;               /* this really releases us */
-  wake_up(&socket_wait_free);
+  wake_up_interruptible(&socket_wait_free);
 
   /* We need to do this. If sock alloc was called we already have an inode. */
   iput(inode);
@@ -391,7 +391,7 @@ sock_awaitconn(struct socket *mysock, struct socket *servsock)
    * Wake up server, then await connection. server will set state to
    * SS_CONNECTED if we're connected.
    */
-  wake_up(servsock->wait);
+  wake_up_interruptible(servsock->wait);
   if (mysock->state != SS_CONNECTED) {
        interruptible_sleep_on(mysock->wait);
        if (mysock->state != SS_CONNECTED &&
index dff2bbeb215dac92ff702c2a6e673d430b4d8434..6ab4e835d2076407eed2d2ec4b6ef201e6fdbd05 100644 (file)
@@ -554,7 +554,7 @@ unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
   UN_DATA(newsock)->peerupd           = UN_DATA(clientsock);
   UN_DATA(newsock)->sockaddr_un        = UN_DATA(sock)->sockaddr_un;
   UN_DATA(newsock)->sockaddr_len       = UN_DATA(sock)->sockaddr_len;
-  wake_up(clientsock->wait);
+  wake_up_interruptible(clientsock->wait);
   return(0);
 }
 
@@ -646,7 +646,8 @@ unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
        upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
        ubuf += cando;
        todo -= cando;
-       if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
+       if (sock->state == SS_CONNECTED)
+               wake_up_interruptible(sock->conn->wait);
        avail = UN_BUF_AVAIL(upd);
   } while(todo && avail);
   unix_unlock(upd);
@@ -731,7 +732,8 @@ unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
        pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
        ubuf += cando;
        todo -= cando;
-       if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
+       if (sock->state == SS_CONNECTED)
+               wake_up_interruptible(sock->conn->wait);
        space = UN_BUF_SPACE(pupd);
   } while(todo && space);
   unix_unlock(pupd);