Commit f614125e authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14y

parent 3448e1a6
VERSION = 0.99
PATCHLEVEL = 14
ALPHA = x
ALPHA = y
all: Version zImage
......
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
......@@ -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) {
......
......@@ -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.
......@@ -57,6 +57,11 @@
* 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
......@@ -68,17 +73,14 @@
*
* 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
......@@ -125,7 +127,7 @@
#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
#include "blk.h"
#define VERSION "1.1"
#define VERSION "1.2"
#define SBPCD_DEBUG
......@@ -143,7 +145,7 @@
#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);
......
......@@ -14,6 +14,11 @@
* '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.
*
......@@ -23,8 +28,17 @@
* 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
......@@ -32,11 +46,6 @@
* 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>
......@@ -45,12 +54,12 @@
#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;
}
......@@ -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,
......
#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
/*
* 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>
......@@ -25,25 +24,21 @@
#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;
......
......@@ -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 */
......
......@@ -49,13 +49,13 @@
#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
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -12,7 +12,11 @@
#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 @@ struct inode * __iget(struct super_block * sb, int nr, int crossmntp)
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;
}
......
......@@ -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));
}
/*
......
......@@ -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;
......
......@@ -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])))
......
......@@ -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;
......
......@@ -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 */
#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 */
#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
......@@ -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)();
......
......@@ -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 */
/*
......
......@@ -140,6 +140,7 @@
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
extern int errno;
......
......@@ -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);
}
......
......@@ -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 @@ asmlinkage void schedule(void)
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;
......
......@@ -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();
......
......@@ -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) {
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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;
......
This diff is collapsed.
......@@ -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 */
......
......@@ -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);
......
......@@ -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 &&
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment