aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@klaava.Helsinki.FI>1992-09-20 17:19:56 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:07 -0400
commit6969da2918ad2edd45dcf9e65ea2db837179ce9c (patch)
tree6d2cc521fc9f2bc90f27dce5da11a1d3538581bd
parentca7e955d618e12c34ebc6b644270a1e8f96c046e (diff)
downloadarchive-6969da2918ad2edd45dcf9e65ea2db837179ce9c.tar.gz
patchlevel 6v0.97-pl6
You all know what the subject line means by now: in case you want to track my kernel versions, the weekly patch is available at nic.funet.fi, pub/OS/Linux/testing/Linus. This patch does not contain any major bug-fixes: it corrects named pipes that broke with pl5, and has some minor changes in the IO-instructions and the hd-driver, but those shouldn't matter for most of you. It does contain all the scsi-patches that I've gotten so far, so if the bootup sequence died on you in the scsi code, pl6 should correct this. The major part of the patch is tytso's serial line changes, making the tty structures dynamic. No more NR_PTY's - the number of pty's is now bounded only by the minor number setup (max 64 pty's) or the amount of memory available (opening a pty requires a page of memory for tty queues). Similarly for serial lines. The above just means that while pl6 can be useful, the changes to pl5 aren't big enough to worry about. Most people don't use named pipes, it seems, and the other changes are either cosmetic or hardware-dependent. I still hope people upgrade, if only so that I can get new bug-reports. I had hoped to release 0.98 this weekend, but studies and the scsi/hd problems put an end to that. 0.98 should be out next weekend or so. Expect the tcp/ip subdirectory and possibly some mm changes. Linus
-rw-r--r--Makefile8
-rw-r--r--boot/setup.S6
-rw-r--r--fs/ext/inode.c1
-rw-r--r--fs/ext/namei.c1
-rw-r--r--fs/inode.c1
-rw-r--r--fs/minix/inode.c1
-rw-r--r--fs/minix/namei.c1
-rw-r--r--fs/super.c10
-rw-r--r--include/asm/io.h2
-rw-r--r--include/linux/serial.h151
-rw-r--r--include/linux/timer.h17
-rw-r--r--include/linux/tty.h161
-rw-r--r--kernel/blk_drv/hd.c5
-rw-r--r--kernel/blk_drv/scsi/aha1542.c48
-rw-r--r--kernel/blk_drv/scsi/scsi.c39
-rw-r--r--kernel/blk_drv/scsi/sd.c13
-rw-r--r--kernel/chr_drv/Makefile4
-rw-r--r--kernel/chr_drv/console.c52
-rw-r--r--kernel/chr_drv/keyboard.c734
-rw-r--r--kernel/chr_drv/pty.c47
-rw-r--r--kernel/chr_drv/serial.c850
-rw-r--r--kernel/chr_drv/tty_io.c455
-rw-r--r--kernel/chr_drv/tty_ioctl.c152
-rw-r--r--kernel/chr_drv/vt.c14
24 files changed, 1675 insertions, 1098 deletions
diff --git a/Makefile b/Makefile
index b426a5e..86ebcf1 100644
--- a/Makefile
+++ b/Makefile
@@ -46,12 +46,6 @@ KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKDB_NO
#
-# comment this line to turn off keyboard NUM LOCK
-#
-
-NUM_LOCK = -DKBD_NUMERIC_LOCK
-
-#
# comment this line if you don't want the emulation-code
#
@@ -118,7 +112,7 @@ linuxsubdirs: dummy
Version:
@./makever.sh
- @echo \#define UTS_RELEASE \"0.97.pl5-`cat .version`\" > tools/version.h
+ @echo \#define UTS_RELEASE \"0.97.pl6-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
diff --git a/boot/setup.S b/boot/setup.S
index 179cda8..fde9231 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -61,6 +61,12 @@ start:
mov ax,#0x5019
cmp bl,#0x10
je novga
+ mov ax,#0x1a00 ! Added check for EGA/VGA discrimination
+ int 0x10
+ mov bx,ax
+ mov ax,#0x5019
+ cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower
+ jne novga
call chsvga
novga: mov [14],ax
mov ah,#0x03 ! read cursor pos
diff --git a/fs/ext/inode.c b/fs/ext/inode.c
index f2f37b4..7998402 100644
--- a/fs/ext/inode.c
+++ b/fs/ext/inode.c
@@ -385,6 +385,7 @@ void ext_read_inode(struct inode * inode)
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
}
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index 5c7e7f4..c5a1d61 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -352,6 +352,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
if (S_ISBLK(mode) || S_ISCHR(mode))
diff --git a/fs/inode.c b/fs/inode.c
index 074f70a..b30fca0 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -194,6 +194,7 @@ struct inode * get_pipe_inode(void)
return NULL;
}
inode->i_count = 2; /* sum of readers/writers */
+ PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
inode->i_pipe = 1;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index ca9808b..7a188f1 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -344,6 +344,7 @@ void minix_read_inode(struct inode * inode)
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
}
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 10d8874..af8bef3 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -261,6 +261,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
if (S_ISBLK(mode) || S_ISCHR(mode))
diff --git a/fs/super.c b/fs/super.c
index 2e09dc2..7c7cd16 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -125,7 +125,7 @@ static struct super_block * read_super(int dev,char *name,int flags,void *data)
check_disk_change(dev);
if (s = get_super(dev))
return s;
- if (!(type=get_fs_type(name))) {
+ if (!(type = get_fs_type(name))) {
printk("get fs type failed %s\n",name);
return NULL;
}
@@ -137,13 +137,15 @@ static struct super_block * read_super(int dev,char *name,int flags,void *data)
}
s->s_dev = dev;
s->s_flags = flags;
- if (!type->read_super(s,data))
- return(NULL);
+ if (!type->read_super(s,data)) {
+ s->s_dev = 0;
+ return NULL;
+ }
s->s_dev = dev;
s->s_covered = NULL;
s->s_rd_only = 0;
s->s_dirt = 0;
- return(s);
+ return s;
}
static int do_umount(int dev)
diff --git a/include/asm/io.h b/include/asm/io.h
index 15cec31..7714173 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -15,7 +15,7 @@
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
#else
-#define __SLOW_DOWN_IO __asm__ __volatile__("inb $0x80,%%al":::"ax")
+#define __SLOW_DOWN_IO __asm__ __volatile__("inb $0x61,%%al":::"ax")
#endif
#ifdef REALLY_SLOW_IO
diff --git a/include/linux/serial.h b/include/linux/serial.h
new file mode 100644
index 0000000..7b47643
--- /dev/null
+++ b/include/linux/serial.h
@@ -0,0 +1,151 @@
+/*
+ * include/linux/serial.h
+ *
+ * Copyright (C) 1992 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+/*
+ * This our internal structure for keeping track of interrupt service
+ * routines.
+ */
+typedef struct struct_ISR *async_ISR;
+struct struct_ISR {
+ int irq; /* The IRQ assigned for this device */
+ int port; /* The base port for this device */
+ /* (use is ISR specific) */
+ void (*ISR_proc)(async_ISR, int);
+ int line; /* The serial line (or base */
+ /* serial line) */
+ int refcnt; /* How many devices are depending on */
+ /* this interrupt (multiport boards) */
+ async_ISR next_ISR; /* For the linked list */
+ async_ISR prev_ISR;
+};
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct async_struct {
+ int baud_base;
+ int port;
+ async_ISR ISR;
+ int flags;
+ int type;
+ struct tty_struct *tty;
+ unsigned long timer;
+ int timeout;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int line;
+};
+
+/*
+ * These are the UART port assignments, expressed as offsets from the base
+ * register. These assignments should hold for any serial port based on
+ * a 8250, 16450, or 16550(A).
+ */
+#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
+#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL 0 /* Out: Devisor Latch Low (DLAB=1) */
+#define UART_DLM 1 /* Out: Devisor Latch High (DLAB=1) */
+#define UART_IER 1 /* Out: Interrupt Enable Register */
+#define UART_IIR 2 /* In: Interrupt ID Register */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+/*
+ * These are the definitions for the FIFO Control Register
+ */
+#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
+#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
+#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
+#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
+#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
+#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
+#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
+#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
+
+#define UART_FCR_CLEAR_CMD (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)
+#define UART_FCR_SETUP_CMD (UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14)
+
+/*
+ * These are the definitions for the Line Control Register
+ *
+ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
+ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
+ */
+#define UART_LCR_DLAB 0x80 /* Devisor latch access bit */
+#define UART_LCR_SBC 0x40 /* Set break control */
+#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
+#define UART_LCR_EPAR 0x10 /* Even paraity select */
+#define UART_LCR_PARITY 0x08 /* Parity Enable */
+#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
+#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
+#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
+#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+
+/*
+ * These are the definitions for the Line Status Register
+ */
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define UART_LSR_FE 0x08 /* Frame error indicator */
+#define UART_LSR_PE 0x04 /* Parity error indicator */
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+
+/*
+ * These are the definitions for the Interrupt Indentification Register
+ */
+#define UART_IIR_PEND 0x01 /* Interrupt pending */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI 0x00 /* Modem status interrupt */
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Interrupt Enable Register
+ */
+#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
+#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
+#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
+#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
+
+/*
+ * These are the definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
+#define UART_MCR_OUT2 0x08 /* Out2 complement */
+#define UART_MCR_OUT1 0x04 /* Out1 complement */
+#define UART_MCR_RTS 0x02 /* RTS complement */
+#define UART_MCR_DTR 0x01 /* DTR complement */
+
+/*
+ * These are the definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
+#define UART_MSR_RI 0x40 /* Ring Indicator */
+#define UART_MSR_DSR 0x20 /* Data Set Ready */
+#define UART_MSR_CTS 0x10 /* Clear to Send */
+#define UART_MSR_DDCD 0x08 /* Delta DCD */
+#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
+#define UART_MSR_DDSR 0x02 /* Delta DSR */
+#define UART_MSR_DCTS 0x01 /* Delta CTS */
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 55d5bdd..d131adb 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -13,10 +13,8 @@
*
* BEEP_TIMER console beep timer
*
- * SERx_TIMER serial incoming characters timer
- *
- * SERx_TIMEOUT timeout for serial writes
- *
+ * RS_TIMER timer for the RS-232 ports
+ *
* HD_TIMER harddisk timer
*
* FLOPPY_TIMER floppy disk timer (not used right now)
@@ -28,16 +26,7 @@
#define BLANK_TIMER 0
#define BEEP_TIMER 1
-
-#define SER1_TIMER 2
-#define SER2_TIMER 3
-#define SER3_TIMER 4
-#define SER4_TIMER 5
-
-#define SER1_TIMEOUT 8
-#define SER2_TIMEOUT 9
-#define SER3_TIMEOUT 10
-#define SER4_TIMEOUT 11
+#define RS_TIMER 2
#define HD_TIMER 16
#define FLOPPY_TIMER 17
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 417ade5..f333ac8 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -3,10 +3,6 @@
/*
* 'tty.h' defines some structures used by tty_io.c and some defines.
- *
- * NOTE! Don't touch this without checking that nothing in rs_io.s or
- * con_io.s breaks. Some constants are hardwired into the system (mainly
- * offsets into 'tty_queue'
*/
#include <linux/termios.h>
@@ -14,8 +10,6 @@
#include <asm/system.h>
#define NR_CONSOLES 8
-#define NR_SERIALS 4
-#define NR_PTYS 4
/*
* These are set up by the setup-routine at boot-time:
@@ -58,7 +52,13 @@ extern struct screen_info screen_info;
*/
#define __DISABLED_CHAR '\0'
-#define TTY_BUF_SIZE 2048
+/*
+ * See comment for the tty_struct structure before changing
+ * TTY_BUF_SIZE. Actually, there should be different sized tty_queue
+ * structures for different purposes. 1024 bytes for the transmit
+ * queue is way overkill. TYT, 9/14/92
+ */
+#define TTY_BUF_SIZE 1024 /* Must be a power of 2 */
struct tty_queue {
unsigned long data;
@@ -69,11 +69,14 @@ struct tty_queue {
};
struct serial_struct {
- unsigned short type;
- unsigned short line;
- unsigned short port;
- unsigned short irq;
- struct tty_struct * tty;
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int reserved[8];
};
/*
@@ -85,6 +88,17 @@ struct serial_struct {
#define PORT_16550 3
#define PORT_16550A 4
+/*
+ * Definitions for async_struct (and serial_struct) flags field
+ */
+#define ASYNC_NOSCRATCH 0x0001 /* 16XXX UART with no scratch register */
+#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
+
+#define ASYNC_SPD_MASK 0x0030
+#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
+#define ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
+#define ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */
+
#define IS_A_CONSOLE(min) (((min) & 0xC0) == 0x00)
#define IS_A_SERIAL(min) (((min) & 0xC0) == 0x40)
#define IS_A_PTY(min) ((min) & 0x80)
@@ -92,6 +106,9 @@ struct serial_struct {
#define IS_A_PTY_SLAVE(min) (((min) & 0xC0) == 0xC0)
#define PTY_OTHER(min) ((min) ^ 0x40)
+#define SL_TO_DEV(line) ((line) | 0x40)
+#define DEV_TO_SL(min) ((min) & 0x3F)
+
#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a) ((a)->head == (a)->tail)
@@ -103,18 +120,18 @@ struct serial_struct {
extern void put_tty_queue(char c, struct tty_queue * queue);
extern int get_tty_queue(struct tty_queue * queue);
-#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
-#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
-#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
-#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL])
-#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
-#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
-#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
-#define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP])
+#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR])
+#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT])
+#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE])
+#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL])
+#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF])
+#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
+#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
+#define SUSPEND_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
-#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
-#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
-#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
+#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & f)
+#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & f)
+#define _O_FLAG(tty,f) ((tty)->termios->c_oflag & f)
#define L_CANON(tty) _L_FLAG((tty),ICANON)
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
@@ -139,36 +156,90 @@ extern int get_tty_queue(struct tty_queue * queue);
#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
-#define C_SPEED(tty) ((tty)->termios.c_cflag & CBAUD)
+#define C_SPEED(tty) ((tty)->termios->c_cflag & CBAUD)
#define C_HUP(tty) (C_SPEED((tty)) == B0)
+/*
+ * Where all of the state associated with a tty is kept while the tty
+ * is open. Since the termios state should be kept even if the tty
+ * has been closed --- for things like the baud rate, etc --- it is
+ * not stored here, but rather a pointer to the real state is stored
+ * here. Possible the winsize structure should have the same
+ * treatment, but (1) the default 80x24 is usually right and (2) it's
+ * most often used by a windowing system, which will set the correct
+ * size each time the window is created or resized anyway.
+ * IMPORTANT: since this structure is dynamically allocated, it must
+ * be no larger than 4096 bytes. Changing TTY_BUF_SIZE will change
+ * the size of this structure, and it needs to be done with care.
+ * - TYT, 9/14/92
+ */
struct tty_struct {
- struct termios termios;
+ struct termios *termios;
int pgrp;
int session;
unsigned char stopped:1, status_changed:1, packet:1;
unsigned char ctrl_status;
- short unused; /* make everything a multiple of 4. */
+ short line;
int flags;
int count;
struct winsize winsize;
+ int (*open)(struct tty_struct * tty, struct file * filp);
+ void (*close)(struct tty_struct * tty, struct file * filp);
void (*write)(struct tty_struct * tty);
+ int (*ioctl)(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned int arg);
+ void (*throttle)(struct tty_struct * tty, int status);
struct tty_struct *link;
- struct tty_queue *read_q;
- struct tty_queue *write_q;
- struct tty_queue *secondary;
+ struct tty_queue read_q;
+ struct tty_queue write_q;
+ struct tty_queue secondary;
};
/*
+ * These are the different types of thottle status which can be sent
+ * to the low-level tty driver. The tty_io.c layer is responsible for
+ * notifying the low-level tty driver of the following conditions:
+ * secondary queue full, secondary queue available, and read queue
+ * available. The low-level driver must send the read queue full
+ * command to itself, if it is interested in that condition.
+ *
+ * Note that the low-level tty driver may elect to ignore one or both
+ * of these conditions; normally, however, it will use ^S/^Q or some
+ * sort of hardware flow control to regulate the input to try to avoid
+ * overflow. While the low-level driver is responsible for all
+ * receiving flow control, note that the ^S/^Q handling (but not
+ * hardware flow control) is handled by the upper layer, in
+ * copy_to_cooked.
+ */
+#define TTY_THROTTLE_SQ_FULL 1
+#define TTY_THROTTLE_SQ_AVAIL 2
+#define TTY_THROTTLE_RQ_FULL 3
+#define TTY_THROTTLE_RQ_AVAIL 4
+
+/*
+ * This defines the low- and high-watermarks for the various conditions.
+ * Again, the low-level driver is free to ignore any of these, and has
+ * to implement RQ_THREHOLD_LW for itself if it wants it.
+ */
+#define SQ_THRESHOLD_LW 0
+#define SQ_THRESHOLD_HW 768
+#define RQ_THRESHOLD_LW 64
+#define RQ_THRESHOLD_HW 768
+
+/*
* so that interrupts won't be able to mess up the
* queues, copy_to_cooked must be atomic with repect
* to itself, as must tty->write. These are the flag
* bit-numbers. Use the set_bit() and clear_bit()
* macros to make it all atomic.
+ *
+ * These bits are used in the flags field of the tty structure.
*/
#define TTY_WRITE_BUSY 0
#define TTY_READ_BUSY 1
#define TTY_CR_PENDING 2
+#define TTY_SQ_THROTTLED 3
+#define TTY_RQ_THROTTLED 4
/*
* These have to be done with inline assembly: that way the bit-setting
@@ -199,16 +270,15 @@ extern inline int clear_bit(int nr, int * addr)
extern void tty_write_flush(struct tty_struct *);
extern void tty_read_flush(struct tty_struct *);
-extern struct tty_struct tty_table[];
-extern struct serial_struct serial_table[];
+extern struct tty_struct *tty_table[];
extern struct tty_struct * redirect;
extern int fg_console;
extern unsigned long video_num_columns;
extern unsigned long video_num_lines;
+extern struct wait_queue * keypress_wait;
-
-#define TTY_TABLE(nr) \
-(tty_table + ((nr) ? (((nr) < 64)? (nr)-1:(nr)) : fg_console))
+#define TTY_TABLE_IDX(nr) ((nr) ? (nr) : (fg_console+1))
+#define TTY_TABLE(nr) (tty_table[TTY_TABLE_IDX(nr)])
/* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
@@ -243,24 +313,23 @@ extern void spty_write(struct tty_struct * tty);
/* serial.c */
-extern int serial_open(unsigned int line, struct file * filp);
-extern void serial_close(unsigned int line, struct file * filp);
+extern int rs_open(struct tty_struct * tty, struct file * filp);
extern void change_speed(unsigned int line);
-extern void send_break(unsigned int line);
-extern int get_serial_info(unsigned int, struct serial_struct *);
-extern int set_serial_info(unsigned int, struct serial_struct *);
-extern int get_modem_info(unsigned int, unsigned int *);
-extern int set_modem_info(unsigned int, unsigned int, unsigned int *);
/* pty.c */
-extern int pty_open(unsigned int dev, struct file * filp);
-extern void pty_close(unsigned int dev, struct file * filp);
+extern int pty_open(struct tty_struct * tty, struct file * filp);
/* console.c */
-void update_screen(int new_console);
-void blank_screen(void);
-void unblank_screen(void);
+extern int con_open(struct tty_struct * tty, struct file * filp);
+extern void update_screen(int new_console);
+extern void blank_screen(void);
+extern void unblank_screen(void);
+
+/* vt.c */
+
+extern int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned int arg);
#endif
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index 77c76fc..3652c96 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -355,8 +355,8 @@ static void recal_intr(void)
*/
static void hd_times_out(void)
{
- sti();
DEVICE_INTR = NULL;
+ sti();
reset = 1;
if (!CURRENT)
return;
@@ -385,8 +385,9 @@ static void do_hd_request(void)
unsigned int sec,head,cyl,track;
unsigned int nsect;
+ if (DEVICE_INTR)
+ return;
repeat:
- DEVICE_INTR = NULL;
timer_active &= ~(1<<HD_TIMER);
sti();
INIT_REQUEST;
diff --git a/kernel/blk_drv/scsi/aha1542.c b/kernel/blk_drv/scsi/aha1542.c
index 6d974f9..0646496 100644
--- a/kernel/blk_drv/scsi/aha1542.c
+++ b/kernel/blk_drv/scsi/aha1542.c
@@ -72,6 +72,18 @@ static int aha1542_out(unchar *cmdp, int len)
return 1;
}
+static int aha1542_in(unchar *cmdp, int len)
+{
+ while (len--)
+ {
+ WAIT(STATUS, DF, DF, 0);
+ *cmdp++ = inb(DATA);
+ }
+ return 0;
+ fail:
+ printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
+ return 1;
+}
int makecode(unsigned hosterr, unsigned scsierr)
{
switch (hosterr) {
@@ -259,6 +271,7 @@ void aha1542_intr_handle(void)
int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
{
unchar ahacmd = CMD_START_SCSI;
+ unchar direction;
unchar *cmd = (unchar *) cmnd;
DEB(int i);
@@ -289,12 +302,18 @@ int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int buffle
return 0; /* we are still testing, so *don't* write */
#endif
memset(&ccb, 0, sizeof ccb);
-
+
ccb.cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
-
+
+ direction = 0;
+ if (*cmd == READ_10 || *cmd == READ_6)
+ direction = 8;
+ else if (*cmd == WRITE_10 || *cmd == WRITE_6)
+ direction = 16;
+
memcpy(ccb.cdb, cmd, ccb.cdblen);
ccb.op = 0; /* SCSI Initiator Command */
- ccb.idlun = (target&7)<<5; /* SCSI Target Id */
+ ccb.idlun = (target&7)<<5 | direction; /* SCSI Target Id */
ccb.rsalen = 12;
any2scsi(ccb.datalen, bufflen);
any2scsi(ccb.dataptr, buff);
@@ -369,6 +388,28 @@ void call_buh()
set_intr_gate(0x2b,&aha1542_interrupt);
}
+/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
+static void aha1542_query()
+{
+ static unchar inquiry_cmd[] = {CMD_INQUIRY };
+ static unchar inquiry_result[4];
+ int i;
+ i = inb(STATUS);
+ if (i & DF) {
+ i = inb(DATA);
+ printk("Stale data:%x ");
+ };
+ aha1542_out(inquiry_cmd, 1);
+ aha1542_in(inquiry_result, 4);
+ WAIT(INTRFLAGS, INTRMASK, HACC, 0);
+ while (0) {
+ fail:
+ printk("aha1542_detect: query card type\n");
+ }
+ aha1542_intr_reset();
+ printk("Inquiry:");
+ for(i=0;i<4;i++) printk("%x ",inquiry_result[i]);
+}
/* return non-zero on detection */
int aha1542_detect(int hostnum)
{
@@ -397,6 +438,7 @@ int aha1542_detect(int hostnum)
}
aha1542_intr_reset();
}
+ aha1542_query();
DEB(aha1542_stat());
setup_mailboxes();
diff --git a/kernel/blk_drv/scsi/scsi.c b/kernel/blk_drv/scsi/scsi.c
index a9b1758..28749ed 100644
--- a/kernel/blk_drv/scsi/scsi.c
+++ b/kernel/blk_drv/scsi/scsi.c
@@ -627,6 +627,27 @@ static int check_sense (int host)
return SUGGEST_RETRY;
}
+/* This function is the mid-level interrupt routine, which decides how
+ * to handle error conditions. Each invocation of this function must
+ * do one and *only* one of the following:
+ *
+ * (1) Call last_cmnd[host].done. This is done for fatal errors and
+ * normal completion, and indicates that the handling for this
+ * request is complete.
+ * (2) Call internal_cmnd to requeue the command. This will result in
+ * scsi_done being called again when the retry is complete.
+ * (3) Call scsi_request_sense. This asks the host adapter/drive for
+ * more information about the error condition. When the information
+ * is available, scsi_done will be called again.
+ * (4) Call reset(). This is sort of a last resort, and the idea is that
+ * this may kick things loose and get the drive working again. reset()
+ * automatically calls scsi_request_sense, and thus scsi_done will be
+ * called again once the reset is complete.
+ *
+ * If none of the above actions are taken, the drive in question
+ * will hang. If more than one of the above actions are taken by
+ * scsi_done, then unpredictable behavior will result.
+ */
static void scsi_done (int host, int result)
{
int status=0;
@@ -670,8 +691,11 @@ static void scsi_done (int host, int result)
internal_timeout[host] &= ~SENSE_TIMEOUT;
sti();
- if (!(last_cmnd[host].flags & WAS_RESET))
+ if (!(last_cmnd[host].flags & WAS_RESET))
+ {
reset(host);
+ return;
+ }
else
{
exit = (DRIVER_HARD | SUGGEST_ABORT);
@@ -768,9 +792,12 @@ static void scsi_done (int host, int result)
case RESERVATION_CONFLICT:
reset(host);
+ return;
+#if 0
exit = DRIVER_SOFT | SUGGEST_ABORT;
status = MAYREDO;
break;
+#endif
default:
printk ("Internal error %s %s \n"
"status byte = %d \n", __FILE__,
@@ -839,11 +866,13 @@ static void scsi_done (int host, int result)
if ((++last_cmnd[host].retries) < last_cmnd[host].allowed)
{
- if ((last_cmnd[host].retries >= (last_cmnd[host].allowed >> 1))
+ if ((last_cmnd[host].retries >= (last_cmnd[host].allowed >> 1))
&& !(last_cmnd[host].flags & WAS_RESET))
- reset(host);
- break;
-
+ {
+ reset(host);
+ break;
+ }
+
}
else
{
diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c
index e477020..dd3cc98 100644
--- a/kernel/blk_drv/scsi/sd.c
+++ b/kernel/blk_drv/scsi/sd.c
@@ -39,7 +39,7 @@ struct hd_struct sd[MAX_SD << 4];
int NR_SD=0;
Scsi_Disk rscsi_disks[MAX_SD];
static int sd_sizes[MAX_SD << 4] = {0, };
-static int this_count;
+static int this_count, total_count = 0;
static int the_result;
static char sense_buffer[255];
@@ -108,6 +108,13 @@ static void rw_intr (int host, int result)
if (!result) {
CURRENT->nr_sectors -= this_count;
+ total_count -= this_count;
+ if(total_count){
+ CURRENT->sector += this_count;
+ CURRENT->buffer += (this_count << 9);
+ do_sd_request();
+ return;
+ };
#ifdef DEBUG
printk("sd%d : %d sectors remain.\n", MINOR(CURRENT->dev), CURRENT->nr_sectors);
@@ -248,6 +255,10 @@ repeat:
this_count = CURRENT->nr_sectors;
else
this_count = (BLOCK_SIZE / 512);
+/* This is a temporary hack for the AHA1742. */
+ if(total_count == 0)
+ total_count = this_count;
+ this_count = 1; /* Take only 512 bytes at a time */
#ifdef DEBUG
printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(CURRENT->dev),
diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile
index 391ad88..484e9b6 100644
--- a/kernel/chr_drv/Makefile
+++ b/kernel/chr_drv/Makefile
@@ -24,10 +24,10 @@ chr_drv.a: $(OBJS)
sync
console.o: console.c
- $(CC) $(CFLAGS) $(NUM_LOCK) -c -o console.o console.c
+ $(CC) $(CFLAGS) -c -o console.o console.c
keyboard.o: keyboard.c
- $(CC) $(CFLAGS) $(KEYBOARD) $(NUM_LOCK) -c -o keyboard.o keyboard.c
+ $(CC) $(CFLAGS) $(KEYBOARD) -c -o keyboard.o keyboard.c
clean:
rm -f core *.o *.a tmp_make keyboard.s
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index a284597..af1d91f 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -7,9 +7,14 @@
/*
* console.c
*
- * This module implements the console io functions
+ * This module exports the console io functions:
+ *
* 'long con_init(long)'
- * 'void con_write(struct tty_queue * queue)'
+ * 'void con_open(struct tty_queue * queue, struct )'
+ * 'void update_screen(int new_console)'
+ * 'void blank_screen(void)'
+ * 'void unblank_screen(void)'
+ *
* Hopefully this will be a rather complete VT102 implementation.
*
* Beeping thanks to John T Kohl.
@@ -55,6 +60,7 @@ extern void set_leds(void);
extern unsigned char kapplic;
extern unsigned char ckmode;
extern unsigned char krepeat;
+extern unsigned char default_kleds;
extern unsigned char kleds;
extern unsigned char kmode;
extern unsigned char kraw;
@@ -187,13 +193,6 @@ static int console_blanked = 0;
#define kbdleds (vt_cons[currcons].vc_kbdleds)
#define vtmode (vt_cons[currcons].vt_mode)
-#if defined KBD_NUMERIC_LOCK
-#define NUMLED_DEFAULT 0x02
-
-#else
-#define NUMLED_DEFAULT 0
-#endif
-
#define SET(mode,fg,v) \
(mode) = (v); \
if (currcons == fg_console) \
@@ -612,7 +611,7 @@ static inline void set_cursor(int currcons)
static void respond_string(char * p, int currcons, struct tty_struct * tty)
{
while (*p) {
- put_tty_queue(*p,tty->read_q);
+ put_tty_queue(*p, &tty->read_q);
p++;
}
TTY_READ_FLUSH(tty);
@@ -628,19 +627,19 @@ static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
n /= 10;
} while(n && i < 3); /* We'll take no chances */
while (i--) {
- put_tty_queue(buff[i],tty->read_q);
+ put_tty_queue(buff[i], &tty->read_q);
}
/* caller must flush */
}
static void cursor_report(int currcons, struct tty_struct * tty)
{
- put_tty_queue('\033', tty->read_q);
- put_tty_queue('[', tty->read_q);
+ put_tty_queue('\033', &tty->read_q);
+ put_tty_queue('[', &tty->read_q);
respond_num(y + (decom ? top+1 : 1), currcons, tty);
- put_tty_queue(';', tty->read_q);
+ put_tty_queue(';', &tty->read_q);
respond_num(x+1, currcons, tty);
- put_tty_queue('R', tty->read_q);
+ put_tty_queue('R', &tty->read_q);
TTY_READ_FLUSH(tty);
}
@@ -873,7 +872,7 @@ static void reset_terminal(int currcons, int do_clear)
ckmode = 0;
kapplic = 0;
lfnlmode = 0;
- kleds = NUMLED_DEFAULT;
+ kleds = default_kleds;
kmode = 0;
set_leds();
} else {
@@ -881,7 +880,7 @@ static void reset_terminal(int currcons, int do_clear)
decckm = 0;
kbdapplic = 0;
lnm = 0;
- kbdleds = NUMLED_DEFAULT;
+ kbdleds = default_kleds;
kbdmode = 0;
}
@@ -906,13 +905,13 @@ void con_write(struct tty_struct * tty)
int c;
unsigned int currcons;
- wake_up(&tty->write_q->proc_list);
- currcons = tty - tty_table;
+ wake_up(&tty->write_q.proc_list);
+ currcons = tty->line - 1;
if (currcons >= NR_CONSOLES) {
- printk("con_write: illegal tty\n\r");
+ printk("con_write: illegal tty (%d)\n", currcons);
return;
}
- while (!tty->stopped && (c = get_tty_queue(tty->write_q)) >= 0) {
+ while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
if (state == ESnormal && translate[c]) {
if (need_wrap) {
cr(currcons);
@@ -1507,3 +1506,14 @@ void console_print(const char * b)
timer_active |= 1<<BLANK_TIMER;
}
}
+
+/*
+ * All we do is set the write and ioctl subroutines; later on maybe we'll
+ * dynamically allocate the console screen memory.
+ */
+int con_open(struct tty_struct *tty, struct file * filp)
+{
+ tty->write = con_write;
+ tty->ioctl = vt_ioctl;
+ return 0;
+}
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index acc88b7..e3f24a7 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -13,36 +13,42 @@
#include <linux/mm.h>
#include <linux/ptrace.h>
+/*
+ * The default IO slowdown is doing 'inb()'s from 0x61, which should be
+ * safe. But as that is the keyboard controller chip address, we do our
+ * slowdowns here by doing short jumps: the keyboard controller should
+ * be able to keep up
+ */
+#define REALLY_SLOW_IO
+#define SLOW_IO_BY_JUMPING
#include <asm/io.h>
#include <asm/system.h>
-#define LSHIFT 0x01
-#define RSHIFT 0x02
-#define LCTRL 0x04
-#define RCTRL 0x08
-#define ALT 0x10
-#define ALTGR 0x20
-#define CAPS 0x40
-#define CAPSDOWN 0x80
+#define LSHIFT 0x01
+#define RSHIFT 0x02
+#define LCTRL 0x04
+#define RCTRL 0x08
+#define ALT 0x10
+#define ALTGR 0x20
+#define CAPS 0x40
+#define CAPSDOWN 0x80
-#define SCRLED 0x01
-#define NUMLED 0x02
-#define CAPSLED 0x04
+#define SCRLED 0x01
+#define NUMLED 0x02
+#define CAPSLED 0x04
-#if defined KBD_NUMERIC_LOCK
-#define NUMLED_DEFAULT NUMLED
+#define NO_META_BIT 0x80
-#else
-#define NUMLED_DEFAULT 0
+#ifndef KBD_DEFLOCK
+#define KBD_DEFLOCK NUMLED
#endif
-#define NO_META_BIT 0x80
-
unsigned char kapplic = 0;
unsigned char ckmode = 0;
unsigned char krepeat = 1;
unsigned char kmode = 0;
-unsigned char kleds = NUMLED_DEFAULT;
+unsigned char default_kleds = KBD_DEFLOCK;
+unsigned char kleds = KBD_DEFLOCK;
unsigned char ke0 = 0;
unsigned char kraw = 0;
unsigned char kbd_flags = KBDFLAGS;
@@ -120,8 +126,9 @@ void keyboard_interrupt(int int_pt_regs)
} else if (ke0 == repke0 && (scancode & 0x7f) == rep)
if (scancode & 0x80)
rep = 0xff;
- else if (!(krepeat && (L_ECHO(tty) || (EMPTY(tty->secondary) &&
- EMPTY(tty->read_q))))) {
+ else if (!(krepeat && tty && (L_ECHO(tty) ||
+ (EMPTY(&tty->secondary) &&
+ EMPTY(&tty->read_q))))) {
ke0 = 0;
return;
}
@@ -132,9 +139,15 @@ void keyboard_interrupt(int int_pt_regs)
static void put_queue(int ch)
{
- register struct tty_queue *qp = table_list[0];
+ struct tty_queue *qp;
+ struct tty_struct *tty = TTY_TABLE(0);
unsigned long new_head;
+ wake_up(&keypress_wait);
+ if (!tty)
+ return;
+ qp = &tty->read_q;
+
qp->buf[qp->head]=ch;
if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1)) != qp->tail)
qp->head=new_head;
@@ -143,9 +156,15 @@ static void put_queue(int ch)
static void puts_queue(char *cp)
{
- register struct tty_queue *qp = table_list[0];
+ struct tty_queue *qp;
+ struct tty_struct *tty = TTY_TABLE(0);
unsigned long new_head;
char ch;
+
+ wake_up(&keypress_wait);
+ if (!tty)
+ return;
+ qp = &tty->read_q;
while (ch=*cp++) {
qp->buf[qp->head]=ch;
@@ -286,7 +305,6 @@ static void applkey(int key)
puts_queue(buf);
}
-
#if defined KBD_FINNISH
static unsigned char key_map[] = {
@@ -299,19 +317,19 @@ static unsigned char key_map[] = {
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', ']', '^', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', '\\',
'[', 0, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -321,18 +339,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_FINNISH_LATIN1
@@ -340,21 +358,21 @@ static unsigned char key_map[] = {
0, 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '+', 180, 127, 9,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', 229, 168, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
+ 'o', 'p', 229, 168, 13, 0, 'a', 's',
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
228, 167, 0, '\'', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
+ 'b', 'n', 'm', ',', '.', '-', 0, '*',
+ 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
+
static unsigned char shift_map[] = {
0, 27, '!', '"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+ '/', '(', ')', '=', '?', '`', 127, 9,
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', 197, '^', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
196, 189, 0, '*', 'Z', 'X', 'C', 'V',
@@ -368,16 +386,16 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
@@ -389,12 +407,12 @@ static unsigned char key_map[] = {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13, 0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
+ '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
@@ -404,29 +422,29 @@ static unsigned char shift_map[] = {
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
- '"', '~', '0', '|', 'Z', 'X', 'C', 'V',
+ '"', '~', '0', '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '>', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_UK
@@ -436,12 +454,12 @@ static unsigned char key_map[] = {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13, 0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', 0, '#', 'z', 'x', 'c', 'v',
+ '\'', '`', 0, '#', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '\\', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
@@ -451,29 +469,29 @@ static unsigned char shift_map[] = {
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
- '@', '~', '0', '~', 'Z', 'X', 'C', 'V',
+ '@', '~', '0', '~', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
0, 0, 0, 0, 0, 0, 0, 0,
0 };
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_GR
@@ -487,19 +505,19 @@ static unsigned char key_map[] = {
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
'O', 'P', '\\', '*', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', '{',
'}', '~', 0, '\'', 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -509,18 +527,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_GR_LATIN1
@@ -534,19 +552,19 @@ static unsigned char key_map[] = {
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '"', 167, '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
'O', 'P', 220, '*', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
- 196, 176, 0, '\'', 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 196, 176, 0, '\'', 'Y', 'X', 'C', 'V',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -556,18 +574,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, 178, 179, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 181, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 181, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_FR
@@ -581,19 +599,19 @@ static unsigned char key_map[] = {
'b', 'n', ',', ';', ':', '!', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', ']', '+', 127, 9,
+ '7', '8', '9', '0', ']', '+', 127, 9,
'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '<', '>', 13, 0, 'Q', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
'%', '~', 0, '#', 'W', 'X', 'C', 'V',
- 'B', 'N', '?', '.', '/', '\\', 0, '*',
+ 'B', 'N', '?', '.', '/', '\\', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -603,24 +621,24 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '~', '#', '{', '[', '|',
- '`', '\\', '^', '@', ']', '}', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '`', '\\', '^', '@', ']', '}', 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_FR_LATIN1
static unsigned char key_map[] = {
0, 27, '&', 233, '"', '\'', '(', '-',
- 232, '_', 231, 224, ')', '=', 127, 9,
+ 232, '_', 231, 224, ')', '=', 127, 9,
'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '^', '$', 13, 0, 'q', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
@@ -628,19 +646,19 @@ static unsigned char key_map[] = {
'b', 'n', ',', ';', ':', '!', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', 176, '+', 127, 9,
+ '7', '8', '9', '0', 176, '+', 127, 9,
'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', 168, 163, 13, 0, 'Q', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
'%', 0, 0, 181, 'W', 'X', 'C', 'V',
- 'B', 'N', '?', '.', '/', 167, 0, '*',
+ 'B', 'N', '?', '.', '/', 167, 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -650,18 +668,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '~', '#', '{', '[', '|',
- '`', '\\', '^', '@', ']', '}', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 164, 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '`', '\\', '^', '@', ']', '}', 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 164, 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_DK
@@ -675,19 +693,19 @@ static unsigned char key_map[] = {
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', 197, '^', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 198,
165, 0, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -697,18 +715,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', 0, '|', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', 0, '|', 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '\\', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_DK_LATIN1
@@ -722,19 +740,19 @@ static unsigned char key_map[] = {
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', 197, '^', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', 198,
165, 167, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -744,159 +762,159 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', 0, '|', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', 0, '|', 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '\\', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_DVORAK
static unsigned char key_map[] = {
0, 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '\\', '=', 127, 9,
- '\'', ',', '.', 'p', 'y', 'f', 'g', 'c',
- 'r', 'l', '/', ']', 13, 0, 'a', 'o',
+ '\'', ',', '.', 'p', 'y', 'f', 'g', 'c',
+ 'r', 'l', '/', ']', 13, 0, 'a', 'o',
'e', 'u', 'i', 'd', 'h', 't', 'n', 's',
- '-', '`', 0, '[', ';', 'q', 'j', 'k',
+ '-', '`', 0, '[', ';', 'q', 'j', 'k',
'x', 'b', 'm', 'w', 'v', 'z', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
0, 0, 0, 0, 0, 0, '<', 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '|', '+', 127, 9,
- '"', '<', '>', 'P', 'Y', 'F', 'G', 'C',
+ '"', '<', '>', 'P', 'Y', 'F', 'G', 'C',
'R', 'L', '?', '}', 13, 0, 'A', 'O',
'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S',
'_', '~', 0, '{', ':', 'Q', 'J', 'K',
'X', 'B', 'M', 'W', 'V', 'Z', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
0, 0, 0, 0, 0, 0, '<', 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0 };
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', '\\', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '|', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_SG
static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\'', '^', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', 0, 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0,
- 0, 0, 0, '$', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 27, '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', '0', '\'', '^', 127, 9,
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
+ 'o', 'p', 0, 0, 13, 0, 'a', 's',
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0,
+ 0, 0, 0, '$', 'y', 'x', 'c', 'v',
+ 'b', 'n', 'm', ',', '.', '-', 0, '*',
+ 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
- 0, 27, '+', '"', '*', 0, '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', 0, '!', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0,
- 0, 0, 0, 0, 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 27, '+', '"', '*', 0, '%', '&',
+ '/', '(', ')', '=', '?', '`', 127, 9,
+ 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
+ 'O', 'P', 0, '!', 13, 0, 'A', 'S',
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0,
+ 0, 0, 0, 0, 'Y', 'X', 'C', 'V',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '>', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char alt_map[] = {
- 0, 0, 0, '@', '#', 0, 0, 0,
- '|', 0, 0, 0, '\'', '~', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '[', ']', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- '{', 0, 0, '}', 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, 0, '@', '#', 0, 0, 0,
+ '|', 0, 0, 0, '\'', '~', 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '[', ']', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ '{', 0, 0, '}', 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '\\', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_SG_LATIN1
static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\'', '^', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', 252, 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
- 228, 167, 0, '$', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 27, '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', '0', '\'', '^', 127, 9,
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
+ 'o', 'p', 252, 0, 13, 0, 'a', 's',
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
+ 228, 167, 0, '$', 'y', 'x', 'c', 'v',
+ 'b', 'n', 'm', ',', '.', '-', 0, '*',
+ 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
- 0, 27, '+', '"', '*', 231, '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', 220, '!', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
- 196, 176, 0, 163, 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 27, '+', '"', '*', 231, '%', '&',
+ '/', '(', ')', '=', '?', '`', 127, 9,
+ 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
+ 'O', 'P', 220, '!', 13, 0, 'A', 'S',
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
+ 196, 176, 0, 163, 'Y', 'X', 'C', 'V',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '>', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char alt_map[] = {
- 0, 0, 0, '@', '#', 0, 0, 172,
- '|', 162, 0, 0, '\'', '~', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '[', ']', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 233,
- '{', 0, 0, '}', 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, 0, '@', '#', 0, 0, 172,
+ '|', 162, 0, 0, '\'', '~', 0, 0,
+ '@', 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, '[', ']', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 233,
+ '{', 0, 0, '}', 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, '\\', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#elif defined KBD_NO
@@ -906,23 +924,23 @@ static unsigned char key_map[] = {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '}', '~', 13, 0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', '|',
- '{', '|', 0, '\'', 'z', 'x', 'c', 'v',
+ '{', '|', 0, '\'', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '-', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
static unsigned char shift_map[] = {
0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
+ '/', '(', ')', '=', '?', '`', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', ']', '^', 13, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', '\\',
'[', 0, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*',
0, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, '-', 0, 0, 0, '+', 0,
@@ -932,18 +950,18 @@ static unsigned char shift_map[] = {
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', 0, '\'', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ '{', '[', ']', '}', 0, '\'', 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, '~', 13, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0 };
#else
#error "KBD-type not defined"
@@ -999,7 +1017,6 @@ unsigned char accent_table[5][64] = {
"`\344bcd\353fgh\357jklmn\366pqrst\374vwx\377z{|}~" /* dieresis */
};
-
/*
* Check if dead key pressed. If so, check if same key pressed twice;
* in that case return the char, otherwise store char and return 0.
@@ -1012,7 +1029,7 @@ unsigned char accent_table[5][64] = {
unsigned int handle_diacr(unsigned int ch)
{
static unsigned char diacr_table[] =
- {'`', 180, '^', '~', 168, 0}; /* Must end with 0 */
+ {'`', 180, '^', '~', 168, 0}; /* Must end with 0 */
int i;
for(i=0; diacr_table[i]; i++)
@@ -1040,7 +1057,6 @@ unsigned int handle_diacr(unsigned int ch)
return ch;
}
}
-
#if defined KBD_FR || defined KBD_US || defined KBD_UK
static unsigned char num_table[] = "789-456+1230.";
@@ -1048,13 +1064,13 @@ static unsigned char num_table[] = "789-456+1230.";
static unsigned char num_table[] = "789-456+1230,";
#endif
-static unsigned char cur_table[] = "HA5-DGC+YB623";
+static unsigned char cur_table[] = "1A5-DGC+4B623";
static unsigned int pad_table[] = { 7,8,9,0,4,5,6,0,1,2,3,0,0 };
-/*
- Keypad / 35 B7 Q
+/*
+ Keypad / 35 B7 Q
Keypad * (PrtSc) 37 B7 R
- Keypad NumLock 45 ?? P
+ Keypad NumLock 45 ?? P
Keypad 7 (Home) 47 C7 w
Keypad 8 (Up arrow) 48 C8 x
Keypad 9 (PgUp) 49 C9 y
@@ -1063,21 +1079,33 @@ static unsigned int pad_table[] = { 7,8,9,0,4,5,6,0,1,2,3,0,0 };
Keypad 5 4C CC u
Keypad 6 (Right arrow) 4D CD v
Keypad + 4E CE l
- Keypad 1 (End) 4F CF q
+ Keypad 1 (End) 4F CF q
Keypad 2 (Down arrow) 50 D0 r
Keypad 3 (PgDn) 51 D1 s
Keypad 0 (Ins) 52 D2 p
- Keypad . (Del) 53 D3 n
-*/
+ Keypad . (Del) 53 D3 n
+*/
static unsigned char appl_table[] = "wxyStuvlqrspn";
-static char *func_table[] = {
- "\033[[A", "\033[[B", "\033[[C", "\033[[D",
- "\033[[E", "\033[[F", "\033[[G", "\033[[H",
- "\033[[I", "\033[[J", "\033[[K", "\033[[L"
-};
-
+/*
+ Set up keyboard to generate DEC VT200 F-keys.
+ DEC F1 - F5 not implemented (DEC HOLD, LOCAL PRINT, SETUP, SW SESS, BREAK)
+ DEC F6 - F10 are mapped to F6 - F10
+ DEC F11 - F20 are mapped to Shift-F1 - Shift-F10
+ DEC HELP and DEC DO are mapped to F11, F12 or Shift- F11, F12.
+ Regular (?) Linux F1-F5 remain the same.
+*/
+
+static char *func_table[2][12] = { /* DEC F1 - F10 */ {
+ "\033[[A", "\033[[B", "\033[[C", "\033[[D",
+ "\033[[E", "\033[17~", "\033[18~", "\033[19~",
+ "\033[20~", "\033[21~", "\033[28~", "\033[29~"
+}, /* DEC F11 - F20 */ {
+ "\033[23~", "\033[24~", "\033[25~", "\033[26~",
+ "\033[28~", "\033[29~", "\033[31~", "\033[32~",
+ "\033[33~", "\033[34~", "\033[28~", "\033[29~"
+}};
static void cursor(int sc)
{
@@ -1093,12 +1121,12 @@ static void cursor(int sc)
return;
}
- if ((kmode&ALT) && sc!=12) { /* Alt-numpad */
+ if ((kmode&ALT) && sc!=12) { /* Alt-numpad */
npadch=npadch*10+pad_table[sc];
return;
}
- if (kapplic && !(kmode&(LSHIFT|RSHIFT))) { /* shift forces cursor */
+ if (kapplic && !(kmode&(LSHIFT|RSHIFT))) { /* shift forces cursor */
applkey(appl_table[sc]);
return;
}
@@ -1111,13 +1139,14 @@ static void cursor(int sc)
static void cur(int sc)
{
- char buf[] = { 0x1b, '[', 0, 0, 0 }; /* must not be static */
+ char buf[] = { 0x1b, '[', 0, 0, 0 }; /* must not be static */
buf[2]=cur_table[sc];
if (buf[2] < '9')
buf[3]='~';
- if ((buf[2] >= 'A' && buf[2] <= 'D') ? ckmode : kapplic)
- buf[1]='O';
+ else
+ if ((buf[2] >= 'A' && buf[2] <= 'D') ? ckmode : kapplic)
+ buf[1]='O';
puts_queue(buf);
}
@@ -1134,9 +1163,11 @@ static void func(int sc)
if (kmode&ALT)
change_console(sc);
else
- puts_queue(func_table[sc]);
-}
-
+ if (kmode & ( LSHIFT | RSHIFT)) /* DEC F11 - F20 */
+ puts_queue(func_table[1][sc]);
+ else /* DEC F1 - F10 */
+ puts_queue(func_table[0][sc]);
+}
static void slash(int sc)
{
@@ -1183,12 +1214,10 @@ static void plus(int sc)
do_self(sc);
}
-
static void none(int sc)
{
}
-
/*
* kb_wait waits for the keyboard controller buffer to empty.
*/
@@ -1244,7 +1273,6 @@ void hard_reset_now(void)
__asm__("\tlidt _no_idt"::);
}
}
-
static fptr key_table[] = {
none,do_self,do_self,do_self, /* 00-03 s0 esc 1 2 */
diff --git a/kernel/chr_drv/pty.c b/kernel/chr_drv/pty.c
index 76a8915..516672f 100644
--- a/kernel/chr_drv/pty.c
+++ b/kernel/chr_drv/pty.c
@@ -7,9 +7,9 @@
/*
* pty.c
*
- * This module implements the pty functions
- * void mpty_write(struct tty_struct * queue);
- * void spty_write(struct tty_struct * queue);
+ * This module exports the following pty function:
+ *
+ * int pty_open(struct tty_struct * tty, struct file * filp);
*/
#include <linux/errno.h>
@@ -20,31 +20,32 @@
#include <asm/system.h>
#include <asm/io.h>
-int pty_open(unsigned int dev, struct file * filp)
-{
- struct tty_struct * tty;
+static void pty_close(struct tty_struct * tty, struct file * filp);
- tty = tty_table + dev;
- if (!tty->link)
+int pty_open(struct tty_struct *tty, struct file * filp)
+{
+ if (!tty || !tty->link)
return -ENODEV;
- wake_up(&tty->read_q->proc_list);
+ if (IS_A_PTY_MASTER(tty->line))
+ tty->write = mpty_write;
+ else
+ tty->write = spty_write;
+ tty->close = pty_close;
+ wake_up(&tty->read_q.proc_list);
if (filp->f_flags & O_NDELAY)
return 0;
while (!tty->link->count && !(current->signal & ~current->blocked))
- interruptible_sleep_on(&tty->link->read_q->proc_list);
+ interruptible_sleep_on(&tty->link->read_q.proc_list);
if (!tty->link->count)
return -ERESTARTSYS;
return 0;
}
-void pty_close(unsigned int dev, struct file * filp)
+static void pty_close(struct tty_struct * tty, struct file * filp)
{
- struct tty_struct * tty;
-
- tty = tty_table + dev;
- wake_up(&tty->read_q->proc_list);
- wake_up(&tty->link->write_q->proc_list);
- if (IS_A_PTY_MASTER(dev)) {
+ wake_up(&tty->read_q.proc_list);
+ wake_up(&tty->link->write_q.proc_list);
+ if (IS_A_PTY_MASTER(tty->line)) {
if (tty->link->pgrp > 0)
kill_pg(tty->link->pgrp,SIGHUP,1);
}
@@ -54,20 +55,20 @@ static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
{
int c;
- while (!from->stopped && !EMPTY(from->write_q)) {
- if (FULL(to->read_q)) {
- if (FULL(to->secondary))
+ while (!from->stopped && !EMPTY(&from->write_q)) {
+ if (FULL(&to->read_q)) {
+ if (FULL(&to->secondary))
break;
TTY_READ_FLUSH(to);
continue;
}
- c = get_tty_queue(from->write_q);
- put_tty_queue(c,to->read_q);
+ c = get_tty_queue(&from->write_q);
+ put_tty_queue(c, &to->read_q);
if (current->signal & ~current->blocked)
break;
}
TTY_READ_FLUSH(to);
- wake_up(&from->write_q->proc_list);
+ wake_up(&from->write_q.proc_list);
}
/*
diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c
index 737669c..ca4a615 100644
--- a/kernel/chr_drv/serial.c
+++ b/kernel/chr_drv/serial.c
@@ -2,15 +2,19 @@
* linux/kernel/serial.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-/*
- * serial.c
*
- * This module implements the rs232 io functions
- * void rs_write(struct tty_struct * queue);
+ * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now
+ * much more extensible to support other serial cards based on the
+ * 16450/16550A UART's. Added support for the AST FourPort and the
+ * Accent Async board. We use the async_ISR structure to allow
+ * multiple ports (or boards, if the hardware permits) to share a
+ * single IRQ channel.
+ *
+ * This module exports the following rs232 io functions:
+ *
* long rs_init(long);
- * and all interrupts pertaining to serial IO.
+ * int rs_open(struct tty_struct * tty, struct file * filp)
+ * void change_speed(unsigned int line)
*/
#include <linux/errno.h>
@@ -18,6 +22,7 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
+#include <linux/serial.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -25,129 +30,204 @@
#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
-struct serial_struct serial_table[NR_SERIALS] = {
- { PORT_UNKNOWN, 0, 0x3F8, 4, NULL},
- { PORT_UNKNOWN, 1, 0x2F8, 3, NULL},
- { PORT_UNKNOWN, 2, 0x3E8, 4, NULL},
- { PORT_UNKNOWN, 3, 0x2E8, 3, NULL},
+/*
+ * rs_read_process - Bitfield of serial lines that have I/O processing
+ * to be done at the next clock tick.
+ * rs_write_timeout - Bitfield of serial lines that have a possible
+ * write timeout pending. (In case the THRE
+ * interrupt gets lost.)
+ */
+static unsigned long rs_read_process = 0;
+static unsigned long rs_write_timeout = 0;
+
+static void UART_ISR_proc(async_ISR ISR, int line);
+static void FourPort_ISR_proc(async_ISR ISR, int line);
+
+struct struct_ISR COM1_ISR = { 4, 0x3f8, UART_ISR_proc, 0, };
+struct struct_ISR COM2_ISR = { 3, 0x2f8, UART_ISR_proc, 0, };
+struct struct_ISR COM3_ISR = { 4, 0x3e8, UART_ISR_proc, 0, };
+struct struct_ISR COM4_ISR = { 3, 0x2e8, UART_ISR_proc, 0, };
+
+struct struct_ISR FourPort1_ISR = { 2, 0x1bf, FourPort_ISR_proc, 0, };
+struct struct_ISR FourPort2_ISR = { 5, 0x2bf, FourPort_ISR_proc, 0, };
+
+struct struct_ISR Accent3_ISR = { 4, 0x330, UART_ISR_proc, 0, };
+struct struct_ISR Accent4_ISR = { 4, 0x338, UART_ISR_proc, 0, };
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+struct async_struct rs_table[] = {
+ { BASE_BAUD, 0x3F8, &COM1_ISR, 0, },
+ { BASE_BAUD, 0x2F8, &COM2_ISR, 0, },
+ { BASE_BAUD, 0x3E8, &COM3_ISR, 0, },
+ { BASE_BAUD, 0x2E8, &COM4_ISR, 0, },
+
+ { BASE_BAUD, 0x1A0, &FourPort1_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x1A8, &FourPort1_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x1B0, &FourPort1_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x1B8, &FourPort1_ISR, ASYNC_FOURPORT | ASYNC_NOSCRATCH },
+
+ { BASE_BAUD, 0x2A0, &FourPort2_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x2A8, &FourPort2_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x2B0, &FourPort2_ISR, ASYNC_FOURPORT },
+ { BASE_BAUD, 0x2B8, &FourPort2_ISR, ASYNC_FOURPORT | ASYNC_NOSCRATCH },
+
+ { BASE_BAUD, 0x330, &Accent3_ISR, 0 },
+ { BASE_BAUD, 0x338, &Accent4_ISR, 0 },
};
-void send_break(unsigned int line)
+#define NR_PORTS (sizeof(rs_table)/sizeof(struct async_struct))
+
+static async_ISR IRQ_ISR[16]; /* Used to store the head of the */
+ /* ISR linked list chain for each IRQ */
+
+/*
+ * This is used to figure out the divsor speeds and the timeouts
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 56000, 115200, 0 };
+
+static void send_break( struct async_struct * info)
{
unsigned short port;
- struct serial_struct * info;
- if (line >= NR_SERIALS)
- return;
- info = serial_table + line;
if (!(port = info->port))
return;
- port += 3;
+ port += UART_LCR;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 25;
- outb_p(inb_p(port) | 0x40,port);
+ outb_p(inb_p(port) | UART_LCR_SBC, port);
schedule();
- outb_p(inb_p(port) & 0xbf,port);
+ outb_p(inb_p(port) & ~UART_LCR_SBC, port);
}
/*
- * There are several races here: we avoid most of them by disabling timer_active
- * for the crucial part of the process.. That's a good idea anyway.
+ * There are several races here: we avoid most of them by disabling
+ * timer_active for the crucial part of the process.. That's a good
+ * idea anyway.
*
* The problem is that we have to output characters /both/ from interrupts
* and from the normal write: the latter to be sure the interrupts start up
* again. With serial lines, the interrupts can happen so often that the
* races actually are noticeable.
*/
-static void send_intr(struct serial_struct * info)
+static void send_intr(struct async_struct * info)
{
unsigned short port = info->port;
- unsigned int timer = SER1_TIMEOUT + info->line;
- struct tty_queue * queue = info->tty->write_q;
- int c, i = 0;
-
- if (info->tty->stopped) return;
-
- timer_active &= ~(1 << timer);
- while (inb_p(info->port+5) & 0x20) {
- if (queue->tail == queue->head)
- goto end_send;
- c = queue->buf[queue->tail];
- queue->tail++;
- queue->tail &= TTY_BUF_SIZE-1;
- outb(c,port);
- if ((info->type != PORT_16550A) || (++i >= 14) || info->tty->stopped)
- break;
+ int line = info->line;
+ struct tty_queue * queue = &info->tty->write_q;
+ int c, count = 0;
+
+ if (info->tty->stopped)
+ return;
+
+ if (info->type == PORT_16550A)
+ count = 16;
+ else
+ count = 1;
+
+ rs_write_timeout &= ~(1 << line);
+
+ if (inb_p(UART_LSR + info->port) & UART_LSR_THRE) {
+ while (count-- && !info->tty->stopped) {
+ if (queue->tail == queue->head)
+ goto end_send;
+ c = queue->buf[queue->tail];
+ queue->tail++;
+ queue->tail &= TTY_BUF_SIZE-1;
+ outb(c, UART_TX + port);
+ }
}
- timer_table[timer].expires = jiffies + 10;
- timer_active |= 1 << timer;
+ info->timer = jiffies + info->timeout;
+ if (info->timer < timer_table[RS_TIMER].expires)
+ timer_table[RS_TIMER].expires = info->timer;
+ rs_write_timeout |= 1 << line;
+ timer_active |= 1 << RS_TIMER;
end_send:
if (LEFT(queue) > WAKEUP_CHARS)
wake_up(&queue->proc_list);
}
-static void receive_intr(struct serial_struct * info)
+static void receive_intr(struct async_struct * info)
{
unsigned short port = info->port;
- struct tty_queue * queue = info->tty->read_q;
+ struct tty_queue * queue = &info->tty->read_q;
int head = queue->head;
int maxhead = (queue->tail-1) & (TTY_BUF_SIZE-1);
+ int count = 0;
- timer_active &= ~((1<<SER1_TIMER)<<info->line);
+ rs_read_process &= ~(1 << info->line);
do {
- queue->buf[head] = inb(port);
+ count++;
+ queue->buf[head] = inb(UART_TX + port);
if (head != maxhead) {
head++;
head &= TTY_BUF_SIZE-1;
}
- } while (inb(port+5) & 1);
+ } while (inb(UART_LSR + port) & UART_LSR_DR);
queue->head = head;
- timer_active |= (1<<SER1_TIMER)<<info->line;
+ rs_read_process |= 1 << info->line;
+ timer_table[RS_TIMER].expires = 0;
+ timer_active |= 1<<RS_TIMER;
}
-static void line_status_intr(struct serial_struct * info)
+static void line_status_intr(struct async_struct * info)
{
- unsigned char status = inb(info->port+5);
+ unsigned char status = inb(UART_LSR + info->port);
-/* printk("line status: %02x\n",status); */
+/* printk("line status: %02x\n",status); */
}
-static void modem_status_intr(struct serial_struct * info)
+static void modem_status_intr(struct async_struct * info)
{
- unsigned char status = inb(info->port+6);
+ unsigned char status = inb(UART_MSR + info->port);
- if (!(info->tty->termios.c_cflag & CLOCAL)) {
- if ((status & 0x88) == 0x08 && info->tty->pgrp > 0)
+ if (!(info->tty->termios->c_cflag & CLOCAL)) {
+ if (((status & (UART_MSR_DCD|UART_MSR_DDCD)) == UART_MSR_DDCD)
+ && info->tty->pgrp > 0)
kill_pg(info->tty->pgrp,SIGHUP,1);
- if (info->tty->termios.c_cflag & CRTSCTS)
- info->tty->stopped = !(status & 0x10);
+ if (info->tty->termios->c_cflag & CRTSCTS)
+ info->tty->stopped = !(status & UART_MSR_CTS);
if (!info->tty->stopped)
send_intr(info);
}
}
-static void (*jmp_table[4])(struct serial_struct *) = {
+static void (*jmp_table[4])(struct async_struct *) = {
modem_status_intr,
send_intr,
receive_intr,
line_status_intr
};
-static void check_tty(struct serial_struct * info)
+/*
+ * This ISR handles the COM1-4 8250, 16450, and 16550A UART's. It is
+ * also called by the FourPort ISR, since the FourPort also uses the
+ * same National Semiconduct UART's, with some interrupt multiplexing
+ * thrown in.
+ */
+static void UART_ISR_proc(async_ISR ISR, int line)
{
unsigned char ident;
+ struct async_struct * info = rs_table + line;
if (!info || !info->tty || !info->port)
- return;
+ return;
while (1) {
- ident = inb(info->port+2) & 7;
+ ident = inb(UART_IIR + info->port) & 7;
if (ident & 1)
return;
- ident >>= 1;
- if (ident > 3)
- return;
+ ident = ident >> 1;
jmp_table[ident](info);
}
}
@@ -156,11 +236,11 @@ static void check_tty(struct serial_struct * info)
* Again, we disable interrupts to be sure there aren't any races:
* see send_intr for details.
*/
-static inline void do_rs_write(struct serial_struct * info)
+static inline void do_rs_write(struct async_struct * info)
{
if (!info->tty || !info->port)
return;
- if (!info->tty->write_q || EMPTY(info->tty->write_q))
+ if (EMPTY(&info->tty->write_q))
return;
cli();
send_intr(info);
@@ -168,93 +248,107 @@ static inline void do_rs_write(struct serial_struct * info)
}
/*
- * IRQ routines: one per line
+ * Here is the fourport ISR
*/
-static void com1_IRQ(int unused)
-{
- check_tty(serial_table+0);
-}
-
-static void com2_IRQ(int unused)
-{
- check_tty(serial_table+1);
-}
-
-static void com3_IRQ(int unused)
+static void FourPort_ISR_proc(async_ISR ISR, int line)
{
- check_tty(serial_table+2);
-}
-
-static void com4_IRQ(int unused)
-{
- check_tty(serial_table+3);
+ int i;
+ unsigned char ivec;
+
+ ivec = ~inb(ISR->port) & 0x0F;
+ for (i = line; ivec; i++) {
+ if (ivec & 1)
+ UART_ISR_proc(ISR, i);
+ ivec = ivec >> 1;
+ }
}
/*
- * Receive timer routines: one per line
+ * This is the serial driver's generic interrupt routine
*/
-static void com1_timer(void)
-{
- TTY_READ_FLUSH(tty_table+64);
-}
-
-static void com2_timer(void)
+static void rs_interrupt(int irq)
{
- TTY_READ_FLUSH(tty_table+65);
-}
+ async_ISR p = IRQ_ISR[irq];
-static void com3_timer(void)
-{
- TTY_READ_FLUSH(tty_table+66);
-}
-
-static void com4_timer(void)
-{
- TTY_READ_FLUSH(tty_table+67);
+ while (p) {
+ (p->ISR_proc)(p, p->line);
+ p = p->next_ISR;
+ }
}
/*
- * Send timeout routines: one per line
+ * This subroutine handles all of the timer functionality required for
+ * the serial ports.
*/
-static void com1_timeout(void)
-{
- do_rs_write(serial_table);
-}
-
-static void com2_timeout(void)
-{
- do_rs_write(serial_table + 1);
-}
-
-static void com3_timeout(void)
-{
- do_rs_write(serial_table + 2);
-}
-static void com4_timeout(void)
+#define END_OF_TIME 0xffffffff
+static void rs_timer(void)
{
- do_rs_write(serial_table + 3);
+ unsigned long mask;
+ struct async_struct *info;
+ unsigned long next_timeout;
+
+ info = rs_table;
+ next_timeout = END_OF_TIME;
+ for (mask = 1 ; mask ; info++, mask <<= 1) {
+ if ((mask > rs_read_process) &&
+ (mask > rs_write_timeout))
+ break;
+ if (mask & rs_read_process) {
+ TTY_READ_FLUSH(info->tty);
+ rs_read_process &= ~mask;
+ }
+ if (mask & rs_write_timeout) {
+ if (info->timer > jiffies) {
+ rs_write_timeout &= ~mask;
+ do_rs_write(info);
+ }
+ if ((mask & rs_write_timeout) &&
+ (info->timer < next_timeout))
+ next_timeout = info->timer;
+ }
+ }
+ if (next_timeout != END_OF_TIME) {
+ timer_table[RS_TIMER].expires = next_timeout;
+ timer_active |= 1 << RS_TIMER;
+ }
}
-static void init(struct serial_struct * info)
+static void init(struct async_struct * info)
{
- unsigned char status1, status2, scratch;
+ unsigned char status1, status2, scratch, scratch2;
unsigned short port = info->port;
- if (inb(port+5) == 0xff) {
+ /*
+ * Check to see if a UART is really there.
+ */
+ scratch = inb_p(UART_MCR + port);
+ outb_p(UART_MCR_LOOP | scratch, UART_MCR + port);
+ scratch2 = inb_p(UART_MSR + port);
+ outb_p(UART_MCR_LOOP | 0x0A, UART_MCR + port);
+ status1 = inb_p(UART_MSR + port) & 0xF0;
+ outb_p(scratch, UART_MCR + port);
+ outb_p(scratch, UART_MSR + port);
+ if (status1 != 0x90) {
info->type = PORT_UNKNOWN;
return;
}
- scratch = inb(port+7);
- outb_p(0xa5, port+7);
- status1 = inb(port+7);
- outb_p(0x5a, port+7);
- status2 = inb(port+7);
+ if (!(info->flags & ASYNC_NOSCRATCH)) {
+ scratch = inb(UART_SCR + port);
+ outb_p(0xa5, UART_SCR + port);
+ status1 = inb(UART_SCR + port);
+ outb_p(0x5a, UART_SCR + port);
+ status2 = inb(UART_SCR + port);
+ outb_p(scratch, UART_SCR + port);
+ } else {
+ status1 = 0xa5;
+ status2 = 0x5a;
+ }
if (status1 == 0xa5 && status2 == 0x5a) {
- outb_p(scratch, port+7);
- outb_p(0x01, port+2);
- scratch = inb(port+2) >> 6;
+ outb_p(UART_FCR_ENABLE_FIFO, UART_FCR + port);
+ scratch = inb(UART_IIR + port) >> 6;
+ info->xmit_fifo_size = 1;
switch (scratch) {
case 0:
info->type = PORT_16450;
@@ -264,83 +358,163 @@ static void init(struct serial_struct * info)
break;
case 2:
info->type = PORT_16550;
- outb_p(0x00, port+2);
break;
case 3:
info->type = PORT_16550A;
- outb_p(0xc7, port+2);
+ info->xmit_fifo_size = 16;
break;
}
} else
info->type = PORT_8250;
- outb_p(0x80,port+3); /* set DLAB of line control reg */
- outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps) */
- outb_p(0x00,port+1); /* MS of divisor */
- outb_p(0x03,port+3); /* reset DLAB */
- outb_p(0x00,port+4); /* reset DTR,RTS, OUT_2 */
- outb_p(0x00,port+1); /* disable all intrs */
- (void)inb(port); /* read data port to reset things (?) */
+ change_speed(info->line);
+ outb_p(0x00, UART_IER + port); /* disable all intrs */
+ outb_p(0x00, UART_MCR + port); /* reset DTR,RTS,OUT_2 */
+ (void)inb(UART_RX + port); /* read data port to reset things (?) */
}
-void serial_close(unsigned line, struct file * filp)
+/*
+ * This routine gets called when tty_write has put something into
+ * the write_queue. It must check wheter the queue is empty, and
+ * set the interrupt register accordingly
+ */
+void rs_write(struct tty_struct * tty)
{
- struct serial_struct * info;
- int irq;
+ int line = tty->line - 64;
- if (line >= NR_SERIALS)
+ do_rs_write(rs_table+line);
+}
+
+/*
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * ISR from the interrupt chain if necessary, and we free that IRQ if
+ * nothing is left in the chain.
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ struct async_struct * info;
+ async_ISR ISR;
+ int irq, line;
+
+ line = DEV_TO_SL(tty->line);
+ if ((line < 0) || (line >= NR_PORTS))
return;
- info = serial_table + line;
+ wait_until_sent(tty);
+ info = rs_table + line;
if (!info->port)
return;
- outb(0x00,info->port+4); /* reset DTR, RTS, */
- irq = info->irq;
+ info->tty = 0;
+ outb_p(0x00, UART_IER + info->port); /* disable all intrs */
+ outb_p(0x00, UART_MCR + info->port); /* reset DTR, RTS, */
+ outb(UART_FCR_CLEAR_CMD, UART_FCR + info->port); /* disable FIFO's */
+ ISR = info->ISR;
+ irq = ISR->irq;
if (irq == 2)
irq = 9;
- free_irq(irq);
+ if (--ISR->refcnt == 0) {
+ if (ISR->next_ISR)
+ ISR->next_ISR->prev_ISR = ISR->prev_ISR;
+ if (ISR->prev_ISR)
+ ISR->prev_ISR->next_ISR = ISR->next_ISR;
+ else
+ IRQ_ISR[irq] = ISR->next_ISR;
+ if (!IRQ_ISR[irq])
+ free_irq(irq);
+ }
}
-static void startup(unsigned short port)
+static void startup(struct async_struct * info)
{
- int i;
+ unsigned short port = info->port;
+ unsigned short ICP;
+
+ /*
+ * First, clear the FIFO buffers and disable them
+ */
+ if (info->type == PORT_16550A)
+ outb_p(UART_FCR_CLEAR_CMD, UART_FCR + port);
+
+ /*
+ * Next, clear the interrupt registers.
+ */
+ (void)inb_p(UART_LSR + port);
+ (void)inb_p(UART_RX + port);
+ (void)inb_p(UART_IIR + port);
+ (void)inb_p(UART_MSR + port);
+
+ /*
+ * Now, initialize the UART
+ */
+ outb_p(UART_LCR_WLEN8, UART_LCR + port); /* reset DLAB */
+ if (info->flags & ASYNC_FOURPORT)
+ outb_p(UART_MCR_DTR | UART_MCR_RTS,
+ UART_MCR + port);
+ else
+ outb_p(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2,
+ UART_MCR + port);
+
+ /*
+ * Enable FIFO's if necessary
+ */
+ if (info->type == PORT_16550A) {
+ outb_p(UART_FCR_SETUP_CMD, UART_FCR + port);
+ info->xmit_fifo_size = 16;
+ } else {
+ info->xmit_fifo_size = 1;
+ }
- outb_p(0x03,port+3); /* reset DLAB */
- outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */
- outb_p(0x0f,port+1); /* enable all intrs */
- inb_p(port+2);
- inb_p(port+6);
- inb_p(port+2);
- inb_p(port+5);
- for (i = 0; i < 16 ; i++) {
- inb_p(port+0);
- if (!(inb_p(port+5) & 1))
- break;
+ /*
+ * Finally, enable interrupts
+ */
+ outb_p(0x0f,UART_IER + port); /* enable all intrs */
+ if (info->flags & ASYNC_FOURPORT) {
+ /* Enable interrupts on the AST Fourport board */
+ ICP = (port & 0xFE0) | 0x01F;
+ outb_p(0x80, ICP);
+ (void) inb(ICP);
}
- inb_p(port+2);
- inb_p(port+5);
}
void change_speed(unsigned int line)
{
- struct serial_struct * info;
- unsigned short port,quot;
+ struct async_struct * info;
+ unsigned short port;
+ int quot = 0;
unsigned cflag,cval;
- static unsigned short quotient[] = {
- 0, 2304, 1536, 1047, 857,
- 768, 576, 384, 192, 96,
- 64, 48, 24, 12, 6, 3
- };
+ int i;
- if (line >= NR_SERIALS)
+ if (line >= NR_PORTS)
return;
- info = serial_table + line;
- cflag = info->tty->termios.c_cflag;
+ info = rs_table + line;
+ cflag = info->tty->termios->c_cflag;
if (!(port = info->port))
return;
- quot = quotient[cflag & CBAUD];
+ i = cflag & CBAUD;
+ if (i == 15) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ i += 1;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ i += 2;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
+ quot = info->custom_divisor;
+ }
+ if (quot) {
+ info->timeout = ((info->xmit_fifo_size*HZ*15*quot) /
+ info->baud_base) + 2;
+ } else if (baud_table[i] == 134) {
+ quot = (2*info->baud_base / 269);
+ info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
+ } else if (baud_table[i]) {
+ quot = info->baud_base / baud_table[i];
+ info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
+ } else {
+ quot = 0;
+ info->timeout = 0;
+ }
if (!quot)
- outb(0x00,port+4);
- else if (!inb(port+4))
- startup(port);
+ outb(0x00,UART_MCR + port);
+ else if (!inb(UART_MCR + port))
+ startup(info);
/* byte size and parity */
cval = cflag & (CSIZE | CSTOPB);
cval >>= 4;
@@ -349,178 +523,279 @@ void change_speed(unsigned int line)
if (!(cflag & PARODD))
cval |= 16;
cli();
- outb_p(cval | 0x80,port+3); /* set DLAB */
- outb_p(quot & 0xff,port); /* LS of divisor */
- outb_p(quot >> 8,port+1); /* MS of divisor */
- outb(cval,port+3); /* reset DLAB */
+ outb_p(cval | UART_LCR_DLAB, UART_LCR + port); /* set DLAB */
+ outb_p(quot & 0xff, UART_DLL + port); /* LS of divisor */
+ outb_p(quot >> 8, UART_DLM + port); /* MS of divisor */
+ outb(cval, UART_LCR + port); /* reset DLAB */
sti();
}
-static void (*serial_handler[NR_SERIALS])(int) = {
- com1_IRQ,com2_IRQ,com3_IRQ,com4_IRQ
-};
-
-/*
- * this routine enables interrupts on 'line', and disables them for any
- * other serial line that shared the same IRQ. Braindamaged AT hardware.
- */
-int serial_open(unsigned line, struct file * filp)
-{
- struct serial_struct * info;
- int irq,retval;
- unsigned short port;
- struct sigaction sa;
-
- sa.sa_handler = serial_handler[line];
- sa.sa_flags = SA_INTERRUPT;
- sa.sa_mask = 0;
- sa.sa_restorer = NULL;
- if (line >= NR_SERIALS)
- return -ENODEV;
- info = serial_table + line;
- if (!(port = info->port))
- return -ENODEV;
- irq = info->irq;
- if (irq == 2)
- irq = 9;
- if (retval = irqaction(irq,&sa))
- return retval;
- startup(port);
- return 0;
-}
-
-int get_serial_info(unsigned int line, struct serial_struct * info)
+static int get_serial_info(struct async_struct * info,
+ struct serial_struct * retinfo)
{
- if (line >= NR_SERIALS)
- return -ENODEV;
- if (!info)
+ struct serial_struct tmp;
+
+ if (!retinfo)
return -EFAULT;
- memcpy_tofs(info,serial_table+line,sizeof(*info));
+ tmp.type = info->type;
+ tmp.line = info->line;
+ tmp.port = info->port;
+ tmp.irq = info->ISR->irq;
+/* tmp.flags = info->flags; */
+ memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
return 0;
}
-int set_serial_info(unsigned int line, struct serial_struct * info)
+static int set_serial_info(struct async_struct * info,
+ struct serial_struct * new_info)
{
struct serial_struct tmp;
- unsigned new_port;
- unsigned irq,new_irq;
- int retval;
- void (*handler)(int) = serial_handler[line];
+ async_ISR ISR;
+ unsigned int new_port;
+ unsigned int irq,new_irq;
+ int retval;
+ struct sigaction sa;
if (!suser())
return -EPERM;
- if (line >= NR_SERIALS)
- return -ENODEV;
- if (!info)
+ if (!new_info)
return -EFAULT;
- memcpy_fromfs(&tmp,info,sizeof(tmp));
- info = serial_table + line;
- if (!(new_port = tmp.port))
- new_port = info->port;
- if (!(new_irq = tmp.irq))
- new_irq = info->irq;
+ memcpy_fromfs(&tmp,new_info,sizeof(tmp));
+ new_port = tmp.port;
+ new_irq = tmp.irq;
if (new_irq > 15 || new_port > 0xffff)
return -EINVAL;
if (new_irq == 2)
new_irq = 9;
- irq = info->irq;
+ ISR = info->ISR;
+ irq = ISR->irq;
if (irq == 2)
irq = 9;
if (irq != new_irq) {
- retval = request_irq(new_irq,handler);
- if (retval)
- return retval;
- info->irq = new_irq;
- free_irq(irq);
+ /*
+ * We need to change the IRQ for this board. OK, if
+ * necessary, first we try to grab the new IRQ for
+ * serial interrupts.
+ */
+ if (!IRQ_ISR[new_irq]) {
+ sa.sa_handler = rs_interrupt;
+ sa.sa_flags = (SA_INTERRUPT);
+ sa.sa_mask = 0;
+ sa.sa_restorer = NULL;
+ retval = irqaction(irq,&sa);
+ if (retval)
+ return retval;
+ }
+
+ /*
+ * If the new IRQ is OK, now we unlink the ISR from
+ * the existing interrupt chain.
+ */
+ if (ISR->next_ISR)
+ ISR->next_ISR->prev_ISR = ISR->prev_ISR;
+ if (ISR->prev_ISR)
+ ISR->prev_ISR->next_ISR = ISR->next_ISR;
+ else
+ IRQ_ISR[irq] = ISR->next_ISR;
+ if (!IRQ_ISR[irq])
+ free_irq(irq);
+
+ /*
+ * Now link in the interrupt to the new interrupt chain.
+ */
+ ISR->prev_ISR = 0;
+ ISR->next_ISR = IRQ_ISR[new_irq];
+ if (ISR->next_ISR)
+ ISR->next_ISR->prev_ISR = ISR;
+ IRQ_ISR[new_irq] = ISR;
}
cli();
if (new_port != info->port) {
- outb(0x00,info->port+4); /* reset DTR, RTS, */
+ outb_p(0x00, UART_IER + info->port); /* disable all intrs */
+ outb(0x00, UART_MCR + info->port); /* reset DTR, RTS, */
info->port = new_port;
init(info);
- startup(new_port);
+ startup(info);
}
sti();
return 0;
}
-int get_modem_info(unsigned int line, unsigned int *value)
+static int get_modem_info(struct async_struct * info, unsigned int *value)
{
- unsigned port = (serial_table + line)->port;
- unsigned char control = inb(port+4);
- unsigned char status = inb(port+6);
+ unsigned port;
+ unsigned char control, status;
unsigned int result;
- result = ((control & 0x02) ? TIOCM_RTS : 0)
- | ((control & 0x01) ? TIOCM_DTR : 0)
- | ((status & 0x80) ? TIOCM_CAR : 0)
- | ((status & 0x40) ? TIOCM_RNG : 0)
- | ((status & 0x20) ? TIOCM_DSR : 0)
- | ((status & 0x10) ? TIOCM_CTS : 0);
+ port = info->port;
+ control = inb(UART_MCR + port);
+ status = inb(UART_MSR + port);
+ result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+ | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
+ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
+ | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
+ | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
put_fs_long(result,(unsigned long *) value);
return 0;
}
-int set_modem_info(unsigned int line, unsigned int cmd, unsigned int *value)
+static int set_modem_info(struct async_struct * info, unsigned int cmd,
+ unsigned int *value)
{
- unsigned port = (serial_table + line)->port;
- unsigned char control = inb(port+4);
+ unsigned port;
+ unsigned char control;
unsigned int arg = get_fs_long((unsigned long *) value);
+ port = info->port;
+ control = inb(UART_MCR + port);
+
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
- control |= 0x02;
+ control |= UART_MCR_RTS;
if (arg & TIOCM_DTR)
- control |= 0x01;
+ control |= UART_MCR_DTR;
break;
case TIOCMBIC:
if (arg & TIOCM_RTS)
- control &= ~0x02;
+ control &= ~UART_MCR_RTS;
if (arg & TIOCM_DTR)
- control &= ~0x01;
+ control &= ~UART_MCR_DTR;
break;
case TIOCMSET:
control = (control & ~0x03)
- | ((arg & TIOCM_RTS) ? 0x02 : 0)
- | ((arg & TIOCM_DTR) ? 0x01 : 0);
+ | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+ | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
break;
default:
return -EINVAL;
}
- outb(port,control);
+ outb(UART_MCR + port,control);
+ return 0;
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned int arg)
+{
+ int line;
+ struct async_struct * info;
+
+ line = DEV_TO_SL(tty->line);
+ if (line < 0 || line >= NR_PORTS)
+ return -ENODEV;
+ info = rs_table + line;
+
+ switch (cmd) {
+ case TCSBRK:
+ wait_until_sent(tty);
+ if (!arg)
+ send_break(info);
+ return 0;
+ case TIOCMGET:
+ verify_area((void *) arg,sizeof(unsigned int *));
+ return get_modem_info(info, (unsigned int *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return set_modem_info(info, cmd, (unsigned int *) arg);
+ case TIOCGSERIAL:
+ verify_area((void *) arg,sizeof(struct serial_struct));
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its interrupt into
+ * the ISR chain. It also performs the serial-speicific
+ * initalization for the tty structure.
+ */
+int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ struct async_struct *info;
+ async_ISR ISR;
+ int irq, retval, line;
+ struct sigaction sa;
+
+ if (!tty)
+ return -ENODEV;
+ if (tty->count > 1)
+ return 0; /* We've already been initialized */
+ line = DEV_TO_SL(tty->line);
+ if ((line < 0) || (line >= NR_PORTS))
+ return -ENODEV;
+ info = rs_table + line;
+ if (!info->port)
+ return -ENODEV;
+ info->tty = tty;
+ tty->write = rs_write;
+ tty->close = rs_close;
+ tty->ioctl = rs_ioctl;
+ ISR = info->ISR;
+ irq = ISR->irq;
+ if (irq == 2)
+ irq = 9;
+ if (!IRQ_ISR[irq]) {
+ sa.sa_handler = rs_interrupt;
+ sa.sa_flags = (SA_INTERRUPT);
+ sa.sa_mask = 0;
+ sa.sa_restorer = NULL;
+ retval = irqaction(irq,&sa);
+ if (retval)
+ return retval;
+ }
+ if (!ISR->refcnt++) {
+ /*
+ * If this is the first time we're using this ISR,
+ * link it in.
+ */
+ ISR->prev_ISR = 0;
+ ISR->next_ISR = IRQ_ISR[irq];
+ if (ISR->next_ISR)
+ ISR->next_ISR->prev_ISR = ISR;
+ IRQ_ISR[irq] = ISR;
+ }
+ startup(info);
return 0;
}
long rs_init(long kmem_start)
{
int i;
- struct serial_struct * info;
-
-/* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
- timer_table[SER1_TIMER].fn = com1_timer;
- timer_table[SER1_TIMER].expires = 0;
- timer_table[SER2_TIMER].fn = com2_timer;
- timer_table[SER2_TIMER].expires = 0;
- timer_table[SER3_TIMER].fn = com3_timer;
- timer_table[SER3_TIMER].expires = 0;
- timer_table[SER4_TIMER].fn = com4_timer;
- timer_table[SER4_TIMER].expires = 0;
-/* SERx_TIMEOUT timers are used for writing: prevent serial lockups */
- timer_table[SER1_TIMEOUT].fn = com1_timeout;
- timer_table[SER1_TIMEOUT].expires = 0;
- timer_table[SER2_TIMEOUT].fn = com2_timeout;
- timer_table[SER2_TIMEOUT].expires = 0;
- timer_table[SER3_TIMEOUT].fn = com3_timeout;
- timer_table[SER3_TIMEOUT].expires = 0;
- timer_table[SER4_TIMEOUT].fn = com4_timeout;
- timer_table[SER4_TIMEOUT].expires = 0;
- for (i = 0, info = serial_table; i < NR_SERIALS; i++,info++) {
- info->tty = (tty_table+64) + i;
+ struct async_struct * info;
+
+ timer_table[RS_TIMER].fn = rs_timer;
+ timer_table[RS_TIMER].expires = 0;
+ for (i = 0; i < 16; i++) {
+ IRQ_ISR[i] = 0;
+ }
+ for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
+ info->line = i;
+ info->tty = 0;
+ info->type = PORT_UNKNOWN;
+ info->timer = 0;
+ info->custom_divisor = 0;
+ if (!info->ISR->line) {
+ info->ISR->line = i;
+ info->ISR->refcnt = 0;
+ info->ISR->next_ISR = 0;
+ info->ISR->prev_ISR = 0;
+ }
init(info);
if (info->type == PORT_UNKNOWN)
continue;
- printk("serial port at 0x%04x (irq = %d)",info->port,info->irq);
+ printk("ttys%d%s at 0x%04x (irq = %d)", info->line,
+ (info->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+ info->port, info->ISR->irq);
switch (info->type) {
case PORT_8250:
printk(" is a 8250\n");
@@ -542,16 +817,3 @@ long rs_init(long kmem_start)
return kmem_start;
}
-/*
- * This routine gets called when tty_write has put something into
- * the write_queue. It must check wheter the queue is empty, and
- * set the interrupt register accordingly
- *
- * void _rs_write(struct tty_struct * tty);
- */
-void rs_write(struct tty_struct * tty)
-{
- int line = tty - tty_table - 64;
-
- do_rs_write(serial_table+line);
-}
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 2deb850..3e13096 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -9,6 +9,17 @@
* or rs-channels. It also implements echoing, cooked mode etc.
*
* Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
+ *
+ * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
+ * tty_struct and tty_queue structures. Previously there was a array
+ * of 256 tty_struct's which was statically allocated, and the
+ * tty_queue structures were allocated at boot time. Both are now
+ * dynamically allocated only when the tty is open.
+ *
+ * Also restructured routines so that there is more of a separation
+ * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
+ * the low-level tty routines (serial.c, pty.c, console.c). This
+ * makes for cleaner and more compact code. -TYT, 9/17/92
*/
#include <linux/types.h>
@@ -19,6 +30,8 @@
#include <linux/tty.h>
#include <linux/ctype.h>
#include <linux/kd.h>
+#include <linux/mm.h>
+#include <linux/string.h>
#include <asm/io.h>
#include <asm/segment.h>
@@ -26,19 +39,9 @@
#include "vt_kern.h"
-#define QUEUES (3*(NR_CONSOLES+NR_SERIALS+2*NR_PTYS))
-static struct tty_queue * tty_queues;
-struct tty_struct tty_table[256];
-
-#define con_queues tty_queues
-#define rs_queues ((3*NR_CONSOLES) + tty_queues)
-#define mpty_queues ((3*(NR_CONSOLES+NR_SERIALS)) + tty_queues)
-#define spty_queues ((3*(NR_CONSOLES+NR_SERIALS+NR_PTYS)) + tty_queues)
-
-#define con_table tty_table
-#define rs_table (64+tty_table)
-#define mpty_table (128+tty_table)
-#define spty_table (192+tty_table)
+struct tty_struct *tty_table[256];
+struct termios *tty_termios[256]; /* We need to keep the termios state */
+ /* around, even when a tty is closed */
/*
* fg_console is the current virtual console,
@@ -47,12 +50,9 @@ struct tty_struct tty_table[256];
*/
int fg_console = 0;
struct tty_struct * redirect = NULL;
+struct wait_queue * keypress_wait;
-/*
- * these are the tables used by the machine code handlers.
- * you can implement virtual consoles.
- */
-struct tty_queue * table_list[] = { NULL, NULL };
+int initialize_tty_struct(struct tty_struct *tty, int line);
void inline put_tty_queue(char c, struct tty_queue * queue)
{
@@ -84,7 +84,7 @@ int inline get_tty_queue(struct tty_queue * queue)
void inline tty_write_flush(struct tty_struct * tty)
{
- if (EMPTY(tty->write_q))
+ if (!tty->write || EMPTY(&tty->write_q))
return;
if (set_bit(TTY_WRITE_BUSY,&tty->flags))
return;
@@ -95,7 +95,7 @@ void inline tty_write_flush(struct tty_struct * tty)
void tty_read_flush(struct tty_struct * tty)
{
- if (EMPTY(tty->read_q))
+ if (EMPTY(&tty->read_q))
return;
if (set_bit(TTY_READ_BUSY, &tty->flags))
return;
@@ -110,38 +110,39 @@ void change_console(unsigned int new_console)
return;
if (new_console == fg_console || new_console >= NR_CONSOLES)
return;
- table_list[0] = con_queues + 0 + new_console*3;
- table_list[1] = con_queues + 1 + new_console*3;
update_screen(new_console);
}
-static void sleep_if_empty(struct tty_queue * queue)
-{
- cli();
- while (!(current->signal & ~current->blocked) && EMPTY(queue))
- interruptible_sleep_on(&queue->proc_list);
- sti();
-}
-
void wait_for_keypress(void)
{
- sleep_if_empty(tty_table[fg_console].secondary);
- flush_input(&tty_table[fg_console]);
+ interruptible_sleep_on(&keypress_wait);
}
void copy_to_cooked(struct tty_struct * tty)
{
int c;
- if (!(tty && tty->write && tty->read_q &&
- tty->write_q && tty->secondary)) {
- printk("copy_to_cooked: missing queues\n\r");
+ if (!tty) {
+ printk("copy_to_cooked: called with NULL tty\n");
return;
}
+ if (!tty->write) {
+ printk("copy_to_cooked: tty %d has null write routine\n",
+ tty->line);
+ }
while (1) {
- if (FULL(tty->secondary))
+ /*
+ * Check to see how much room we have left in the
+ * secondary queue. Send a throttle command or abort
+ * if necessary.
+ */
+ c = LEFT(&tty->secondary);
+ if (tty->throttle && (c < SQ_THRESHOLD_LW)
+ && !set_bit(TTY_SQ_THROTTLED, &tty->flags))
+ tty->throttle(tty, TTY_THROTTLE_SQ_FULL);
+ if (c == 0)
break;
- c = get_tty_queue(tty->read_q);
+ c = get_tty_queue(&tty->read_q);
if (c < 0)
break;
if (I_STRP(tty))
@@ -159,42 +160,42 @@ void copy_to_cooked(struct tty_struct * tty)
if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
(c==KILL_CHAR(tty))) {
/* deal with killing the input line */
- while(!(EMPTY(tty->secondary) ||
- (c=LAST(tty->secondary))==10 ||
+ while(!(EMPTY(&tty->secondary) ||
+ (c=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) &&
(c==EOF_CHAR(tty))))) {
if (L_ECHO(tty)) {
if (c<32) {
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
+ put_tty_queue(8, &tty->write_q);
+ put_tty_queue(' ', &tty->write_q);
+ put_tty_queue(8,&tty->write_q);
}
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
+ put_tty_queue(8,&tty->write_q);
+ put_tty_queue(' ',&tty->write_q);
+ put_tty_queue(8,&tty->write_q);
}
- DEC(tty->secondary->head);
+ DEC(tty->secondary.head);
}
continue;
}
if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
(c==ERASE_CHAR(tty))) {
- if (EMPTY(tty->secondary) ||
- (c=LAST(tty->secondary))==10 ||
+ if (EMPTY(&tty->secondary) ||
+ (c=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) &&
(c==EOF_CHAR(tty))))
continue;
if (L_ECHO(tty)) {
if (c<32) {
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
+ put_tty_queue(8,&tty->write_q);
+ put_tty_queue(' ',&tty->write_q);
+ put_tty_queue(8,&tty->write_q);
}
- put_tty_queue(8,tty->write_q);
- put_tty_queue(32,tty->write_q);
- put_tty_queue(8,tty->write_q);
+ put_tty_queue(8,&tty->write_q);
+ put_tty_queue(32,&tty->write_q);
+ put_tty_queue(8,&tty->write_q);
}
- DEC(tty->secondary->head);
+ DEC(tty->secondary.head);
continue;
}
}
@@ -236,24 +237,28 @@ void copy_to_cooked(struct tty_struct * tty)
}
if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
c==EOF_CHAR(tty)))
- tty->secondary->data++;
+ tty->secondary.data++;
if ((c==10) && (L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty)))) {
- put_tty_queue(10,tty->write_q);
- put_tty_queue(13,tty->write_q);
+ put_tty_queue(10,&tty->write_q);
+ put_tty_queue(13,&tty->write_q);
} else if (L_ECHO(tty)) {
if (c<32 && L_ECHOCTL(tty)) {
- put_tty_queue('^',tty->write_q);
- put_tty_queue(c+64,tty->write_q);
+ put_tty_queue('^',&tty->write_q);
+ put_tty_queue(c+64, &tty->write_q);
} else
- put_tty_queue(c,tty->write_q);
+ put_tty_queue(c, &tty->write_q);
}
- put_tty_queue(c,tty->secondary);
+ put_tty_queue(c, &tty->secondary);
}
TTY_WRITE_FLUSH(tty);
- if (!EMPTY(tty->secondary))
- wake_up(&tty->secondary->proc_list);
- if (tty->write_q->proc_list && LEFT(tty->write_q) > TTY_BUF_SIZE/2)
- wake_up(&tty->write_q->proc_list);
+ if (!EMPTY(&tty->secondary))
+ wake_up(&tty->secondary.proc_list);
+ if (tty->write_q.proc_list && LEFT(&tty->write_q) > TTY_BUF_SIZE/2)
+ wake_up(&tty->write_q.proc_list);
+ if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW)
+ && !clear_bit(TTY_RQ_THROTTLED, &tty->flags))
+ tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);
+
}
int is_ignored(int sig)
@@ -262,27 +267,6 @@ int is_ignored(int sig)
(current->sigaction[sig-1].sa_handler == SIG_IGN));
}
-/*
- * Called when we need to send a SIGTTIN or SIGTTOU to our process
- * group
- *
- * We only request that a system call be restarted if there was if the
- * default signal handler is being used. The reason for this is that if
- * a job is catching SIGTTIN or SIGTTOU, the signal handler may not want
- * the system call to be restarted blindly. If there is no way to reset the
- * terminal pgrp back to the current pgrp (perhaps because the controlling
- * tty has been released on logout), we don't want to be in an infinite loop
- * while restarting the system call, and have it always generate a SIGTTIN
- * or SIGTTOU. The default signal handler will cause the process to stop
- * thus avoiding the infinite loop problem. Presumably the job-control
- * cognizant parent will fix things up before continuging its child process.
- */
-int tty_signal(int sig, struct tty_struct *tty)
-{
- (void) kill_pg(current->pgrp,sig,1);
- return -ERESTARTSYS;
-}
-
static void wait_for_canon_input(struct tty_struct * tty)
{
while (1) {
@@ -294,13 +278,13 @@ static void wait_for_canon_input(struct tty_struct * tty)
return;
if (current->signal & ~current->blocked)
return;
- if (FULL(tty->read_q))
+ if (FULL(&tty->read_q))
return;
- if (tty->secondary->data)
+ if (tty->secondary.data)
return;
cli();
- if (!tty->secondary->data)
- interruptible_sleep_on(&tty->secondary->proc_list);
+ if (!tty->secondary.data)
+ interruptible_sleep_on(&tty->secondary.proc_list);
sti();
}
}
@@ -315,20 +299,22 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
if (channel > 255)
return -EIO;
tty = TTY_TABLE(channel);
- if (!(tty->read_q && tty->secondary))
+ if (!tty)
return -EIO;
if ((tty->pgrp > 0) &&
(current->tty == channel) &&
(tty->pgrp != current->pgrp))
if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
return -EIO;
- else
- return(tty_signal(SIGTTIN, tty));
+ else {
+ (void) kill_pg(current->pgrp, SIGTTIN, 1);
+ return -ERESTARTSYS;
+ }
if (L_CANON(tty))
minimum = time = current->timeout = 0;
else {
- time = 10L*tty->termios.c_cc[VTIME];
- minimum = tty->termios.c_cc[VMIN];
+ time = 10L*tty->termios->c_cc[VTIME];
+ minimum = tty->termios->c_cc[VMIN];
if (minimum)
current->timeout = 0xffffffff;
else {
@@ -372,10 +358,10 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
TTY_READ_FLUSH(tty);
if (tty->link)
TTY_WRITE_FLUSH(tty->link);
- while (nr > 0 && ((c = get_tty_queue(tty->secondary)) >= 0)) {
+ while (nr > 0 && ((c = get_tty_queue(&tty->secondary)) >= 0)) {
if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
c==EOF_CHAR(tty)) || c==10)
- tty->secondary->data--;
+ tty->secondary.data--;
if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
c==EOF_CHAR(tty)) && L_CANON(tty))
break;
@@ -386,7 +372,7 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
if (c==10 && L_CANON(tty))
break;
};
- wake_up(&tty->read_q->proc_list);
+ wake_up(&tty->read_q.proc_list);
if (b-buf >= minimum || !current->timeout)
break;
if (current->signal & ~current->blocked)
@@ -396,9 +382,16 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
TTY_READ_FLUSH(tty);
if (tty->link)
TTY_WRITE_FLUSH(tty->link);
+ /*
+ * If there is enough space in the secondary queue
+ * now, let the low-level driver know.
+ */
+ if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
+ && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
+ tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
cli();
- if (EMPTY(tty->secondary))
- interruptible_sleep_on(&tty->secondary->proc_list);
+ if (EMPTY(&tty->secondary))
+ interruptible_sleep_on(&tty->secondary.proc_list);
sti();
}
TTY_READ_FLUSH(tty);
@@ -433,22 +426,25 @@ static int write_chan(unsigned int channel, struct file * file, char * buf, int
if (channel > 255)
return -EIO;
- tty = TTY_TABLE(channel);
+ if (redirect && ((channel == 0) || (channel+1 == fg_console)))
+ tty = redirect;
+ else
+ tty = TTY_TABLE(channel);
+ if (!tty || !tty->write)
+ return -EIO;
if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
(current->tty == channel) && (tty->pgrp != current->pgrp)) {
if (is_orphaned_pgrp(tty->pgrp))
return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
+ if (!is_ignored(SIGTTOU)) {
+ (void) kill_pg(current->pgrp, SIGTTOU, 1);
+ return -ERESTARTSYS;
+ }
}
if (nr < 0)
return -EINVAL;
if (!nr)
return 0;
- if (redirect && tty == TTY_TABLE(0))
- tty = redirect;
- if (!(tty->write_q && tty->write))
- return -EIO;
while (nr>0) {
if (current->signal & ~current->blocked)
break;
@@ -456,15 +452,15 @@ static int write_chan(unsigned int channel, struct file * file, char * buf, int
send_sig(SIGPIPE,current,0);
break;
}
- if (FULL(tty->write_q)) {
+ if (FULL(&tty->write_q)) {
TTY_WRITE_FLUSH(tty);
cli();
- if (FULL(tty->write_q))
- interruptible_sleep_on(&tty->write_q->proc_list);
+ if (FULL(&tty->write_q))
+ interruptible_sleep_on(&tty->write_q.proc_list);
sti();
continue;
}
- while (nr>0 && !FULL(tty->write_q)) {
+ while (nr>0 && !FULL(&tty->write_q)) {
c=get_fs_byte(b);
if (O_POST(tty)) {
if (c=='\r' && O_CRNL(tty))
@@ -473,7 +469,7 @@ static int write_chan(unsigned int channel, struct file * file, char * buf, int
c='\r';
if (c=='\n' && O_NLCR(tty) &&
!set_bit(TTY_CR_PENDING,&tty->flags)) {
- put_tty_queue(13,tty->write_q);
+ put_tty_queue(13,&tty->write_q);
continue;
}
if (O_LCUC(tty))
@@ -481,7 +477,7 @@ static int write_chan(unsigned int channel, struct file * file, char * buf, int
}
b++; nr--;
clear_bit(TTY_CR_PENDING,&tty->flags);
- put_tty_queue(c,tty->write_q);
+ put_tty_queue(c,&tty->write_q);
}
if (nr>0)
schedule();
@@ -539,7 +535,7 @@ static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int
*/
static int tty_open(struct inode * inode, struct file * filp)
{
- struct tty_struct *tty;
+ struct tty_struct *tty, *o_tty;
int dev, retval;
dev = inode->i_rdev;
@@ -551,10 +547,32 @@ static int tty_open(struct inode * inode, struct file * filp)
return -ENODEV;
filp->f_rdev = 0x0400 | dev;
tty = TTY_TABLE(dev);
- if (!tty->count && !(tty->link && tty->link->count)) {
- flush_input(tty);
- flush_output(tty);
- tty->stopped = 0;
+ if (!tty) {
+ tty = TTY_TABLE(dev) = (struct tty_struct *)
+ get_free_page(GFP_KERNEL);
+ if (!tty)
+ return -ENOMEM;
+ retval = initialize_tty_struct(tty, TTY_TABLE_IDX(dev));
+ if (retval) {
+ free_page((unsigned long)tty);
+ return retval;
+ }
+ if (IS_A_PTY(dev) && !tty_table[PTY_OTHER(dev)]) {
+ o_tty = tty_table[PTY_OTHER(dev)] =
+ (struct tty_struct *) get_free_page(GFP_USER);
+ if (!o_tty) {
+ free_page((unsigned long)tty);
+ return -ENOMEM;
+ }
+ retval = initialize_tty_struct(o_tty, PTY_OTHER(dev));
+ if (retval) {
+ free_page((unsigned long) tty);
+ free_page((unsigned long) o_tty);
+ return retval;
+ }
+ tty->link = o_tty;
+ o_tty->link = tty;
+ }
}
if (IS_A_PTY_MASTER(dev)) {
if (tty->count)
@@ -565,7 +583,7 @@ static int tty_open(struct inode * inode, struct file * filp)
/* perhaps user applications that don't take care of
this deserve what the get, but I think my system
has hung do to this, esp. in X. -RAB */
- tty->termios.c_lflag &= ~ECHO;
+ tty->termios->c_lflag &= ~ECHO;
}
tty->count++;
retval = 0;
@@ -583,10 +601,10 @@ static int tty_open(struct inode * inode, struct file * filp)
tty->session = current->session;
tty->pgrp = current->pgrp;
}
- if (IS_A_SERIAL(dev) && tty->count < 2)
- retval = serial_open(dev-64,filp);
- else if (IS_A_PTY(dev))
- retval = pty_open(dev,filp);
+ if (tty->open)
+ retval = tty->open(tty, filp);
+ else
+ retval = -ENODEV;
if (retval) {
tty->count--;
if (IS_A_PTY_MASTER(dev) && tty->link)
@@ -607,26 +625,44 @@ static void tty_release(struct inode * inode, struct file * filp)
dev = filp->f_rdev;
if (MAJOR(dev) != 4) {
- printk("tty_close: tty pseudo-major != 4\n");
+ printk("tty_release: tty pseudo-major != 4\n");
return;
}
dev = MINOR(filp->f_rdev);
tty = TTY_TABLE(dev);
- if (IS_A_PTY_MASTER(dev) && tty->link)
- tty->link->count--;
- tty->count--;
+ if (!tty) {
+ printk("tty_release: TTY_TABLE(%d) was NULL\n", dev);
+ return;
+ }
+ if (IS_A_PTY_MASTER(dev) && tty->link) {
+ if (--tty->link->count < 0) {
+ printk("tty_release: bad tty slave count (dev = %d): %d\n",
+ dev, tty->count);
+ tty->link->count = 0;
+ }
+ }
+ if (--tty->count < 0) {
+ printk("tty_release: bad TTY_TABLE(%d)->count: %d\n",
+ dev, tty->count);
+ tty->count = 0;
+ }
if (tty->count)
return;
- if (IS_A_SERIAL(dev)) {
- wait_until_sent(tty);
- serial_close(dev-64,filp);
- } else if (IS_A_PTY(dev))
- pty_close(dev,filp);
+ if (tty->close)
+ tty->close(tty, filp);
if (!tty->count && (tty == redirect))
redirect = NULL;
if (tty = tty->link)
if (!tty->count && (tty == redirect))
redirect = NULL;
+ if (!tty->count && !(tty->link && tty->link->count)) {
+ if (tty->link) {
+ free_page((unsigned long) TTY_TABLE(PTY_OTHER(dev)));
+ TTY_TABLE(PTY_OTHER(dev)) = 0;
+ }
+ free_page((unsigned long) TTY_TABLE(dev));
+ TTY_TABLE(dev) = 0;
+ }
}
static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
@@ -641,9 +677,13 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
}
dev = MINOR(filp->f_rdev);
tty = TTY_TABLE(dev);
+ if (!tty) {
+ printk("tty_select: tty struct for dev %d was NULL\n", dev);
+ return 0;
+ }
switch (sel_type) {
case SEL_IN:
- if (!EMPTY(tty->secondary))
+ if (!EMPTY(&tty->secondary))
return 1;
if (tty->link && !tty->link->count)
return 1;
@@ -653,12 +693,12 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
tty->link->status_changed)
return 1;
- select_wait(&tty->secondary->proc_list, wait);
+ select_wait(&tty->secondary.proc_list, wait);
return 0;
case SEL_OUT:
- if (!FULL(tty->write_q))
+ if (!FULL(&tty->write_q))
return 1;
- select_wait(&tty->write_q->proc_list, wait);
+ select_wait(&tty->write_q.proc_list, wait);
return 0;
case SEL_EX:
if (tty->link && !tty->link->count)
@@ -679,106 +719,67 @@ static struct file_operations tty_fops = {
tty_release
};
+/*
+ * This subroutine initializes a tty structure. We have to set up
+ * things correctly for each different type of tty.
+ */
+int initialize_tty_struct(struct tty_struct *tty, int line)
+{
+ struct termios *tp;
+
+ memset(tty, 0, sizeof(struct tty_struct));
+ tty->line = line;
+ tty->pgrp = -1;
+ tty->winsize.ws_row = 24;
+ tty->winsize.ws_col = 80;
+ if (!tty_termios[line]) {
+ tp = tty_termios[line] = malloc(sizeof(struct termios));
+ if (!tp)
+ return -ENOMEM;
+ memset(tp, 0, sizeof(struct termios));
+ memcpy(tp->c_cc, INIT_C_CC, NCCS);
+ if (IS_A_CONSOLE(line)) {
+ tp->c_iflag = ICRNL;
+ tp->c_oflag = OPOST | ONLCR;
+ tp->c_cflag = B38400 | CS8;
+ tp->c_lflag = IXON | ISIG | ICANON | ECHO |
+ ECHOCTL | ECHOKE;
+ } else if IS_A_SERIAL(line) {
+ tp->c_cflag = B2400 | CS8;
+ } else if IS_A_PTY_MASTER(line) {
+ tp->c_cflag = B9600 | CS8;
+ } else if IS_A_PTY_SLAVE(line) {
+ tp->c_cflag = B9600 | CS8;
+ tp->c_lflag = IXON | ISIG | ICANON;
+ }
+ }
+ tty->termios = tty_termios[line];
+
+ if (IS_A_CONSOLE(line)) {
+ tty->open = con_open;
+ tty->winsize.ws_row = video_num_lines;
+ tty->winsize.ws_col = video_num_columns;
+ } else if IS_A_SERIAL(line) {
+ tty->open = rs_open;
+ } else if IS_A_PTY(line) {
+ tty->open = pty_open;
+ }
+ return 0;
+}
+
long tty_init(long kmem_start)
{
int i;
- tty_queues = (struct tty_queue *) kmem_start;
- kmem_start += QUEUES * (sizeof (struct tty_queue));
- table_list[0] = con_queues + 0;
- table_list[1] = con_queues + 1;
chrdev_fops[4] = &tty_fops;
chrdev_fops[5] = &tty_fops;
- for (i=0 ; i < QUEUES ; i++)
- tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
+ keypress_wait = 0;
for (i=0 ; i<256 ; i++) {
- tty_table[i] = (struct tty_struct) {
- {0, 0, 0, 0, 0, INIT_C_CC},
- -1, 0, 0, 0, 0, 0, 0, 0, 0, {0,0,0,0},
- NULL, NULL, NULL, NULL, NULL
- };
+ tty_table[i] = 0;
+ tty_termios[i] = 0;
}
kmem_start = con_init(kmem_start);
- for (i = 0 ; i<NR_CONSOLES ; i++) {
- con_table[i] = (struct tty_struct) {
- {ICRNL, /* change incoming CR to NL */
- OPOST|ONLCR, /* change outgoing NL to CRNL */
- B38400 | CS8,
- IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
- 0, /* console termio */
- INIT_C_CC},
- -1, /* initial pgrp */
- 0, /* initial session */
- 0, /* initial stopped */
- 0, /* initial status_changed */
- 0, /* initial packet */
- 0, /* initial ctrl_status */
- 0, /* initial unused */
- 0, /* initial flags */
- 0, /* initial count */
- {video_num_lines,video_num_columns,0,0},
- con_write,
- NULL, /* other-tty */
- con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
- };
- }
- for (i = 0 ; i<NR_SERIALS ; i++) {
- rs_table[i] = (struct tty_struct) {
- {0, /* no translation */
- 0, /* no translation */
- B2400 | CS8,
- 0,
- 0,
- INIT_C_CC},
- -1,
- 0,
- 0, 0, 0, 0, 0,
- 0,
- 0,
- {24,80,0,0},
- rs_write,
- NULL, /* other-tty */
- rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3
- };
- }
- for (i = 0 ; i<NR_PTYS ; i++) {
- mpty_table[i] = (struct tty_struct) {
- {0, /* no translation */
- 0, /* no translation */
- B9600 | CS8,
- 0,
- 0,
- INIT_C_CC},
- -1,
- 0,
- 0, 0, 0, 0, 0,
- 0,
- 0,
- {24,80,0,0},
- mpty_write,
- spty_table+i,
- mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
- };
- spty_table[i] = (struct tty_struct) {
- {0, /* no translation */
- 0, /* no translation */
- B9600 | CS8,
- IXON | ISIG | ICANON,
- 0,
- INIT_C_CC},
- -1,
- 0,
- 0, 0, 0, 0, 0,
- 0,
- 0,
- {24,80,0,0},
- spty_write,
- mpty_table+i,
- spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
- };
- }
kmem_start = rs_init(kmem_start);
printk("%d virtual consoles\n\r",NR_CONSOLES);
- printk("%d pty's\n\r",NR_PTYS);
return kmem_start;
}
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index b92dcb4..4b2996e 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -19,7 +19,6 @@
extern int session_of_pgrp(int pgrp);
extern int do_screendump(int arg);
extern int kill_pg(int pgrp, int sig, int priv);
-extern int vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg);
static void flush(struct tty_queue * queue)
{
@@ -35,17 +34,14 @@ void flush_input(struct tty_struct * tty)
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_FLUSHREAD;
- if (tty->read_q) {
- flush(tty->read_q);
- wake_up(&tty->read_q->proc_list);
- }
- if (tty->secondary) {
- flush(tty->secondary);
- tty->secondary->data = 0;
- }
- if ((tty = tty->link) && tty->write_q) {
- flush(tty->write_q);
- wake_up(&tty->write_q->proc_list);
+ flush(&tty->read_q);
+ wake_up(&tty->read_q.proc_list);
+ flush(&tty->secondary);
+ tty->secondary.data = 0;
+
+ if (tty = tty->link) {
+ flush(&tty->write_q);
+ wake_up(&tty->write_q.proc_list);
}
}
@@ -53,32 +49,27 @@ void flush_output(struct tty_struct * tty)
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
- if (tty->write_q) {
- flush(tty->write_q);
- wake_up(&tty->write_q->proc_list);
- }
+ flush(&tty->write_q);
+ wake_up(&tty->write_q.proc_list);
if (tty = tty->link) {
- if (tty->read_q) {
- flush(tty->read_q);
- wake_up(&tty->read_q->proc_list);
- }
- if (tty->secondary) {
- flush(tty->secondary);
- tty->secondary->data = 0;
- }
+ flush(&tty->read_q);
+ wake_up(&tty->read_q.proc_list);
+ flush(&tty->secondary);
+ tty->secondary.data = 0;
}
}
void wait_until_sent(struct tty_struct * tty)
{
- while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
+ while (!(current->signal & ~current->blocked) &&
+ !EMPTY(&tty->write_q)) {
TTY_WRITE_FLUSH(tty);
current->counter = 0;
cli();
- if (EMPTY(tty->write_q))
+ if (EMPTY(&tty->write_q))
break;
else
- interruptible_sleep_on(&tty->write_q->proc_list);
+ interruptible_sleep_on(&tty->write_q.proc_list);
sti();
}
sti();
@@ -118,7 +109,7 @@ static int get_termios(struct tty_struct * tty, struct termios * termios)
verify_area(termios, sizeof (*termios));
for (i=0 ; i< (sizeof (*termios)) ; i++)
- put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
+ put_fs_byte( ((char *)tty->termios)[i] , i+(char *)termios );
return 0;
}
@@ -126,7 +117,7 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
int channel)
{
int i;
- unsigned short old_cflag = tty->termios.c_cflag;
+ unsigned short old_cflag = tty->termios->c_cflag;
/* If we try to set the state of terminal and we're not in the
foreground, send a SIGTTOU. If the signal is blocked or
@@ -135,18 +126,20 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
(tty->pgrp != current->pgrp)) {
if (is_orphaned_pgrp(current->pgrp))
return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
+ if (!is_ignored(SIGTTOU)) {
+ (void) kill_pg(current->pgrp,SIGTTOU,1);
+ return -ERESTARTSYS;
+ }
}
for (i=0 ; i< (sizeof (*termios)) ; i++)
- ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
- if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
+ ((char *)tty->termios)[i]=get_fs_byte(i+(char *)termios);
+ if (IS_A_SERIAL(channel) && tty->termios->c_cflag != old_cflag)
change_speed(channel-64);
/* puting mpty's into echo mode is very bad, and I think under
some situations can cause the kernel to do nothing but
copy characters back and forth. -RAB */
- if (IS_A_PTY_MASTER(channel)) tty->termios.c_lflag &= ~ECHO;
+ if (IS_A_PTY_MASTER(channel)) tty->termios->c_lflag &= ~ECHO;
return 0;
}
@@ -157,13 +150,13 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
struct termio tmp_termio;
verify_area(termio, sizeof (*termio));
- tmp_termio.c_iflag = tty->termios.c_iflag;
- tmp_termio.c_oflag = tty->termios.c_oflag;
- tmp_termio.c_cflag = tty->termios.c_cflag;
- tmp_termio.c_lflag = tty->termios.c_lflag;
- tmp_termio.c_line = tty->termios.c_line;
+ tmp_termio.c_iflag = tty->termios->c_iflag;
+ tmp_termio.c_oflag = tty->termios->c_oflag;
+ tmp_termio.c_cflag = tty->termios->c_cflag;
+ tmp_termio.c_lflag = tty->termios->c_lflag;
+ tmp_termio.c_line = tty->termios->c_line;
for(i=0 ; i < NCC ; i++)
- tmp_termio.c_cc[i] = tty->termios.c_cc[i];
+ tmp_termio.c_cc[i] = tty->termios->c_cc[i];
for (i=0 ; i< (sizeof (*termio)) ; i++)
put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
return 0;
@@ -177,42 +170,44 @@ static int set_termio(struct tty_struct * tty, struct termio * termio,
{
int i;
struct termio tmp_termio;
- unsigned short old_cflag = tty->termios.c_cflag;
+ unsigned short old_cflag = tty->termios->c_cflag;
if ((current->tty == channel) &&
(tty->pgrp > 0) &&
(tty->pgrp != current->pgrp)) {
if (is_orphaned_pgrp(current->pgrp))
return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
+ if (!is_ignored(SIGTTOU)) {
+ (void) kill_pg(current->pgrp,SIGTTOU,1);
+ return -ERESTARTSYS;
+ }
}
for (i=0 ; i< (sizeof (*termio)) ; i++)
((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
/* take care of the packet stuff. */
if ((tmp_termio.c_iflag & IXON) &&
- ~(tty->termios.c_iflag & IXON))
+ ~(tty->termios->c_iflag & IXON))
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_DOSTOP;
}
if (~(tmp_termio.c_iflag & IXON) &&
- (tty->termios.c_iflag & IXON))
+ (tty->termios->c_iflag & IXON))
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_NOSTOP;
}
- *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
- *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
- *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
- *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
- tty->termios.c_line = tmp_termio.c_line;
+ *(unsigned short *)&tty->termios->c_iflag = tmp_termio.c_iflag;
+ *(unsigned short *)&tty->termios->c_oflag = tmp_termio.c_oflag;
+ *(unsigned short *)&tty->termios->c_cflag = tmp_termio.c_cflag;
+ *(unsigned short *)&tty->termios->c_lflag = tmp_termio.c_lflag;
+ tty->termios->c_line = tmp_termio.c_line;
for(i=0 ; i < NCC ; i++)
- tty->termios.c_cc[i] = tmp_termio.c_cc[i];
- if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
+ tty->termios->c_cc[i] = tmp_termio.c_cc[i];
+ if (IS_A_SERIAL(channel) && tty->termios->c_cflag != old_cflag)
change_speed(channel-64);
return 0;
}
@@ -265,15 +260,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
return -EINVAL;
}
dev = MINOR(file->f_rdev);
- tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
+ tty = TTY_TABLE(dev);
+ if (!tty)
+ return -EINVAL;
if (IS_A_PTY(dev))
- other_tty = tty_table + PTY_OTHER(dev);
+ other_tty = tty_table[PTY_OTHER(dev)];
else
other_tty = NULL;
- if (!(tty->write_q && tty->read_q && tty->secondary && tty->write))
- return -EINVAL;
switch (cmd) {
case TCGETS:
return get_termios(tty,(struct termios *) arg);
@@ -294,13 +289,6 @@ int tty_ioctl(struct inode * inode, struct file * file,
wait_until_sent(tty); /* fallthrough */
case TCSETA:
return set_termio(tty,(struct termio *) arg, dev);
- case TCSBRK:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- wait_until_sent(tty);
- if (!arg)
- send_break(dev-64);
- return 0;
case TCXONC:
switch (arg) {
case TCOOFF:
@@ -313,11 +301,13 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0;
case TCIOFF:
if (STOP_CHAR(tty))
- put_tty_queue(STOP_CHAR(tty),tty->write_q);
+ put_tty_queue(STOP_CHAR(tty),
+ &tty->write_q);
return 0;
case TCION:
if (START_CHAR(tty))
- put_tty_queue(START_CHAR(tty),tty->write_q);
+ put_tty_queue(START_CHAR(tty),
+ &tty->write_q);
return 0;
}
return -EINVAL; /* not implemented */
@@ -356,14 +346,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0;
case TIOCOUTQ:
verify_area((void *) arg,4);
- put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
+ put_fs_long(CHARS(&tty->write_q),
+ (unsigned long *) arg);
return 0;
case TIOCINQ:
verify_area((void *) arg,4);
- if (L_CANON(tty) && !tty->secondary->data)
+ if (L_CANON(tty) && !tty->secondary.data)
put_fs_long(0, (unsigned long *) arg);
else
- put_fs_long(CHARS(tty->secondary),
+ put_fs_long(CHARS(&tty->secondary),
(unsigned long *) arg);
return 0;
case TIOCSTI:
@@ -374,17 +365,6 @@ int tty_ioctl(struct inode * inode, struct file * file,
if (IS_A_PTY_MASTER(dev))
set_window_size(other_tty,(struct winsize *) arg);
return set_window_size(tty,(struct winsize *) arg);
- case TIOCMGET:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- verify_area((void *) arg,sizeof(unsigned int *));
- return get_modem_info(dev-64,(unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- return set_modem_info(dev-64,cmd,(unsigned int *) arg);
case TIOCGSOFTCAR:
return -EINVAL; /* not implemented */
case TIOCSSOFTCAR:
@@ -411,15 +391,6 @@ int tty_ioctl(struct inode * inode, struct file * file,
else
redirect = tty;
return 0;
- case TIOCGSERIAL:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- verify_area((void *) arg,sizeof(struct serial_struct));
- return get_serial_info(dev-64,(struct serial_struct *) arg);
- case TIOCSSERIAL:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- return set_serial_info(dev-64,(struct serial_struct *) arg);
case FIONBIO:
if (arg)
file->f_flags |= O_NONBLOCK;
@@ -453,6 +424,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
}
default:
- return vt_ioctl(tty, dev, cmd, arg);
+ if (tty->ioctl)
+ return (tty->ioctl)(tty, file, cmd, arg);
+ else
+ return -EINVAL;
}
}
diff --git a/kernel/chr_drv/vt.c b/kernel/chr_drv/vt.c
index 81702d6..acb6dc7 100644
--- a/kernel/chr_drv/vt.c
+++ b/kernel/chr_drv/vt.c
@@ -63,16 +63,18 @@ kiocsound(unsigned int freq)
}
/*
- * all the vt ioctls affect only consoles, so we reject all other ttys.
- * we also have the capability to modify any console, not just the fg_console.
+ * We handle the console-specific ioctl's here. We allow the
+ * capability to modify any console, not just the fg_console.
*/
-int
-vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg)
+int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned int arg)
{
- int console = dev ? dev - 1 : fg_console;
+ int console;
unsigned char ucval;
- if (!IS_A_CONSOLE(dev) || console < 0 || console >= NR_CONSOLES)
+ console = tty->line - 1;
+
+ if (console < 0 || console >= NR_CONSOLES)
return -EINVAL;
switch (cmd) {