aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Benedict Torvalds <torvalds@klaava.Helsinki.FI>1992-03-18 00:32:46 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:02 -0400
commitedb046236801c4975482840240127aeefdd0f7d7 (patch)
treef204d177cb6e85af83b46c2ee9653677a40be9cb
parent741d52384b75d810b8a04d7f16733b9a6ff809a5 (diff)
downloadarchive-edb046236801c4975482840240127aeefdd0f7d7.tar.gz
0.95a uploaded - soon availablev0.95a
I just uploaded the new kernel source and image to nic.funet.fi into the incoming-directory under linux. As usual, they won't show up for a day or two: wait for arl to announce that it's available. The new version called 0.95a has no major new features, and is just a bug-fix release for 0.95 - it hopefully fixes all known bugs, but that's what I thought about plain 0.95 :(. There are even less installation documents than before: (a) they haven't changed since 0.95 and (b) the rootdisk is no longer made by me (which means that 0.95a will probably be the first release that actually has all the needed device special files there.) Everyone's favourite bug is also fixed: 0.95a actually returns the correct version number from uname(). (Boy did I get bug reports on this one :^) I'm including the release-note at the end of the post. Linus PS: Whoever made the GNU-emacs binary available for linux - the inability to use the "meta-X shell" command is a bit disturbing. I looked into it a bit, and my guess is that the linux config file doesn't define HAVE_SETSID. Could somebody with more diskspace than I have try to recompile gemacs with HAVE_SETSID defined, and tell me if this fixes the problem? ========== RELEASE NOTES FOR LINUX v0.95a Linus Torvalds, March 17, 1992 This is file mostly contains info on changed features of Linux, and using old versions as a help-reference might be a good idea. COPYRIGHT Linux-0.95a is NOT public domain software, but is copyrighted by me. The copyright conditions are the same as those imposed by the GNU copyleft: get a copy of the GNU copyleft at any major ftp-site (if it carries linux, it probably carries a lot of GNU software anyway, and they all contain the copyright). The copyleft is pretty detailed, but it mostly just means that you may freely copy linux for your own use, and redistribute all/parts of it, as long as you make source available (not necessarily in the same distribution, but you make it clear how people can get it for nothing more than copying costs). Any changes you make that you distribute will also automatically fall under the GNU copyleft. NOTE! The linux unistd library-functions (the low-level interface to linux: system calls etc) are excempt from the copyright - you may use them as you wish, and using those in your binary files won't mean that your files are automatically under the GNU copyleft. This concerns /only/ the unistd-library and those (few) other library functions I have written: most of the rest of the library has it's own copyrights (or is public domain). See the library sources for details of those. NEW FEATURES OF 0.95a 0.95a is mainly a bug-fix release: it didn't even get it's own version number. Plain 0.95 fixed a lot of bugs in 0.12, but also introduced totally new bugs: 0.95a tries to correct these. The bugs corrected (knock wood) are: - floppy and harddisk drivers should now once more work with most hardware: I'd be interested in reports of "unexpected HD interrupt" and "reset-floppy called" with the new kernel. - A rather serious tty-bug corrected: this one messed up the screen under 0.95, and switched characters over the serial lines. Under extreme circumstances it could even crash the machine. - ptrace had a bug: hopefully it works now. - The extended partitions didn't work under 0.95, although most of the code was there. Please somebody tell me it works under 0.95a. - the 0.95 fdisk was broken: a new one with the new root-floppy should clear up the confusion. - select() and the sleep-wakeup code had fundamental (but relatively benign) problems under 0.95 (and all earlier versions). The sleeping code is totally redesigned, and select should work better even under load. One actual new feature, not just a bug-fix: - ser3-4 support is there, although I've been unable to test it (as I haven't got more than ser2). NOTE! Due to AT hardware limitations, ser1 cannot be active at the same time as ser3, and likewise ser2 and ser4 are mutually exclusive. The interrupt-handlers should have no problems with shared interrupts, but the actual hardware probably has, so the kernel disables interrupts from one serial line when the other one is opened. - faster default keyrepeat rate: this is going to need some getting used to, but is extremely practical especially with bigger screen sizes. - VGA cards that aren't recognized at bootup are put into the 80x50 character mode if <enter> was pressed when asking about SVGA modes. NEW FEATURES OF 0.95 Init/login Yeah, thanks to poe (Peter Orbaeck (sp?)), linux now boots up like a real unix with a login-prompt. Login as root (no passwd), and change your /etc/passwd to your hearts delight (and add other logins in /etc/inittab etc). Virtual consoles on any (?) hardware. You can select one of several consoles by pressing the left alt-key and a function key at the same time. Linux should report the number of virtual consoles available upon bootup. /dev/tty0 is now "the current" screen, /dev/tty1 is the main console, and /dev/tty2-8 can exist depending on your text-mode or card. The virtual consoles also have some new screen-handling commands: they confirm even better to vt200 control codes than 0.11. Special graphic characters etc: you can well use them as terminals to VMS (although that's a shameful waste of resources), and the PF1-4 keys work somewhat in the application-key mode. Extended vt200 emulation 0.95 contains code to handle a vt200 application keymap mode: the cursor keys send slightly different codes when in application mode, and the numeric keyboard tries to emulate the vt200 application keys. This probably isn't complete yet. Symbolic links. 0.95 now allows symlinks to point to other symlinks etc (the maximum depth is a rather arbitrary 5 links). 0.12 didn't like more than one level of indirection. Virtual memory. VM under 0.95 should be better than under 0.12: no more lockups (as far as I have seen), and you can now swap to the filesystem as well as to a special partition. There are two programs to handle this: mkswap to set up a swap-file/partition and swapon to start up swapping. mkswap needs either a partition or a file that already exists to make a swap-area. To make a swap-file, do this: # dd bs=1024 count=NN if=/dev/hda of=swapfile # mkswap swapfile NN The first command just makes a file that is NN blocks long (initializing it from /dev/hda, but that could be anything). The second command then writes the necessary setup-info into the file. To start swapping, write # swapon swapfile NOTE! 'dd' isn't on the rootdisk: you have to install some things onto the harddisk before you can get up and running. NOTE2! When linux runs totally out of virtual memory, things slow down dramatically. It tries to keep on running as long as it can, but at least it shouldn't lock up any more. ^C should work, although you might have to wait a while for it.. Faster floppies Ok, you don't notice this much when booting up from a floppy: bash has grown, so it takes longer to load, and the optimizations work mostly with sequential accesses. When you start un-taring floppies to get the programs onto your harddisk, you'll notice that it's much faster now. That should be about the only use for floppies under a unix: nobody in their right mind uses floppies as filesystems. Better FS-independence Hopefully you'll never even notice this, but the filesystem has been partly rewritten to make it less minix-fs-specific. I haven't implemented all the VFS-patches I got, so it's still not ready, but it's getting there, slowly. And that's it, I think. Happy hacking. Linus (torvalds@kruuna.helsinki.fi)
-rw-r--r--Makefile18
-rw-r--r--boot/setup.S27
-rw-r--r--fs/bitmap.c169
-rw-r--r--fs/block_dev.c10
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/file_dev.c90
-rw-r--r--fs/inode.c4
-rw-r--r--fs/minix/file_dev.c11
-rw-r--r--fs/minix/truncate.c2
-rw-r--r--fs/select.c64
-rw-r--r--fs/truncate.c99
-rw-r--r--include/asm/io.h24
-rw-r--r--include/asm/segment.h34
-rw-r--r--include/linux/config.h2
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/sched.h8
-rw-r--r--include/linux/timer.h5
-rw-r--r--include/linux/tty.h19
-rw-r--r--include/termios.h2
-rw-r--r--init/main.c1
-rw-r--r--kernel/blk_drv/blk.h24
-rw-r--r--kernel/blk_drv/floppy.c90
-rw-r--r--kernel/blk_drv/hd.c66
-rw-r--r--kernel/chr_drv/console.c252
-rw-r--r--kernel/chr_drv/keyboard.S12
-rw-r--r--kernel/chr_drv/rs_io.s55
-rw-r--r--kernel/chr_drv/serial.c62
-rw-r--r--kernel/chr_drv/tty_io.c73
-rw-r--r--kernel/chr_drv/tty_ioctl.c13
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/ptrace.c482
-rw-r--r--kernel/sched.c67
-rw-r--r--mm/Makefile2
-rw-r--r--mm/memory.c29
-rw-r--r--mm/page.s40
-rw-r--r--mm/swap.c51
36 files changed, 881 insertions, 1039 deletions
diff --git a/Makefile b/Makefile
index 8bedb81..e397dab 100644
--- a/Makefile
+++ b/Makefile
@@ -61,28 +61,28 @@ tools/system: boot/head.o init/main.o \
$(LIBS) \
-o tools/system > System.map
-kernel/math/math.a:
+kernel/math/math.a: dummy
(cd kernel/math; make)
-kernel/blk_drv/blk_drv.a:
+kernel/blk_drv/blk_drv.a: dummy
(cd kernel/blk_drv; make)
-kernel/chr_drv/chr_drv.a:
+kernel/chr_drv/chr_drv.a: dummy
(cd kernel/chr_drv; make)
-kernel/kernel.o:
+kernel/kernel.o: dummy
(cd kernel; make)
-mm/mm.o:
+mm/mm.o: dummy
(cd mm; make)
-fs/fs.o:
+fs/fs.o: dummy
(cd fs; make)
-fs/minix/minix.o:
+fs/minix/minix.o: dummy
(cd fs/minix; make)
-lib/lib.a:
+lib/lib.a: dummy
(cd lib; make)
boot/setup: boot/setup.s
@@ -120,6 +120,8 @@ dep:
(cd kernel; make dep)
(cd mm; make dep)
+dummy:
+
### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \
diff --git a/boot/setup.S b/boot/setup.S
index 1befd14..7e9d132 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -43,6 +43,12 @@ start:
int 0x15
mov [2],ax
+! set the keyboard repeat rate to the max
+
+ mov ax,#0x0305
+ mov bx,#0x0000
+ int 0x16
+
! check for EGA/VGA and some config parameters
mov ah,#0x12
@@ -498,8 +504,25 @@ nozero: sub al,#0x80
lodsw
pop ds
ret
-novid7: pop ds ! Here could be code to support standard 80x50,80x30
- mov ax,#0x5019
+novid7:
+ mov ax,#0x1112
+ mov bl,#0
+ int 0x10 ! use 8x8 font set (50 lines on VGA)
+
+ mov ax,#0x1200
+ mov bl,#0x20
+ int 0x10 ! use alternate print screen
+
+ mov ax,#0x1201
+ mov bl,#0x34
+ int 0x10 ! turn off cursor emulation
+
+ mov ah,#0x01
+ mov cx,#0x0607
+ int 0x10 ! turn on cursor (scan lines 6 to 7)
+
+ pop ds
+ mov ax,#0x5032 ! return 80x50
ret
! Routine that 'tabs' to next col.
diff --git a/fs/bitmap.c b/fs/bitmap.c
deleted file mode 100644
index ec733d0..0000000
--- a/fs/bitmap.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * linux/fs/bitmap.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-/* bitmap.c contains the code that handles the inode and block bitmaps */
-#include <string.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-#define clear_block(addr) \
-__asm__("cld\n\t" \
- "rep\n\t" \
- "stosl" \
- ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
-
-#define set_bit(nr,addr) ({\
-register int res __asm__("ax"); \
-__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
-"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
-res;})
-
-#define clear_bit(nr,addr) ({\
-register int res __asm__("ax"); \
-__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
-"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
-res;})
-
-#define find_first_zero(addr) ({ \
-int __res; \
-__asm__("cld\n" \
- "1:\tlodsl\n\t" \
- "notl %%eax\n\t" \
- "bsfl %%eax,%%edx\n\t" \
- "je 2f\n\t" \
- "addl %%edx,%%ecx\n\t" \
- "jmp 3f\n" \
- "2:\taddl $32,%%ecx\n\t" \
- "cmpl $8192,%%ecx\n\t" \
- "jl 1b\n" \
- "3:" \
- :"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \
-__res;})
-
-int free_block(int dev, int block)
-{
- struct super_block * sb;
- struct buffer_head * bh;
-
- if (!(sb = get_super(dev)))
- panic("trying to free block on nonexistent device");
- if (block < sb->s_firstdatazone || block >= sb->s_nzones)
- panic("trying to free block not in datazone");
- bh = get_hash_table(dev,block);
- if (bh) {
- if (bh->b_count > 1) {
- brelse(bh);
- return 0;
- }
- bh->b_dirt=0;
- bh->b_uptodate=0;
- if (bh->b_count)
- brelse(bh);
- }
- block -= sb->s_firstdatazone - 1 ;
- if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
- printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
- printk("free_block: bit already cleared\n");
- }
- sb->s_zmap[block/8192]->b_dirt = 1;
- return 1;
-}
-
-int new_block(int dev)
-{
- struct buffer_head * bh;
- struct super_block * sb;
- int i,j;
-
- if (!(sb = get_super(dev)))
- panic("trying to get new block from nonexistant device");
- j = 8192;
- for (i=0 ; i<8 ; i++)
- if (bh=sb->s_zmap[i])
- if ((j=find_first_zero(bh->b_data))<8192)
- break;
- if (i>=8 || !bh || j>=8192)
- return 0;
- if (set_bit(j,bh->b_data))
- panic("new_block: bit already set");
- bh->b_dirt = 1;
- j += i*8192 + sb->s_firstdatazone-1;
- if (j >= sb->s_nzones)
- return 0;
- if (!(bh=getblk(dev,j)))
- panic("new_block: cannot get block");
- if (bh->b_count != 1)
- panic("new block: count is != 1");
- clear_block(bh->b_data);
- bh->b_uptodate = 1;
- bh->b_dirt = 1;
- brelse(bh);
- return j;
-}
-
-void free_inode(struct m_inode * inode)
-{
- struct super_block * sb;
- struct buffer_head * bh;
-
- if (!inode)
- return;
- if (!inode->i_dev) {
- memset(inode,0,sizeof(*inode));
- return;
- }
- if (inode->i_count>1) {
- printk("trying to free inode with count=%d\n",inode->i_count);
- panic("free_inode");
- }
- if (inode->i_nlinks)
- panic("trying to free inode with links");
- if (!(sb = get_super(inode->i_dev)))
- panic("trying to free inode on nonexistent device");
- if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
- panic("trying to free inode 0 or nonexistant inode");
- if (!(bh=sb->s_imap[inode->i_num>>13]))
- panic("nonexistent imap in superblock");
- if (clear_bit(inode->i_num&8191,bh->b_data))
- printk("free_inode: bit already cleared.\n\r");
- bh->b_dirt = 1;
- memset(inode,0,sizeof(*inode));
-}
-
-struct m_inode * new_inode(int dev)
-{
- struct m_inode * inode;
- struct super_block * sb;
- struct buffer_head * bh;
- int i,j;
-
- if (!(inode=get_empty_inode()))
- return NULL;
- if (!(sb = get_super(dev)))
- panic("new_inode with unknown device");
- j = 8192;
- for (i=0 ; i<8 ; i++)
- if (bh=sb->s_imap[i])
- if ((j=find_first_zero(bh->b_data))<8192)
- break;
- if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {
- iput(inode);
- return NULL;
- }
- if (set_bit(j,bh->b_data))
- panic("new_inode: bit already set");
- bh->b_dirt = 1;
- inode->i_count=1;
- inode->i_nlinks=1;
- inode->i_dev=dev;
- inode->i_uid=current->euid;
- inode->i_gid=current->egid;
- inode->i_dirt=1;
- inode->i_num = j + i*8192;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- return inode;
-}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index e4a4e9e..cca44d3 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -47,8 +47,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
filp->f_pos += chars;
written += chars;
count -= chars;
- while (chars-->0)
- *(p++) = get_fs_byte(buf++);
+ memcpy_fromfs(p,buf,chars);
+ p += chars;
+ buf += chars;
bh->b_dirt = 1;
brelse(bh);
}
@@ -85,8 +86,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
filp->f_pos += chars;
read += chars;
count -= chars;
- while (chars-->0)
- put_fs_byte(*(p++),buf++);
+ memcpy_tofs(buf,p,chars);
+ p += chars;
+ buf += chars;
brelse(bh);
}
return read;
diff --git a/fs/buffer.c b/fs/buffer.c
index 2ece779..d4aaa06 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -109,10 +109,15 @@ void inline invalidate_buffers(int dev)
void check_disk_change(int dev)
{
int i;
+ struct buffer_head * bh;
if (MAJOR(dev) != 2)
return;
- if (!floppy_change(dev & 0x03))
+ if (!(bh = getblk(dev,0)))
+ return;
+ i = floppy_change(bh);
+ brelse(bh);
+ if (!i)
return;
for (i=0 ; i<NR_SUPER ; i++)
if (super_block[i].s_dev == dev)
diff --git a/fs/file_dev.c b/fs/file_dev.c
deleted file mode 100644
index 0c50eaa..0000000
--- a/fs/file_dev.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * linux/fs/file_dev.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <errno.h>
-#include <fcntl.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
-{
- int left,chars,nr;
- struct buffer_head * bh;
-
- if ((left=count)<=0)
- return 0;
- while (left) {
- if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
- if (!(bh=bread(inode->i_dev,nr)))
- break;
- } else
- bh = NULL;
- nr = filp->f_pos % BLOCK_SIZE;
- chars = MIN( BLOCK_SIZE-nr , left );
- filp->f_pos += chars;
- left -= chars;
- if (bh) {
- char * p = nr + bh->b_data;
- while (chars-->0)
- put_fs_byte(*(p++),buf++);
- brelse(bh);
- } else {
- while (chars-->0)
- put_fs_byte(0,buf++);
- }
- }
- inode->i_atime = CURRENT_TIME;
- return (count-left)?(count-left):-ERROR;
-}
-
-int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
-{
- off_t pos;
- int block,c;
- struct buffer_head * bh;
- char * p;
- int i=0;
-
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = filp->f_pos;
- while (i<count) {
- if (!(block = create_block(inode,pos/BLOCK_SIZE)))
- break;
- if (!(bh=bread(inode->i_dev,block)))
- break;
- c = pos % BLOCK_SIZE;
- p = c + bh->b_data;
- bh->b_dirt = 1;
- c = BLOCK_SIZE-c;
- if (c > count-i) c = count-i;
- pos += c;
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_dirt = 1;
- }
- i += c;
- while (c-->0)
- *(p++) = get_fs_byte(buf++);
- brelse(bh);
- }
- inode->i_mtime = CURRENT_TIME;
- if (!(filp->f_flags & O_APPEND)) {
- filp->f_pos = pos;
- inode->i_ctime = CURRENT_TIME;
- }
- return (i?i:-1);
-}
diff --git a/fs/inode.c b/fs/inode.c
index dd68b1d..7173e23 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -73,8 +73,10 @@ void invalidate_inodes(int dev)
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
if (inode->i_dev == dev) {
- if (inode->i_count)
+ if (inode->i_count) {
printk("inode in use on removed disk\n\r");
+ continue;
+ }
inode->i_dev = inode->i_dirt = 0;
}
}
diff --git a/fs/minix/file_dev.c b/fs/minix/file_dev.c
index 646ba0e..d9d1fb9 100644
--- a/fs/minix/file_dev.c
+++ b/fs/minix/file_dev.c
@@ -39,9 +39,8 @@ int minix_file_read(struct inode * inode, struct file * filp, char * buf, int co
left -= chars;
read += chars;
if (bh) {
- char * p = nr + bh->b_data;
- while (chars-->0)
- put_fs_byte(*(p++),buf++);
+ memcpy_tofs(buf,nr+bh->b_data,chars);
+ buf += chars;
brelse(bh);
} else {
while (chars-->0)
@@ -81,7 +80,6 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
}
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
- bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-written)
c = count-written;
@@ -91,8 +89,9 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
inode->i_dirt = 1;
}
written += c;
- while (c-->0)
- *(p++) = get_fs_byte(buf++);
+ memcpy_fromfs(p,buf,c);
+ buf += c;
+ bh->b_dirt = 1;
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index 4f163bd..ab72736 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -135,6 +135,8 @@ static int check_char_dev(struct inode * inode, struct file * filp)
tty->session= current->session;
tty->pgrp = current->pgrp;
}
+ if (IS_A_SERIAL(min))
+ serial_open(min-64);
}
return 0;
}
diff --git a/fs/select.c b/fs/select.c
index 053b1ab..e5d1439 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -39,11 +39,15 @@ typedef struct {
struct task_struct ** wait_address;
} wait_entry;
-typedef struct {
- int nr;
+typedef struct select_table_struct {
+ int nr, woken;
+ struct task_struct * current;
+ struct select_table_struct * next_table;
wait_entry entry[NR_OPEN*3];
} select_table;
+static select_table * sel_tables = NULL;
+
static void add_wait(struct task_struct ** wait_address, select_table * p)
{
int i;
@@ -53,32 +57,52 @@ static void add_wait(struct task_struct ** wait_address, select_table * p)
for (i = 0 ; i < p->nr ; i++)
if (p->entry[i].wait_address == wait_address)
return;
+ current->next_wait = NULL;
p->entry[p->nr].wait_address = wait_address;
- p->entry[p->nr].old_task = * wait_address;
+ p->entry[p->nr].old_task = *wait_address;
*wait_address = current;
p->nr++;
}
-static void free_wait(select_table * p)
+/*
+ * free_wait removes the current task from any wait-queues and then
+ * wakes up the queues.
+ */
+static void free_one_table(select_table * p)
{
int i;
struct task_struct ** tpp;
+ for(tpp = &LAST_TASK ; tpp > &FIRST_TASK ; --tpp)
+ if (*tpp && ((*tpp)->next_wait == p->current))
+ (*tpp)->next_wait = NULL;
+ if (!p->nr)
+ return;
for (i = 0; i < p->nr ; i++) {
- tpp = p->entry[i].wait_address;
- while (*tpp && *tpp != current) {
- (*tpp)->state = 0;
- current->state = TASK_UNINTERRUPTIBLE;
- schedule();
- }
- if (!*tpp)
- printk("free_wait: NULL");
- if (*tpp = p->entry[i].old_task)
- (**tpp).state = 0;
+ wake_up(p->entry[i].wait_address);
+ wake_up(&p->entry[i].old_task);
}
p->nr = 0;
}
+static void free_wait(select_table * p)
+{
+ select_table * tmp;
+
+ if (p->woken)
+ return;
+ p = sel_tables;
+ sel_tables = NULL;
+ while (p) {
+ wake_up(&p->current);
+ p->woken = 1;
+ tmp = p->next_table;
+ p->next_table = NULL;
+ free_one_table(p);
+ p = tmp;
+ }
+}
+
static struct tty_struct * get_tty(struct inode * inode)
{
int major, minor;
@@ -177,6 +201,10 @@ int do_select(fd_set in, fd_set out, fd_set ex,
}
repeat:
wait_table.nr = 0;
+ wait_table.woken = 0;
+ wait_table.current = current;
+ wait_table.next_table = sel_tables;
+ sel_tables = &wait_table;
*inp = *outp = *exp = 0;
count = 0;
mask = 1;
@@ -200,7 +228,9 @@ repeat:
if (!(current->signal & ~current->blocked) &&
current->timeout && !count) {
current->state = TASK_INTERRUPTIBLE;
+ sti();
schedule();
+ cli();
free_wait(&wait_table);
goto repeat;
}
@@ -276,7 +306,9 @@ int sys_select( unsigned long *buffer )
timeout *= (1000000/HZ);
put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
}
- if (!i && (current->signal & ~current->blocked))
+ if (i)
+ return i;
+ if (current->signal & ~current->blocked)
return -EINTR;
- return i;
+ return 0;
}
diff --git a/fs/truncate.c b/fs/truncate.c
deleted file mode 100644
index 32bc19d..0000000
--- a/fs/truncate.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * linux/fs/truncate.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/sched.h>
-
-#include <sys/stat.h>
-
-static int free_ind(int dev,int block)
-{
- struct buffer_head * bh;
- unsigned short * p;
- int i;
- int block_busy;
-
- if (!block)
- return 1;
- block_busy = 0;
- if (bh=bread(dev,block)) {
- p = (unsigned short *) bh->b_data;
- for (i=0;i<512;i++,p++)
- if (*p)
- if (free_block(dev,*p)) {
- *p = 0;
- bh->b_dirt = 1;
- } else
- block_busy = 1;
- brelse(bh);
- }
- if (block_busy)
- return 0;
- else
- return free_block(dev,block);
-}
-
-static int free_dind(int dev,int block)
-{
- struct buffer_head * bh;
- unsigned short * p;
- int i;
- int block_busy;
-
- if (!block)
- return 1;
- block_busy = 0;
- if (bh=bread(dev,block)) {
- p = (unsigned short *) bh->b_data;
- for (i=0;i<512;i++,p++)
- if (*p)
- if (free_ind(dev,*p)) {
- *p = 0;
- bh->b_dirt = 1;
- } else
- block_busy = 1;
- brelse(bh);
- }
- if (block_busy)
- return 0;
- else
- return free_block(dev,block);
-}
-
-void truncate(struct m_inode * inode)
-{
- int i;
- int block_busy;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-repeat:
- block_busy = 0;
- for (i=0;i<7;i++)
- if (inode->i_zone[i]) {
- if (free_block(inode->i_dev,inode->i_zone[i]))
- inode->i_zone[i]=0;
- else
- block_busy = 1;
- }
- if (free_ind(inode->i_dev,inode->i_zone[7]))
- inode->i_zone[7] = 0;
- else
- block_busy = 1;
- if (free_dind(inode->i_dev,inode->i_zone[8]))
- inode->i_zone[8] = 0;
- else
- block_busy = 1;
- inode->i_dirt = 1;
- if (block_busy) {
- current->counter = 0;
- schedule();
- goto repeat;
- }
- inode->i_size = 0;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-}
-
diff --git a/include/asm/io.h b/include/asm/io.h
index 118249a..9886d7b 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -1,27 +1,37 @@
static void inline outb(char value, unsigned short port)
{
-__asm__ volatile ("outb %0,%1"::"a" (value),"d" (port));
+__asm__ volatile ("outb %0,%1"
+ ::"a" ((char) value),"d" ((unsigned short) port));
}
static void inline outb_p(char value, unsigned short port)
{
-__asm__ volatile ("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"
- ::"a" (value),"d" (port));
+__asm__ volatile ("outb %0,%1\n"
+ "\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:"
+ ::"a" ((char) value),"d" ((unsigned short) port));
}
static unsigned char inline inb(unsigned short port)
{
unsigned char _v;
- __asm__ volatile ("inb %1,%0":"=a" (_v):"d" (port));
+__asm__ volatile ("inb %1,%0"
+ :"=a" (_v):"d" ((unsigned short) port));
return _v;
}
static unsigned char inb_p(unsigned short port)
{
unsigned char _v;
- __asm__ volatile ("inb %1,%0\n"
- "\tjmp 1f\n"
+__asm__ volatile ("inb %1,%0\n"
+ "\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
"1:\tjmp 1f\n"
- "1:":"=a" (_v):"d" ((unsigned short) port));
+ "1:"
+ :"=a" (_v):"d" ((unsigned short) port));
return _v;
}
diff --git a/include/asm/segment.h b/include/asm/segment.h
index 5efc9e7..cf2890c 100644
--- a/include/asm/segment.h
+++ b/include/asm/segment.h
@@ -37,6 +37,40 @@ extern inline void put_fs_long(unsigned long val,unsigned long * addr)
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
}
+extern inline void memcpy_tofs(void * to, void * from, unsigned long n)
+{
+__asm__("cld\n\t"
+ "push %%es\n\t"
+ "push %%fs\n\t"
+ "pop %%es\n\t"
+ "testb $1,%%cl\n\t"
+ "je 1f\n\t"
+ "movsb\n"
+ "1:\ttestb $2,%%cl\n\t"
+ "je 2f\n\t"
+ "movsw\n"
+ "2:\tshrl $2,%%ecx\n\t"
+ "rep ; movsl\n\t"
+ "pop %%es"
+ ::"c" (n),"D" ((long) to),"S" ((long) from)
+ :"cx","di","si");
+}
+
+extern inline void memcpy_fromfs(void * to, void * from, unsigned long n)
+{
+__asm__("cld\n\t"
+ "testb $1,%%cl\n\t"
+ "je 1f\n\t"
+ "fs ; movsb\n"
+ "1:\ttestb $2,%%cl\n\t"
+ "je 2f\n\t"
+ "fs ; movsw\n"
+ "2:\tshrl $2,%%ecx\n\t"
+ "rep ; fs ; movsl"
+ ::"c" (n),"D" ((long) to),"S" ((long) from)
+ :"cx","di","si");
+}
+
/*
* Someone who knows GNU asm better than I should double check the followig.
* It seems to work, but I don't know if I'm doing something subtly wrong.
diff --git a/include/linux/config.h b/include/linux/config.h
index ca364b6..fc2ce17 100644
--- a/include/linux/config.h
+++ b/include/linux/config.h
@@ -16,7 +16,7 @@
#define UTS_SYSNAME "Linux"
#define UTS_NODENAME "(none)" /* set by sethostname() */
#define UTS_RELEASE "0" /* patchlevel */
-#define UTS_VERSION "0.12"
+#define UTS_VERSION "0.95a"
#define UTS_MACHINE "i386" /* hardware type */
/* Don't touch these, unless you really know what your doing. */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0c7b2e9..8851646 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -165,7 +165,7 @@ extern struct buffer_head * start_buffer;
extern int nr_buffers;
extern void check_disk_change(int dev);
-extern int floppy_change(unsigned int nr);
+extern int floppy_change(struct buffer_head * first_block);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d903e2d..99f919b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -120,7 +120,11 @@ struct task_struct {
* older sibling, respectively. (p->father can be replaced with
* p->p_pptr->pid)
*/
- struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ /*
+ * sleep makes a singly linked list with this.
+ */
+ struct task_struct *next_wait;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
unsigned long timeout,alarm;
@@ -164,7 +168,7 @@ struct task_struct {
/* ec,brk... */ 0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \
-/* proc links*/ &init_task.task,0,0,0, \
+/* proc links*/ &init_task.task,NULL,NULL,NULL,NULL, \
/* uid etc */ 0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0, \
/* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 295738e..ab3c74e 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -24,11 +24,16 @@
#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 HD_TIMER 16
#define FLOPPY_TIMER 17
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4812f85..805894d 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -10,14 +10,14 @@
#define _TTY_H
#define MAX_CONSOLES 8
-#define NR_SERIALS 2
+#define NR_SERIALS 4
#define NR_PTYS 4
extern int NR_CONSOLES;
#include <termios.h>
-#define TTY_BUF_SIZE 1024
+#define TTY_BUF_SIZE 2048
struct tty_queue {
unsigned long data;
@@ -60,6 +60,7 @@ struct tty_struct {
int pgrp;
int session;
int stopped;
+ int busy;
struct winsize winsize;
void (*write)(struct tty_struct * tty);
struct tty_queue *read_q;
@@ -67,6 +68,18 @@ struct tty_struct {
struct tty_queue *secondary;
};
+#define TTY_WRITE(tty) \
+do { \
+ cli(); \
+ if (!(tty)->busy) { \
+ (tty)->busy = 1; \
+ sti(); \
+ (tty)->write((tty)); \
+ (tty)->busy = 0; \
+ } else \
+ sti(); \
+} while (0)
+
extern struct tty_struct tty_table[];
extern int fg_console;
extern unsigned long video_num_columns;
@@ -96,6 +109,8 @@ void rs_write(struct tty_struct * tty);
void mpty_write(struct tty_struct * tty);
void spty_write(struct tty_struct * tty);
+extern void serial_open(unsigned int line);
+
void copy_to_cooked(struct tty_struct * tty);
void update_screen(int new_console);
diff --git a/include/termios.h b/include/termios.h
index faa6e53..b04a0e9 100644
--- a/include/termios.h
+++ b/include/termios.h
@@ -3,8 +3,6 @@
#include <sys/types.h>
-#define TTY_BUF_SIZE 1024
-
/* 0x54 is just a magic number to make these relatively uniqe ('T') */
#define TCGETS 0x5401
diff --git a/init/main.c b/init/main.c
index 1739de5..d53e00f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -203,6 +203,7 @@ void init(void)
NR_BUFFERS*BLOCK_SIZE);
printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
+ execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init);
/* if this fails, fall through to original stuff */
diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h
index 28e37d5..c159025 100644
--- a/kernel/blk_drv/blk.h
+++ b/kernel/blk_drv/blk.h
@@ -100,11 +100,16 @@ extern int * blk_size[NR_BLK_DEV];
void (*DEVICE_INTR)(void) = NULL;
#endif
#ifdef DEVICE_TIMEOUT
-#define SET_INTR(x) (DEVICE_INTR = (x), \
- timer_table[DEVICE_TIMEOUT].expires = jiffies + 200, \
- timer_active |= 1<<DEVICE_TIMEOUT)
+
+#define SET_INTR(x) if (DEVICE_INTR = (x)) { \
+timer_table[DEVICE_TIMEOUT].expires = jiffies + 200; \
+timer_active |= 1<<DEVICE_TIMEOUT; \
+} else timer_active &= ~(1<<DEVICE_TIMEOUT)
+
#else
+
#define SET_INTR(x) (DEVICE_INTR = (x))
+
#endif
static void (DEVICE_REQUEST)(void);
@@ -134,23 +139,16 @@ extern inline void end_request(int uptodate)
CURRENT = CURRENT->next;
}
-#ifdef DEVICE_TIMEOUT
-#define CLEAR_DEVICE_TIMEOUT timer_active &= ~(1<<DEVICE_TIMEOUT);
-#else
-#define CLEAR_DEVICE_TIMEOUT
-#endif
-
#ifdef DEVICE_INTR
-#define CLEAR_DEVICE_INTR DEVICE_INTR = 0;
+#define CLEAR_INTR SET_INTR(NULL)
#else
-#define CLEAR_DEVICE_INTR
+#define CLEAR_INTR
#endif
#define INIT_REQUEST \
repeat: \
if (!CURRENT) {\
- CLEAR_DEVICE_INTR \
- CLEAR_DEVICE_TIMEOUT \
+ CLEAR_INTR; \
return; \
} \
if (MAJOR(CURRENT->dev) != MAJOR_NR) \
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index 92881e5..a97bff6 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -43,6 +43,8 @@
#define MAJOR_NR 2
#include "blk.h"
+unsigned int changed_floppies = 0;
+
static int recalibrate = 0;
static int reset = 0;
static int seek = 0;
@@ -56,8 +58,8 @@ __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
#define DRIVE(x) ((x)&0x03)
/*
* Note that MAX_ERRORS=X doesn't imply that we retry every bad read
- * max X times - some types of errors increase the errorcount by 2,
- * so we might actually retry only X/2 times before giving up.
+ * max X times - some types of errors increase the errorcount by 2 or
+ * even 3, so we might actually retry only X/2 times before giving up.
*/
#define MAX_ERRORS 12
@@ -115,18 +117,20 @@ extern char floppy_track_buffer[512*2*18];
* information to interrupts. They are the data used for the current
* request.
*/
+#define NO_TRACK 255
+
static int read_track = 0; /* flag to indicate if we want to read all track */
static int buffer_track = -1;
static int buffer_drive = -1;
static int cur_spec1 = -1;
static int cur_rate = -1;
static struct floppy_struct * floppy = floppy_type;
-static unsigned char current_drive = 0;
+static unsigned char current_drive = 255;
static unsigned char sector = 0;
static unsigned char head = 0;
static unsigned char track = 0;
static unsigned char seek_track = 0;
-static unsigned char current_track = 255;
+static unsigned char current_track = NO_TRACK;
static unsigned char command = 0;
unsigned char selected = 0;
struct task_struct * wait_on_floppy_select = NULL;
@@ -145,20 +149,37 @@ void floppy_deselect(unsigned int nr)
* to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop.
*/
-int floppy_change(unsigned int nr)
+int floppy_change(struct buffer_head * bh)
{
-repeat:
- floppy_on(nr);
- while ((current_DOR & 3) != nr && selected)
- sleep_on(&wait_on_floppy_select);
- if ((current_DOR & 3) != nr)
- goto repeat;
- if (inb(FD_DIR) & 0x80) {
- floppy_off(nr);
- buffer_track = -1;
+ unsigned int mask = 1 << (bh->b_dev & 0x03);
+
+ if (MAJOR(bh->b_dev) != 2) {
+ printk("floppy_changed: not a floppy\n");
+ return 0;
+ }
+ if (changed_floppies & mask) {
+ changed_floppies &= ~mask;
+ recalibrate = 1;
return 1;
}
- floppy_off(nr);
+ if (!bh)
+ return 0;
+ if (bh->b_dirt)
+ ll_rw_block(WRITE,bh);
+ else {
+ buffer_track = -1;
+ bh->b_uptodate = 0;
+ ll_rw_block(READ,bh);
+ }
+ cli();
+ while (bh->b_lock)
+ sleep_on(&bh->b_wait);
+ sti();
+ if (changed_floppies & mask) {
+ changed_floppies &= ~mask;
+ recalibrate = 1;
+ return 1;
+ }
return 0;
}
@@ -223,6 +244,7 @@ static void output_byte(char byte)
return;
}
}
+ current_track = NO_TRACK;
reset = 1;
printk("Unable to send byte to FDC\n\r");
}
@@ -244,13 +266,14 @@ static int result(void)
}
}
reset = 1;
+ current_track = NO_TRACK;
printk("Getstatus times out\n\r");
return -1;
}
static void bad_flp_intr(void)
{
- current_track = -1;
+ current_track = NO_TRACK;
CURRENT->errors++;
if (CURRENT->errors > MAX_ERRORS) {
floppy_deselect(current_drive);
@@ -258,6 +281,8 @@ static void bad_flp_intr(void)
}
if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
+ else
+ recalibrate = 1;
}
/*
@@ -383,15 +408,15 @@ static void transfer(void)
static void recal_interrupt(void)
{
output_byte(FD_SENSEI);
+ current_track = NO_TRACK;
if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1;
- else
- recalibrate = 0;
do_fd_request();
}
void unexpected_floppy_interrupt(void)
{
+ current_track = NO_TRACK;
output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1;
@@ -427,15 +452,16 @@ static void reset_floppy(void)
{
int i;
+ do_floppy = reset_interrupt;
reset = 0;
+ current_track = NO_TRACK;
cur_spec1 = -1;
cur_rate = -1;
recalibrate = 1;
printk("Reset-floppy called\n\r");
cli();
- do_floppy = reset_interrupt;
outb_p(current_DOR & ~0x04,FD_DOR);
- for (i=0 ; i<100 ; i++)
+ for (i=0 ; i<1000 ; i++)
__asm__("nop");
outb(current_DOR,FD_DOR);
sti();
@@ -443,6 +469,18 @@ static void reset_floppy(void)
static void floppy_on_interrupt(void)
{
+ if (inb(FD_DIR) & 0x80) {
+ changed_floppies |= 1<<current_drive;
+ buffer_track = -1;
+ }
+ if (reset) {
+ reset_floppy();
+ return;
+ }
+ if (recalibrate) {
+ recalibrate_floppy();
+ return;
+ }
/* We cannot do a floppy-select, as that might sleep. We just force it */
selected = 1;
if (current_drive != (current_DOR & 3)) {
@@ -459,19 +497,11 @@ void do_fd_request(void)
unsigned int block;
char * buffer_area;
- seek = 0;
- if (reset) {
- reset_floppy();
- return;
- }
- if (recalibrate) {
- recalibrate_floppy();
- return;
- }
INIT_REQUEST;
+ seek = 0;
floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
if (current_drive != CURRENT_DEV)
- seek = 1;
+ current_track = NO_TRACK;
current_drive = CURRENT_DEV;
block = CURRENT->sector;
if (block+2 > floppy->size) {
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index b75b176..e3a6ca5 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -11,6 +11,9 @@
* sleep. Special care is recommended.
*
* modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *
+ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ * in the early extended-partition checks and added DM partitions
*/
#include <linux/config.h>
@@ -26,10 +29,11 @@
#define MAJOR_NR 3
#include "blk.h"
-#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
-inb_p(0x71); \
-})
+static inline unsigned char CMOS_READ(unsigned char addr)
+{
+ outb_p(0x80|addr,0x70);
+ return inb_p(0x71);
+}
/* Max read/write errors/sector */
#define MAX_ERRORS 7
@@ -39,7 +43,7 @@ static void recal_intr(void);
static void bad_rw_intr(void);
static int recalibrate = 0;
-static int reset = 0;
+static int reset = 1;
/*
* This struct defines the HD's and their types.
@@ -87,12 +91,30 @@ static void check_partition(unsigned int dev)
if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
p = 0x1BE + (void *)bh->b_data;
for (i=0 ; i<4 ; i++,p++) {
+ if (!(hd[i+minor].nr_sects = p->nr_sects))
+ continue;
hd[i+minor].start_sect = p->start_sect;
- hd[i+minor].nr_sects = p->nr_sects;
+ if ((current_minor & 0x3f) >= 60)
+ continue;
+ if (p->sys_ind == EXTENDED_PARTITION) {
+ current_minor += 4;
+ check_partition(0x0300 | (i+minor));
+ }
}
- if (p->nr_sects && p->sys_ind == EXTENDED_PARTITION) {
- current_minor += 4;
- check_partition(i+minor);
+ /*
+ * check for Disk Manager partition table
+ */
+ if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
+ p = 0x1BE + (void *)bh->b_data;
+ for (i=4; i<16; i++) {
+ p--;
+ if ((current_minor & 0x3f) >= 60)
+ break;
+ if (!(hd[current_minor+4].start_sect = p->start_sect))
+ continue;
+ hd[current_minor+4].nr_sects = p->nr_sects;
+ current_minor++;
+ }
}
} else
printk("Bad partition table on dev %04x\n",dev);
@@ -196,7 +218,8 @@ static int win_result(void)
if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
== (READY_STAT | SEEK_STAT))
return(0); /* ok */
- if (i&1) i=inb(HD_ERROR);
+ if (i&1)
+ i=inb(HD_ERROR);
return (1);
}
@@ -289,11 +312,15 @@ static void bad_rw_intr(void)
end_request(0);
if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
+ else
+ recalibrate = 1;
}
static void read_intr(void)
{
+ SET_INTR(&read_intr);
if (win_result()) {
+ SET_INTR(NULL);
bad_rw_intr();
do_hd_request();
return;
@@ -302,10 +329,9 @@ static void read_intr(void)
CURRENT->errors = 0;
CURRENT->buffer += 512;
CURRENT->sector++;
- if (--CURRENT->nr_sectors) {
- SET_INTR(&read_intr);
+ if (--CURRENT->nr_sectors)
return;
- }
+ SET_INTR(NULL);
end_request(1);
do_hd_request();
}
@@ -336,14 +362,14 @@ static void recal_intr(void)
}
static void hd_times_out(void)
-{
+{
+ do_hd = NULL;
+ reset = 1;
if (!CURRENT)
return;
printk("HD timeout");
if (++CURRENT->errors >= MAX_ERRORS)
end_request(0);
- SET_INTR(NULL);
- reset = 1;
do_hd_request();
}
@@ -357,7 +383,8 @@ void do_hd_request(void)
INIT_REQUEST;
dev = MINOR(CURRENT->dev);
block = CURRENT->sector;
- if (dev >= (NR_HD<<6) || block+2 > hd[dev].nr_sects) {
+ nsect = CURRENT->nr_sectors;
+ if (dev >= (NR_HD<<6) || block+nsect > hd[dev].nr_sects) {
end_request(0);
goto repeat;
}
@@ -368,7 +395,6 @@ void do_hd_request(void)
head = block % hd_info[dev].head;
cyl = block / hd_info[dev].head;
sec++;
- nsect = CURRENT->nr_sectors;
if (reset) {
recalibrate = 1;
reset_hd();
@@ -376,7 +402,7 @@ void do_hd_request(void)
}
if (recalibrate) {
recalibrate = 0;
- hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
+ hd_out(dev,hd_info[dev].sect,0,0,0,
WIN_RESTORE,&recal_intr);
if (reset)
goto repeat;
@@ -404,7 +430,7 @@ void do_hd_request(void)
void hd_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- set_trap_gate(0x2E,&hd_interrupt);
+ set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
timer_table[HD_TIMER].fn = hd_times_out;
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index 3de8648..f506c4c 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -187,7 +187,7 @@ static char * translations[] = {
#define GRAF_TRANS (translations[1])
/* NOTE! gotoxy thinks x==video_num_columns is ok */
-static inline void gotoxy(int currcons, int new_x,unsigned int new_y)
+static inline void gotoxy(int currcons, unsigned int new_x,unsigned int new_y)
{
if (new_x > video_num_columns || new_y >= video_num_lines)
return;
@@ -210,75 +210,46 @@ static inline void set_origin(int currcons)
sti();
}
-static void scrup(int currcons)
+static void scrup(int currcons, unsigned int t, unsigned int b)
{
- unsigned int oldbottom, oldtop;
-
- oldbottom = bottom;
- oldtop = top;
- if (y < top) {
- top = 0;
- bottom = y + 1;
- } else if (y > bottom) {
- bottom = video_num_lines;
- top = y;
- }
- if (top > video_num_lines)
- top = 0;
- if (bottom > video_num_lines)
- bottom = video_num_lines;
- if (bottom <= top) {
- bottom = oldbottom;
- top = oldtop;
+ int hardscroll = 1;
+
+ if (b > video_num_lines || t >= b)
return;
- }
- if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
- {
- if (!top && bottom == video_num_lines) {
- origin += video_size_row;
- pos += video_size_row;
- scr_end += video_size_row;
- if (scr_end > video_mem_end) {
- __asm__("cld\n\t"
- "rep\n\t"
- "movsl\n\t"
- "movl _video_num_columns,%1\n\t"
- "rep\n\t"
- "stosw"
- ::"a" (video_erase_char),
- "c" ((video_num_lines-1)*video_num_columns>>1),
- "D" (video_mem_start),
- "S" (origin)
- :"cx","di","si");
- scr_end -= origin-video_mem_start;
- pos -= origin-video_mem_start;
- origin = video_mem_start;
- } else {
- __asm__("cld\n\t"
- "rep\n\t"
- "stosw"
- ::"a" (video_erase_char),
- "c" (video_num_columns),
- "D" (scr_end-video_size_row)
- :"cx","di");
- }
- set_origin(currcons);
- } else {
+ if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
+ hardscroll = 0;
+ else if (t || b != video_num_lines)
+ hardscroll = 0;
+ if (hardscroll) {
+ origin += video_size_row;
+ pos += video_size_row;
+ scr_end += video_size_row;
+ if (scr_end > video_mem_end) {
__asm__("cld\n\t"
"rep\n\t"
"movsl\n\t"
- "movl _video_num_columns,%%ecx\n\t"
+ "movl _video_num_columns,%1\n\t"
"rep\n\t"
"stosw"
::"a" (video_erase_char),
- "c" ((bottom-top-1)*video_num_columns>>1),
- "D" (origin+video_size_row*top),
- "S" (origin+video_size_row*(top+1))
+ "c" ((video_num_lines-1)*video_num_columns>>1),
+ "D" (video_mem_start),
+ "S" (origin)
:"cx","di","si");
+ scr_end -= origin-video_mem_start;
+ pos -= origin-video_mem_start;
+ origin = video_mem_start;
+ } else {
+ __asm__("cld\n\t"
+ "rep\n\t"
+ "stosw"
+ ::"a" (video_erase_char),
+ "c" (video_num_columns),
+ "D" (scr_end-video_size_row)
+ :"cx","di");
}
- }
- else /* Not EGA/VGA */
- {
+ set_origin(currcons);
+ } else {
__asm__("cld\n\t"
"rep\n\t"
"movsl\n\t"
@@ -286,37 +257,17 @@ static void scrup(int currcons)
"rep\n\t"
"stosw"
::"a" (video_erase_char),
- "c" ((bottom-top-1)*video_num_columns>>1),
- "D" (origin+video_size_row*top),
- "S" (origin+video_size_row*(top+1))
+ "c" ((b-t-1)*video_num_columns>>1),
+ "D" (origin+video_size_row*t),
+ "S" (origin+video_size_row*(t+1))
:"cx","di","si");
}
- bottom = oldbottom;
- top = oldtop;
}
-static void scrdown(int currcons)
+static void scrdown(int currcons, unsigned int t, unsigned int b)
{
- unsigned int oldbottom, oldtop;
-
- oldbottom = bottom;
- oldtop = top;
- if (y < top) {
- top = 0;
- bottom = y + 1;
- } else if (y > bottom) {
- bottom = video_num_lines;
- top = y;
- }
- if (top > video_num_lines)
- top = 0;
- if (bottom > video_num_lines)
- bottom = video_num_lines;
- if (bottom<=top) {
- bottom = oldbottom;
- top = oldtop;
+ if (b > video_num_lines || t >= b)
return;
- }
__asm__("std\n\t"
"rep\n\t"
"movsl\n\t"
@@ -326,12 +277,10 @@ static void scrdown(int currcons)
"stosw\n\t"
"cld"
::"a" (video_erase_char),
- "c" ((bottom-top-1)*video_num_columns>>1),
- "D" (origin+video_size_row*bottom-4),
- "S" (origin+video_size_row*(bottom-1)-4)
+ "c" ((b-t-1)*video_num_columns>>1),
+ "D" (origin+video_size_row*b-4),
+ "S" (origin+video_size_row*(b-1)-4)
:"ax","cx","di","si");
- bottom = oldbottom;
- top = oldtop;
}
static void lf(int currcons)
@@ -341,7 +290,7 @@ static void lf(int currcons)
pos += video_size_row;
return;
} else
- scrup(currcons);
+ scrup(currcons,top,bottom);
}
static void ri(int currcons)
@@ -351,7 +300,7 @@ static void ri(int currcons)
pos -= video_size_row;
return;
} else
- scrdown(currcons);
+ scrdown(currcons,top,bottom);
}
static void cr(int currcons)
@@ -371,8 +320,8 @@ static void del(int currcons)
static void csi_J(int currcons, int vpar)
{
- long count;
- long start;
+ unsigned long count;
+ unsigned long start;
switch (vpar) {
case 0: /* erase from cursor to end of display */
@@ -429,7 +378,7 @@ static void csi_K(int currcons, int vpar)
:"cx","di");
}
-void csi_m(int currcons )
+static void csi_m(int currcons )
{
int i;
static int conv_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
@@ -455,22 +404,23 @@ void csi_m(int currcons )
}
break;
case 5: attr=attr|0x80;break; /* blinking */
- case 7: attr=(attr<<4)|(attr>>4);break; /* negative */
+ case 7: attr=(attr&0x88)|((attr<<4)&0x70)|
+ ((attr>>4)&0x07);break; /* negative */
case 22: attr=attr&0xf7;break; /* not bold */
case 24: attr=attr&0xfe;break; /* not underline */
case 25: attr=attr&0x7f;break; /* not blinking */
case 27: attr=def_attr;break; /* positive image */
- case 39: attr=(attr & 0xf0)|(def_attr & 0x0f); break;
- case 49: attr=(attr & 0x0f)|(def_attr & 0xf0); break;
+ case 39: attr=(attr & 0xf8)|(def_attr & 0x07); break;
+ case 49: attr=(attr & 0x8f)|(def_attr & 0x70); break;
default:
if (!can_do_colour)
break;
iscolor = 1;
if ((par[i]>=30) && (par[i]<=37))
- attr = (attr & 0xf0) | conv_table[par[i]-30];
+ attr = (attr & 0xf8) | conv_table[par[i]-30];
else /* Background color */
if ((par[i]>=40) && (par[i]<=47))
- attr = (attr & 0x0f) | (conv_table[par[i]-40]<<4);
+ attr = (attr & 0x8f) | (conv_table[par[i]-40]<<4);
else
break;
}
@@ -511,39 +461,30 @@ static void respond(int currcons, struct tty_struct * tty)
static void insert_char(int currcons)
{
- int i=x;
+ unsigned int i = x;
unsigned short tmp, old = video_erase_char;
unsigned short * p = (unsigned short *) pos;
- while (i++<video_num_columns) {
- tmp=*p;
- *p=old;
- old=tmp;
+ while (i++ < video_num_columns) {
+ tmp = *p;
+ *p = old;
+ old = tmp;
p++;
}
}
static void insert_line(int currcons)
{
- int oldtop,oldbottom;
-
- oldtop=top;
- oldbottom=bottom;
- top=y;
- bottom = video_num_lines;
- scrdown(currcons);
- top=oldtop;
- bottom=oldbottom;
+ scrdown(currcons,y,bottom);
}
static void delete_char(int currcons)
{
- int i;
+ unsigned int i = x;
unsigned short * p = (unsigned short *) pos;
- if (x>=video_num_columns)
+ if (x >= video_num_columns)
return;
- i = x;
while (++i < video_num_columns) {
*p = *(p+1);
p++;
@@ -553,15 +494,7 @@ static void delete_char(int currcons)
static void delete_line(int currcons)
{
- int oldtop,oldbottom;
-
- oldtop=top;
- oldbottom=bottom;
- top=y;
- bottom = video_num_lines;
- scrup(currcons);
- top=oldtop;
- bottom=oldbottom;
+ scrup(currcons,y,bottom);
}
static void csi_at(int currcons, unsigned int nr)
@@ -606,13 +539,13 @@ static void csi_M(int currcons, unsigned int nr)
static void save_cur(int currcons)
{
- saved_x=x;
- saved_y=y;
+ saved_x = x;
+ saved_y = y;
}
static void restore_cur(int currcons)
{
- gotoxy(currcons,saved_x, saved_y);
+ gotoxy(currcons, saved_x, saved_y);
}
@@ -621,18 +554,16 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
void con_write(struct tty_struct * tty)
{
- int nr;
- char c;
- int currcons;
+ unsigned char c;
+ unsigned int currcons;
wake_up(&tty->write_q->proc_list);
currcons = tty - tty_table;
- if ((currcons>=MAX_CONSOLES) || (currcons<0)) {
+ if (currcons >= MAX_CONSOLES) {
printk("con_write: illegal tty\n\r");
return;
}
- nr = CHARS(tty->write_q);
- while (nr--) {
+ while (!EMPTY(tty->write_q)) {
if (tty->stopped)
break;
GETCH(tty->write_q,c);
@@ -640,41 +571,40 @@ void con_write(struct tty_struct * tty)
state = ESnormal;
switch(state) {
case ESnormal:
- if (c>31 && c<127) {
- if (x>=video_num_columns) {
+ if (c > 31 && c < 127) {
+ while (x >= video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf(currcons);
}
*(char *) pos = translate[c-32];
- pos++;
- *(char *) pos = attr;
- pos++;
+ *(char *) (pos+1) = attr;
+ pos += 2;
x++;
- } else if (c==27)
+ } else if (c == 27)
state = ESesc;
- else if (c==10 || c==11 || c==12)
+ else if (c == 10 || c == 11 || c == 12)
lf(currcons);
- else if (c==13)
+ else if (c == 13)
cr(currcons);
- else if (c==127)
+ else if (c == 127)
del(currcons);
- else if (c==8) {
+ else if (c == 8) {
if (x) {
x--;
pos -= 2;
}
- } else if (c==9) {
+ } else if (c == 9) {
c = 8-(x&7);
x += c;
pos += c<<1;
- if (x>video_num_columns) {
+ if (x > video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf(currcons);
}
- c=9;
- } else if (c==7)
+ c = 9;
+ } else if (c == 7)
sysbeep();
else if (c == 14) {
checkin = 1;
@@ -740,7 +670,7 @@ void con_write(struct tty_struct * tty)
break;
case ESsquare:
for(npar = 0 ; npar < NPAR ; npar++)
- par[npar]=0;
+ par[npar] = 0;
npar = 0;
state = ESgetpars;
if (c == '[') { /* Function key */
@@ -754,7 +684,8 @@ void con_write(struct tty_struct * tty)
npar++;
break;
} else if (c>='0' && c<='9') {
- par[npar]=10*par[npar]+c-'0';
+ par[npar] *= 10;
+ par[npar] += c-'0';
break;
} else state=ESgotpars;
case ESgotpars:
@@ -823,8 +754,10 @@ void con_write(struct tty_struct * tty)
csi_m(currcons);
break;
case 'r':
- if (par[0]) par[0]--;
- if (!par[1]) par[1] = video_num_lines;
+ if (par[0])
+ par[0]--;
+ if (!par[1])
+ par[1] = video_num_lines;
if (par[0] < par[1] &&
par[1] <= video_num_lines) {
top=par[0];
@@ -839,7 +772,7 @@ void con_write(struct tty_struct * tty)
break;
case 'l': /* blank interval */
case 'b': /* bold attribute */
- if (!((npar >= 2) &&
+ if (!((npar >= 2) &&
((par[1]-13) == par[0]) &&
((par[2]-17) == par[0])))
break;
@@ -1072,9 +1005,7 @@ static void get_scrmem(int currcons)
video_mem_start = (unsigned long)vc_scrbuf[fg_console];
origin = video_mem_start;
scr_end = video_mem_end = video_mem_start+screen_size;
- top = 0;
pos = origin + y*video_size_row + (x<<1);
- bottom = video_num_lines;
}
static void set_scrmem(int currcons)
@@ -1083,8 +1014,6 @@ static void set_scrmem(int currcons)
video_mem_end = video_mem_term;
origin = video_mem_start;
scr_end = video_mem_start + screen_size;
- top = 0;
- bottom = video_num_lines;
pos = origin + y*video_size_row + (x<<1);
memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
}
@@ -1185,15 +1114,14 @@ void console_print(const char * b)
cr(currcons);
continue;
}
- if (x>=video_num_columns) {
+ while (x >= video_num_columns) {
x -= video_num_columns;
pos -= video_size_row;
lf(currcons);
}
*(char *) pos = c;
- pos++;
- *(char *) pos = attr;
- pos++;
+ *(char *) (pos+1) = attr;
+ pos += 2;
x++;
}
set_cursor(currcons);
diff --git a/kernel/chr_drv/keyboard.S b/kernel/chr_drv/keyboard.S
index 0177e06..6a26867 100644
--- a/kernel/chr_drv/keyboard.S
+++ b/kernel/chr_drv/keyboard.S
@@ -32,7 +32,7 @@
/*
* these are for the keyboard read functions
*/
-size = 1024 /* must be a power of two ! And MUST be the same
+size = 2048 /* must be a power of two ! And MUST be the same
as in tty_io.c !!!! */
head = 4
tail = 8
@@ -434,7 +434,7 @@ key_map:
shift_map:
.byte 0,27
- .ascii "!\"#$%%&*()_+"
+ .ascii "!\"#$%^&*()_+"
.byte 127,9
.ascii "QWERTYUIOP{}"
.byte 13,0
@@ -626,7 +626,7 @@ do_self:
testb $0x20,_kmode /* alt-gr */
jne 1f
lea shift_map,%ebx
- testb $0x03,_kmode
+ testb $0x0f,_kmode
jne 1f
lea key_map,%ebx
1: movb (%ebx,%eax),%al
@@ -641,11 +641,7 @@ do_self:
subb $32,%al
2: testb $0x0c,_kmode /* ctrl */
je 3f
- cmpb $64,%al
- jb 3f
- cmpb $64+32,%al
- jae 3f
- subb $64,%al
+ andb $0x1f,%al
3: testb $0x10,_kmode /* left alt */
je 4f
orb $0x80,%al
diff --git a/kernel/chr_drv/rs_io.s b/kernel/chr_drv/rs_io.s
index f147cec..e74dcd3 100644
--- a/kernel/chr_drv/rs_io.s
+++ b/kernel/chr_drv/rs_io.s
@@ -13,7 +13,7 @@
.text
.globl _rs1_interrupt,_rs2_interrupt
-size = 1024 /* must be power of two !
+size = 2048 /* must be power of two !
and must match the value
in tty_io.c!!! */
@@ -29,16 +29,21 @@ startup = 256 /* chars left in write queue when we restart it */
/*
* These are the actual interrupt routines. They look where
* the interrupt is coming from, and take appropriate action.
+ *
+ * rs1_interrupt (IRQ 4) takes care of com1 and com3
+ * rs2_interrupt (IRQ 3) takes care of com2 and com4
*/
.align 2
_rs1_interrupt:
pushl $_table_list+8
+ pushl $_table_list+24
jmp rs_int
+
.align 2
_rs2_interrupt:
pushl $_table_list+16
-rs_int:
- cld
+ pushl $_table_list+32
+rs_int: cld
pushl %edx
pushl %ecx
pushl %ebx
@@ -50,32 +55,39 @@ rs_int:
pushl $0x10
pop %es
movl 24(%esp),%edx
+ call do_rs_intr
+ movl 28(%esp),%edx
+ call do_rs_intr
+ movb $0x20,%al
+ outb %al,$0x20 /* EOI */
+ pop %ds
+ pop %es
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ addl $8,%esp # jump over the _table_list entries
+ iret
+
+do_rs_intr:
+ pushl %edx
movl (%edx),%edx
movl rs_addr(%edx),%edx
addl $2,%edx /* interrupt ident. reg */
-rep_int:
- xorl %eax,%eax
+1: xorl %eax,%eax
inb %dx,%al
testb $1,%al
- jne end
+ jne 2f
cmpb $6,%al /* this shouldn't happen, but ... */
- ja end
- movl 24(%esp),%ecx
+ ja 2f
+ movl (%esp),%ecx
pushl %edx
subl $2,%edx
call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
popl %edx
- jmp rep_int
-end: movb $0x20,%al
- outb %al,$0x20 /* EOI */
- pop %ds
- pop %es
- popl %eax
- popl %ebx
- popl %ecx
- popl %edx
- addl $4,%esp # jump over _table_list entry
- iret
+ jmp 1b
+2: popl %edx
+ ret
jmp_table:
.long modem_status,write_char,read_char,line_status
@@ -112,7 +124,7 @@ read_char:
.align 2
mask_table:
- .long 0,4,8
+ .long 0,4,8,16,32
.align 2
write_char:
@@ -136,6 +148,7 @@ write_char:
cmpl head(%ecx),%ebx
je write_buffer_empty
ret
+
.align 2
write_buffer_empty:
movl proc_list(%ecx),%ebx # wake up sleeping process
@@ -146,6 +159,6 @@ write_buffer_empty:
inb %dx,%al
jmp 1f
1: jmp 1f
-1: andb $0xd,%al /* disable transmit interrupt */
+1: andb $0xd,%al # disable transmit interrupt
outb %al,%dx
ret
diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c
index 2334e50..741cc43 100644
--- a/kernel/chr_drv/serial.c
+++ b/kernel/chr_drv/serial.c
@@ -34,6 +34,16 @@ static void com2_timer(void)
copy_to_cooked(tty_table+65);
}
+static void com3_timer(void)
+{
+ copy_to_cooked(tty_table+66);
+}
+
+static void com4_timer(void)
+{
+ copy_to_cooked(tty_table+67);
+}
+
static inline void do_rs_write(unsigned int port)
{
char c;
@@ -66,17 +76,55 @@ static void com2_timeout(void)
do_rs_write(1);
}
+static void com3_timeout(void)
+{
+ do_rs_write(2);
+}
+
+static void com4_timeout(void)
+{
+ do_rs_write(3);
+}
+
static void init(int port)
{
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(0x0b,port+4); /* set DTR,RTS, OUT_2 */
+ outb_p(0x00,port+4); /* reset DTR,RTS, OUT_2 */
outb_p(0x0d,port+1); /* enable all intrs but writes */
(void)inb(port); /* read data port to reset things (?) */
}
+/*
+ * this routine enables interrupts on 'line', and disables them on
+ * 'line ^ 2', as they share the same IRQ. Braindamaged AT hardware.
+ */
+void serial_open(unsigned int line)
+{
+ unsigned short port;
+ unsigned short port2;
+
+ if (line>3)
+ return;
+ port = tty_table[64+line].read_q->data;
+ if (!port)
+ return;
+ port2 = tty_table[64+(line ^ 2)].read_q->data;
+ cli();
+ if (port2)
+ outb_p(0x00,port2+4);
+ outb_p(0x03,port+3); /* reset DLAB */
+ outb_p(0x0f,port+4); /* set DTR,RTS, OUT_2 */
+ outb_p(0x0d,port+1); /* enable all intrs but writes */
+ inb_p(port+5);
+ inb_p(port+0);
+ inb(port+6);
+ inb(port+2);
+ sti();
+}
+
void rs_init(void)
{
/* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
@@ -84,15 +132,25 @@ void rs_init(void)
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;
set_intr_gate(0x24,rs1_interrupt);
set_intr_gate(0x23,rs2_interrupt);
init(tty_table[64].read_q->data);
init(tty_table[65].read_q->data);
+ init(tty_table[66].read_q->data);
+ init(tty_table[67].read_q->data);
outb(inb_p(0x21)&0xE7,0x21);
}
@@ -108,6 +166,6 @@ void rs_write(struct tty_struct * tty)
cli();
if (!EMPTY(tty->write_q))
outb_p(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
- timer_active |= 3 << SER1_TIMEOUT;
+ timer_active |= 15 << SER1_TIMEOUT;
sti();
}
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 18ea261..12c6479 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -83,7 +83,9 @@ int fg_console = 0;
struct tty_queue * table_list[]={
con_queues + 0, con_queues + 1,
rs_queues + 0, rs_queues + 1,
- rs_queues + 3, rs_queues + 4
+ rs_queues + 3, rs_queues + 4,
+ rs_queues + 6, rs_queues + 7,
+ rs_queues + 9, rs_queues + 10
};
void change_console(unsigned int new_console)
@@ -122,15 +124,27 @@ void copy_to_cooked(struct tty_struct * tty)
{
unsigned char c;
- if (!(tty->read_q || tty->write_q || tty->secondary)) {
+ if (!(tty && tty->write && tty->read_q &&
+ tty->write_q && tty->secondary)) {
printk("copy_to_cooked: missing queues\n\r");
return;
}
+ cli();
+ if (tty->busy) {
+ sti();
+ return;
+ }
+ tty->busy = 1;
+ sti();
while (1) {
if (EMPTY(tty->read_q))
break;
- if (FULL(tty->secondary))
+ if (FULL(tty->secondary)) {
+ if (tty->secondary->proc_list)
+ if (tty->secondary->proc_list != current)
+ current->counter = 0;
break;
+ }
GETCH(tty->read_q,c);
if (c==13) {
if (I_CRNL(tty))
@@ -153,7 +167,6 @@ void copy_to_cooked(struct tty_struct * tty)
if (c<32)
PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q);
- tty->write(tty);
}
DEC(tty->secondary->head);
}
@@ -170,7 +183,6 @@ void copy_to_cooked(struct tty_struct * tty)
if (c<32)
PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q);
- tty->write(tty);
}
DEC(tty->secondary->head);
continue;
@@ -180,13 +192,11 @@ void copy_to_cooked(struct tty_struct * tty)
if ((STOP_CHAR(tty) != _POSIX_VDISABLE) &&
(c==STOP_CHAR(tty))) {
tty->stopped=1;
- tty->write(tty);
continue;
}
if ((START_CHAR(tty) != _POSIX_VDISABLE) &&
(c==START_CHAR(tty))) {
tty->stopped=0;
- tty->write(tty);
continue;
}
}
@@ -221,10 +231,12 @@ void copy_to_cooked(struct tty_struct * tty)
} else
PUTCH(c,tty->write_q);
}
- tty->write(tty);
PUTCH(c,tty->secondary);
}
- wake_up(&tty->secondary->proc_list);
+ tty->write(tty);
+ tty->busy = 0;
+ if (!EMPTY(tty->secondary))
+ wake_up(&tty->secondary->proc_list);
}
/*
@@ -270,7 +282,8 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
tty = TTY_TABLE(channel);
if (!(tty->read_q && tty->secondary))
return -EIO;
- if ((current->tty == channel) && (tty->pgrp != current->pgrp))
+ if ((tty->pgrp > 0) && (current->tty == channel) &&
+ (tty->pgrp != current->pgrp))
return(tty_signal(SIGTTIN, tty));
if (channel & 0x80)
other_tty = tty_table + (channel ^ 0x40);
@@ -295,15 +308,14 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
copy_to_cooked(tty);
while (nr>0) {
if (other_tty && other_tty->write)
- other_tty->write(other_tty);
+ TTY_WRITE(other_tty);
cli();
if (EMPTY(tty->secondary) || (L_CANON(tty) &&
!FULL(tty->read_q) && !tty->secondary->data)) {
- if (!current->timeout ||
- (current->signal & ~current->blocked)) {
- sti();
+ if (!current->timeout)
+ break;
+ if (current->signal & ~current->blocked)
break;
- }
if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
break;
interruptible_sleep_on(&tty->secondary->proc_list);
@@ -329,11 +341,12 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
break;
} while (nr>0 && !EMPTY(tty->secondary));
wake_up(&tty->read_q->proc_list);
- if (time)
- current->timeout = time+jiffies;
if (L_CANON(tty) || b-buf >= minimum)
break;
+ if (time)
+ current->timeout = time+jiffies;
}
+ sti();
current->timeout = 0;
if (b-buf)
return b-buf;
@@ -355,9 +368,13 @@ int tty_write(unsigned channel, char * buf, int nr)
tty = TTY_TABLE(channel);
if (!(tty->write_q && tty->write))
return -EIO;
- if (L_TOSTOP(tty) &&
+ if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
(current->tty == channel) && (tty->pgrp != current->pgrp))
return(tty_signal(SIGTTOU, tty));
+ if (nr < 0)
+ return -EINVAL;
+ if (!nr)
+ return 0;
while (nr>0) {
sleep_if_full(tty->write_q);
if (current->signal & ~current->blocked)
@@ -381,11 +398,15 @@ int tty_write(unsigned channel, char * buf, int nr)
cr_flag = 0;
PUTCH(c,tty->write_q);
}
- tty->write(tty);
+ TTY_WRITE(tty);
if (nr>0)
schedule();
}
- return (b-buf);
+ if (b-buf)
+ return b-buf;
+ if (current->signal & ~current->blocked)
+ return -ERESTARTSYS;
+ return 0;
}
void chr_dev_init(void)
@@ -402,10 +423,14 @@ void tty_init(void)
rs_queues[1] = (struct tty_queue) {0x3f8,0,0,0,""};
rs_queues[3] = (struct tty_queue) {0x2f8,0,0,0,""};
rs_queues[4] = (struct tty_queue) {0x2f8,0,0,0,""};
+ rs_queues[6] = (struct tty_queue) {0x3e8,0,0,0,""};
+ rs_queues[7] = (struct tty_queue) {0x3e8,0,0,0,""};
+ rs_queues[9] = (struct tty_queue) {0x2e8,0,0,0,""};
+ rs_queues[10] = (struct tty_queue) {0x2e8,0,0,0,""};
for (i=0 ; i<256 ; i++) {
tty_table[i] = (struct tty_struct) {
{0, 0, 0, 0, 0, INIT_C_CC},
- 0, 0, 0, {0,0,0,0},
+ -1, 0, 0, 0, {0,0,0,0},
NULL, NULL, NULL, NULL
};
}
@@ -418,9 +443,10 @@ void tty_init(void)
IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
0, /* console termio */
INIT_C_CC},
- 0, /* initial pgrp */
+ -1, /* initial pgrp */
0, /* initial session */
0, /* initial stopped */
+ 0, /* initial busy */
{video_num_lines,video_num_columns,0,0},
con_write,
con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
@@ -434,6 +460,7 @@ void tty_init(void)
0,
0,
INIT_C_CC},
+ -1,
0,
0,
0,
@@ -450,6 +477,7 @@ void tty_init(void)
0,
0,
INIT_C_CC},
+ -1,
0,
0,
0,
@@ -464,6 +492,7 @@ void tty_init(void)
IXON | ISIG | ICANON,
0,
INIT_C_CC},
+ -1,
0,
0,
0,
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index a4250d3..eabfbed 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -53,7 +53,12 @@ static void flush(struct tty_queue * queue)
static void wait_until_sent(struct tty_struct * tty)
{
- /* do nothing - not implemented */
+ cli();
+ while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
+ current->counter = 0;
+ interruptible_sleep_on(&tty->write_q->proc_list);
+ }
+ sti();
}
static void send_break(struct tty_struct * tty)
@@ -137,7 +142,7 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
}
/*
- * This only works as the 386 is low-byt-first
+ * This only works as the 386 is low-byte-first
*/
static int set_termio(struct tty_struct * tty, struct termio * termio,
int channel)
@@ -255,11 +260,11 @@ int tty_ioctl(int dev, int cmd, int arg)
switch (arg) {
case TCOOFF:
tty->stopped = 1;
- tty->write(tty);
+ TTY_WRITE(tty);
return 0;
case TCOON:
tty->stopped = 0;
- tty->write(tty);
+ TTY_WRITE(tty);
return 0;
case TCIOFF:
if (STOP_CHAR(tty))
diff --git a/kernel/exit.c b/kernel/exit.c
index e81319a..be284bd 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -359,9 +359,9 @@ volatile void do_exit(long code)
if (current->tty >= 0) {
tty = TTY_TABLE(current->tty);
- if (tty->pgrp>0)
+ if (tty->pgrp > 0)
kill_pg(tty->pgrp, SIGHUP, 1);
- tty->pgrp = 0;
+ tty->pgrp = -1;
tty->session = 0;
}
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1dab261..6722ef7 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -9,8 +9,11 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <sys/ptrace.h>
-/* does not yet catch signals sent when the child dies. in
- exit.c or in signal.c. */
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
/* determines which flags the user has access to. */
/* 1 = access 0 = no access */
@@ -22,301 +25,310 @@
/* check's for granularity. */
#define GRANULARITY 0x00800000
-/* this is the number to subtract from the top of the stack. To find
- the local frame. */
-
+/*
+ * this is the number to subtract from the top of the stack. To find
+ * the local frame.
+ */
#define MAGICNUMBER 68
-void do_no_page (unsigned long, unsigned long, struct task_struct *);
-void write_verify (unsigned long);
+void do_no_page(unsigned long, unsigned long, struct task_struct *);
+void write_verify(unsigned long);
/* change a pid into a task struct. */
static inline int get_task(int pid)
{
- int i;
- for (i =0; i < NR_TASKS; i++)
- {
- if (task[i] != NULL && (task[i]->pid == pid)) return (i);
- }
- return (-1);
+ int i;
+
+ for (i = 0; i < NR_TASKS; i++) {
+ if (task[i] != NULL && (task[i]->pid == pid))
+ return i;
+ }
+ return -1;
}
-/* this routine will get a word off of the processes priviledged stack.
- the offset is how far from the base addr as stored in the TSS.
- this routine assumes that all the priviledged stacks are in our
- data space. */
+/*
+ * this routine will get a word off of the processes priviledged stack.
+ * the offset is how far from the base addr as stored in the TSS.
+ * this routine assumes that all the priviledged stacks are in our
+ * data space.
+ */
-static inline int
-get_stack_long(struct task_struct *task, int offset)
+static inline int get_stack_long(struct task_struct *task, int offset)
{
- unsigned char *stack;
- stack = (unsigned char *)task->tss.esp0;
- stack += offset;
- return (*((int *)stack));
+ unsigned char *stack;
+ stack = (unsigned char *)task->tss.esp0;
+ stack += offset;
+ return (*((int *)stack));
}
-/* this routine will put a word on the processes priviledged stack.
- the offset is how far from the base addr as stored in the TSS.
- this routine assumes that all the priviledged stacks are in our
- data space. */
-
-static inline int
-put_stack_long(struct task_struct *task, int offset, unsigned short data)
+/*
+ * this routine will put a word on the processes priviledged stack.
+ * the offset is how far from the base addr as stored in the TSS.
+ * this routine assumes that all the priviledged stacks are in our
+ * data space.
+ */
+static inline int put_stack_long(struct task_struct *task, int offset,
+ unsigned short data)
{
- unsigned char *stack;
- stack = (unsigned char *)task->tss.esp0;
- stack += offset;
- *(int *)stack = data;
- return (0);
+ unsigned char * stack;
+ stack = (unsigned char *) task->tss.esp0;
+ stack += offset;
+ *(int *) stack = data;
+ return 0;
}
-/* this routine will get a word out of an arbitrary
- tasks data space. It likes to have the task number
- rather than the task pointer. Perhaps the number
- should be included in the pointer. */
+/*
+ * this routine will get a word out of an arbitrary
+ * tasks data space. It likes to have the task number
+ * rather than the task pointer. Perhaps the number
+ * should be included in the pointer.
+ */
/* seg = 0 if I space */
-static inline int get_long (int tsk, long addr, unsigned seg, int *data)
+static inline int get_long(int tsk, long addr, unsigned seg, int *data)
{
- int i;
- int limit;
- int cur;
- unsigned long address;
- unsigned long page;
- unsigned oldfs;
+ int i;
+ int limit;
+ int cur;
+ unsigned long address;
+ unsigned long page;
+ unsigned oldfs;
+
/* find the task number of the current task. */
- for (i = 0; i < NR_TASKS ; i ++)
- {
- if (task[i] == current) break;
- }
- if (i == NR_TASKS)
- {
- panic ("PTRACE: Can't find current task\n");
- }
- cur = i;
-
- /* we will need to check the redaability of the segment
+ for (i = 0; i < NR_TASKS ; i ++) {
+ if (task[i] == current) break;
+ }
+ if (i == NR_TASKS) {
+ printk("PTRACE: Can't find current task\n");
+ do_exit(SIGSEGV);
+ }
+ cur = i;
+
+ /* we will need to check the readability of the segment
and then the byte in order to avoid segment violations. */
- seg++;
- limit=(task[tsk]->ldt[seg].a) & 0xffff;
+ seg++;
+ limit = (task[tsk]->ldt[seg].a) & 0xffff;
/* this should be constant amound all of our segments, but we
had better check anyway. */
- if (task[tsk]->ldt[seg].b & GRANULARITY) limit = limit << 12;
+ if (task[tsk]->ldt[seg].b & GRANULARITY)
+ limit = limit << 12;
- if (limit <= addr+4) return (-EIO);
+ if (limit <= addr+4)
+ return -EIO;
/* Now compute the address, and make sure that it is present. */
- address = ((task[tsk]->ldt[seg].a & 0xffff000) >> 8) |
- ((task[tsk]->ldt[seg].b & 0xff) << 16 ) |
- (task[tsk]->ldt[seg].b & 0xff000000);
+ address = task[tsk]->start_code + addr;
- page = *((unsigned long*) ((address >> 20) & 0xffc));
+ page = *((unsigned long*) ((address >> 20) & 0xffc));
/* see if it is present. */
- if (! (page & PAGE_PRESENT))
- {
- do_no_page (0, address, task[tsk]);
- }
+ if (!(page & PAGE_PRESENT)) {
+ do_no_page(0, address, task[tsk]);
+ }
- oldfs=get_fs();
+ oldfs = get_fs();
/* now convert seg to the right format. */
- seg = seg << 3 | 0x4;
+ seg = (seg << 3) | 0x4;
- cli(); /* we are about to change our ldt, we better do it
+ cli(); /* we are about to change our ldt, we better do it
with interrupts off. Perhaps we should call schedule
first so that we won't be taking too much extra time. */
- lldt(tsk);
- set_fs(seg);
- *data = get_fs_long((void *)addr); /* we are assuming kernel space
- is in the gdt here. */
- lldt(cur);
- set_fs(oldfs);
- sti();
- return (0);
+ lldt(tsk);
+ set_fs(seg);
+ *data = get_fs_long((void *)addr); /* we are assuming kernel space
+ is in the gdt here. */
+ lldt(cur);
+ set_fs(oldfs);
+ sti();
+ return 0;
}
-/* this routine will get a word out of an arbitrary
- tasks data space. It likes to have the task number
- rather than the task pointer. Perhaps the number
- should be included in the pointer. */
+/*
+ * this routine will get a word out of an arbitrary
+ * tasks data space. It likes to have the task number
+ * rather than the task pointer. Perhaps the number
+ * should be included in the pointer.
+ */
/* seg = 0 if I space */
-static inline int put_long (int tsk, long addr, int data, unsigned seg)
+static inline int put_long(int tsk, long addr, int data, unsigned seg)
{
- int i;
- int limit;
- unsigned oldfs;
- unsigned long address;
- unsigned long page;
- int cur;
+ int i;
+ int limit;
+ unsigned oldfs;
+ unsigned long address;
+ unsigned long page;
+ int cur;
+
/* find the task number of the current task. */
- for (i = 0; i < NR_TASKS ; i ++)
- {
- if (task[i] == current) break;
- }
- if (i == NR_TASKS)
- {
- panic ("PTRACE: Can't find current task\n");
- }
- cur = i;
+ for (i = 0; i < NR_TASKS ; i++) {
+ if (task[i] == current) break;
+ }
+ if (i == NR_TASKS) {
+ printk("PTRACE: Can't find current task\n");
+ do_exit(SIGSEGV);
+ }
+ cur = i;
/* we will need to check the readability of the segment
and then the byte in order to avoid segment violations. */
- seg++;
- limit=(task[tsk]->ldt[seg].a) & 0xffff;
+ seg++;
+ limit = (task[tsk]->ldt[seg].a) & 0xffff;
/* this should be constant amound all of our segments, but we
had better check anyway. */
- if (task[tsk]->ldt[seg].b & GRANULARITY) limit = limit << 12;
+ if (task[tsk]->ldt[seg].b & GRANULARITY)
+ limit = limit << 12;
- if (limit <= addr+4) return (-EIO);
+ if (limit <= addr+4)
+ return -EIO;
/* Now compute the address, and make sure that it is present. */
- address = ((task[tsk]->ldt[seg].a & 0xffff000) >> 8) |
- ((task[tsk]->ldt[seg].b & 0xff) << 16 ) |
- (task[tsk]->ldt[seg].b & 0xff000000);
+ address = task[tsk]->start_code + addr;
- page = *((unsigned long*) ((address >> 20) & 0xffc));
+ page = *((unsigned long*) ((address >> 20) & 0xffc));
/* see if it is present. */
- if (! (page & PAGE_PRESENT))
- {
- do_no_page (0, address, task[tsk]);
- }
- write_verify (address);
+ if (!(page & PAGE_PRESENT)) {
+ do_no_page(0, address, task[tsk]);
+ }
+ write_verify(address);
- oldfs=get_fs();
+ oldfs=get_fs();
/* now convert seg to the right format. */
- seg = seg << 3 | 0x4;
+ seg = (seg << 3) | 0x4;
- cli(); /* we are about to change our ldt, we better do it
+ cli(); /* we are about to change our ldt, we better do it
with interrupts off. Perhaps we should call schedule
first so that we won't be taking too much extra time. */
- lldt(tsk);
- set_fs(seg);
- put_fs_long(data,(void *)addr);
- lldt(cur);
- set_fs(oldfs);
- sti();
- return (0);
+ lldt(tsk);
+ set_fs(seg);
+ put_fs_long(data,(void *)addr);
+ lldt(cur);
+ set_fs(oldfs);
+ sti();
+ return 0;
}
-int
-sys_ptrace( unsigned long *buffer)
/* Perform ptrace(request, pid, addr, data) syscall */
+int sys_ptrace(unsigned long *buffer)
{
- long request, pid, data;
- long addr;
- struct task_struct *child;
- int childno;
-
- request = get_fs_long(buffer++);
- pid = get_fs_long(buffer++);
- addr = get_fs_long(buffer++); /* assume long = void * */
- data = get_fs_long(buffer++);
-
- if (request == 0)
- {
- /* set the ptrace bit in the proccess flags. */
- current->flags |= PF_PTRACED;
- return (0);
- }
-
- childno=get_task(pid);
-
- if (childno < 0)
- return (-ESRCH);
- else
- child = task[childno];
-
- if (child->p_pptr != current ||
- !(child->flags & PF_PTRACED) || child->state != TASK_STOPPED)
- return (-ESRCH);
-
- switch (request)
- {
+ long request, pid, data;
+ long addr;
+ struct task_struct *child;
+ int childno;
+
+ request = get_fs_long(buffer++);
+ pid = get_fs_long(buffer++);
+ addr = get_fs_long(buffer++); /* assume long = void * */
+ data = get_fs_long(buffer++);
+
+ if (request == 0) {
+ /* set the ptrace bit in the proccess flags. */
+ current->flags |= PF_PTRACED;
+ return 0;
+ }
+
+ childno = get_task(pid);
+
+ if (childno < 0)
+ return -ESRCH;
+ else
+ child = task[childno];
+
+ if (child->p_pptr != current || !(child->flags & PF_PTRACED) ||
+ child->state != TASK_STOPPED)
+ return -ESRCH;
+
+ switch (request) {
/* when I and D space are seperate, these will need to be fixed. */
- case 1: /* read word at location addr. */
- case 2: {
- int tmp;
- int res;
- res = get_long(childno, addr, 1, &tmp);
- if (res < 0)
- return res;
- verify_area(data, 4);
- put_fs_long( tmp, (unsigned long *)data);
- return 0;
- }
-
- case 3: /* read the word at location addr in the USER area. */
- {
- int tmp;
- addr = addr >> 2; /* temporary hack. */
- if (addr < 0 || addr >= 17)
- return (-EIO);
- verify_area(data, 4);
- tmp = get_stack_long (child, 4*addr-MAGICNUMBER);
- put_fs_long(tmp,(unsigned long *)data);
- return (0);
- }
- case 4: /* write the word at location addr. */
- case 5:
+ case 1: /* read word at location addr. */
+ case 2: {
+ int tmp,res;
+
+ res = get_long(childno, addr, 1, &tmp);
+ if (res < 0)
+ return res;
+ verify_area((void *) data, 4);
+ put_fs_long(tmp,(unsigned long *) data);
+ return 0;
+ }
+
+ /* read the word at location addr in the USER area. */
+ case 3: {
+ int tmp;
+ addr = addr >> 2; /* temporary hack. */
+ if (addr < 0 || addr >= 17)
+ return -EIO;
+ verify_area((void *) data, 4);
+ tmp = get_stack_long(child, 4*addr - MAGICNUMBER);
+ put_fs_long(tmp,(unsigned long *) data);
+ return 0;
+ }
+
/* when I and D space are seperate, this will have to be fixed. */
- if (put_long(childno, addr, data, 1)) return (-EIO);
- return (0);
-
- case 6: /* write the word at location addr in the USER area */
- addr = addr >> 2; /* temproary hack. */
- if (addr < 0 || addr >= 17) return (-EIO);
- if (addr == ORIG_EAX) return (-EIO);
- if (addr == EFL) /* flags. */
- {
- data &= FLAG_MASK;
- data |= get_stack_long(child, EFL*4-MAGICNUMBER) & ~FLAG_MASK;
- }
-
- if (put_stack_long(child, 4*addr-MAGICNUMBER, data)) return (-EIO);
- return (0);
-
- case 7: /* restart after signal. */
- {
- long tmp;
- child->signal=0;
- if (data > 0 && data <= NSIG)
- child->signal = 1<<(data-1);
- child->state = 0;
+ case 4: /* write the word at location addr. */
+ case 5:
+ if (put_long(childno, addr, data, 1))
+ return -EIO;
+ return 0;
+
+ case 6: /* write the word at location addr in the USER area */
+ addr = addr >> 2; /* temproary hack. */
+ if (addr < 0 || addr >= 17)
+ return -EIO;
+ if (addr == ORIG_EAX)
+ return -EIO;
+ if (addr == EFL) { /* flags. */
+ data &= FLAG_MASK;
+ data |= get_stack_long(child, EFL*4-MAGICNUMBER) & ~FLAG_MASK;
+ }
+
+ if (put_stack_long(child, 4*addr-MAGICNUMBER, data))
+ return -EIO;
+ return 0;
+
+ case 7: { /* restart after signal. */
+ long tmp;
+
+ child->signal=0;
+ if (data > 0 && data <= NSIG)
+ child->signal = 1<<(data-1);
+ child->state = 0;
/* make sure the single step bit is not set. */
- tmp = get_stack_long (child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- return (0);
- }
-
- case 8: /* make the child exit. Best I can do is send it a sigkill.
- perhaps it should be put in the status that it want's to
- exit. */
- {
- long tmp;
- child->state = 0;
- child->signal = 1 << (SIGKILL -1 );
+ tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
+ put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+ return 0;
+ }
+
+/*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it want's to
+ * exit.
+ */
+ case 8: {
+ long tmp;
+
+ child->state = 0;
+ child->signal = 1 << (SIGKILL-1);
/* make sure the single step bit is not set. */
- tmp = get_stack_long (child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- return (0);
- }
-
- case 9: /* set the trap flag. */
- {
- long tmp;
- tmp = get_stack_long (child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
- put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- child->state = 0;
- child->signal=0;
- if (data > 0 && data <NSIG)
- child->signal= 1<<(data-1);
+ tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
+ put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+ return 0;
+ }
+
+ case 9: { /* set the trap flag. */
+ long tmp;
+
+ tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
+ put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+ child->state = 0;
+ child->signal = 0;
+ if (data > 0 && data <NSIG)
+ child->signal= 1<<(data-1);
/* give it a chance to run. */
- return (0);
- }
-
- default:
- return (-EIO);
- }
+ return 0;
+ }
+ default:
+ return -EIO;
+ }
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 335551d..2c8a845 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -126,11 +126,11 @@ void schedule(void)
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) {
- if ((*p)->timeout && (*p)->timeout < jiffies) {
- (*p)->timeout = 0;
- if ((*p)->state == TASK_INTERRUPTIBLE)
+ if ((*p)->timeout && (*p)->timeout < jiffies)
+ if ((*p)->state == TASK_INTERRUPTIBLE) {
+ (*p)->timeout = 0;
(*p)->state = TASK_RUNNING;
- }
+ }
if ((*p)->alarm && (*p)->alarm < jiffies) {
(*p)->signal |= (1<<(SIGALRM-1));
(*p)->alarm = 0;
@@ -178,29 +178,45 @@ int sys_pause(void)
return -EINTR;
}
+void wake_up(struct task_struct **p)
+{
+ struct task_struct * wakeup_ptr, * tmp;
+
+ if (p && *p) {
+ wakeup_ptr = *p;
+ *p = NULL;
+ while (wakeup_ptr && wakeup_ptr != task[0]) {
+ if (wakeup_ptr->state == TASK_STOPPED)
+ printk("wake_up: TASK_STOPPED\n");
+ else if (wakeup_ptr->state == TASK_ZOMBIE)
+ printk("wake_up: TASK_ZOMBIE\n");
+ else
+ wakeup_ptr->state = TASK_RUNNING;
+ tmp = wakeup_ptr->next_wait;
+ wakeup_ptr->next_wait = task[0];
+ wakeup_ptr = tmp;
+ }
+ }
+}
+
static inline void __sleep_on(struct task_struct **p, int state)
{
- struct task_struct *tmp;
unsigned int flags;
if (!p)
return;
- if (current == &(init_task.task))
+ if (current == task[0])
panic("task[0] trying to sleep");
__asm__("pushfl ; popl %0":"=r" (flags));
- tmp = *p;
+ current->next_wait = *p;
+ task[0]->next_wait = NULL;
*p = current;
current->state = state;
-/* make sure interrupts are enabled: there should be no more races here */
sti();
-repeat: schedule();
- if (*p && *p != current) {
- current->state = TASK_UNINTERRUPTIBLE;
- (**p).state = 0;
- goto repeat;
- }
- if (*p = tmp)
- tmp->state=0;
+ schedule();
+ if (current->next_wait != task[0])
+ wake_up(p);
+ current->next_wait = NULL;
__asm__("pushl %0 ; popfl"::"r" (flags));
}
@@ -214,17 +230,6 @@ void sleep_on(struct task_struct **p)
__sleep_on(p,TASK_UNINTERRUPTIBLE);
}
-void wake_up(struct task_struct **p)
-{
- if (p && *p) {
- if ((**p).state == TASK_STOPPED)
- printk("wake_up: TASK_STOPPED");
- if ((**p).state == TASK_ZOMBIE)
- printk("wake_up: TASK_ZOMBIE");
- (**p).state=0;
- }
-}
-
/*
* OK, here are some floppy things that shouldn't be in the kernel
* proper. They are here because the floppy needs a timer, and this
@@ -261,14 +266,6 @@ int ticks_to_floppy_on(unsigned int nr)
return mon_timer[nr];
}
-void floppy_on(unsigned int nr)
-{
- cli();
- while (ticks_to_floppy_on(nr))
- sleep_on(nr+wait_motor);
- sti();
-}
-
void floppy_off(unsigned int nr)
{
moff_timer[nr]=3*HZ;
diff --git a/mm/Makefile b/mm/Makefile
index 44c38ab..cc6e209 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -17,8 +17,6 @@ CPP =gcc -E -nostdinc -I../include
OBJS = memory.o swap.o
-all: mm.o
-
mm.o: $(OBJS)
$(LD) -r -o mm.o $(OBJS)
diff --git a/mm/memory.c b/mm/memory.c
index a77f26f..574f281 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -213,7 +213,13 @@ static unsigned long put_page(unsigned long page,unsigned long address)
*page_table = tmp | 7;
page_table = (unsigned long *) tmp;
}
- page_table[(address>>12) & 0x3ff] = page | 7;
+ page_table += (address>>12) & 0x3ff;
+ if (*page_table) {
+ printk("put_page: page already exists\n");
+ *page_table = 0;
+ invalidate();
+ }
+ *page_table = page | 7;
/* no need for invalidate */
return page;
}
@@ -243,7 +249,13 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address)
*page_table = tmp|7;
page_table = (unsigned long *) tmp;
}
- page_table[(address>>12) & 0x3ff] = page | (PAGE_DIRTY | 7);
+ page_table += (address>>12) & 0x3ff;
+ if (*page_table) {
+ printk("put_dirty_page: page already exists\n");
+ *page_table = 0;
+ invalidate();
+ }
+ *page_table = page | (PAGE_DIRTY | 7);
/* no need for invalidate */
return page;
}
@@ -296,8 +308,10 @@ repeat:
*/
void do_wp_page(unsigned long error_code,unsigned long address)
{
- if (address < TASK_SIZE)
+ if (address < TASK_SIZE) {
printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
+ do_exit(SIGSEGV);
+ }
if (address - current->start_code >= TASK_SIZE) {
printk("Bad things happen: page error in do_wp_page\n\r");
do_exit(SIGSEGV);
@@ -305,7 +319,6 @@ void do_wp_page(unsigned long error_code,unsigned long address)
un_wp_page((unsigned long *)
(((address>>10) & 0xffc) + (0xfffff000 &
*((unsigned long *) ((address>>20) &0xffc)))));
-
}
void write_verify(unsigned long address)
@@ -436,8 +449,10 @@ void do_no_page(unsigned long error_code,
if (last_checked >= CHECK_LAST_NR)
last_checked = 0;
last_pages[last_checked] = address & 0xfffff000;
- if (address < TASK_SIZE)
+ if (address < TASK_SIZE) {
printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
+ do_exit(SIGSEGV);
+ }
if (address - tsk->start_code >= TASK_SIZE) {
printk("Bad things happen: nonexistent page error in do_no_page\n\r");
do_exit(SIGSEGV);
@@ -567,12 +582,12 @@ void show_mem(void)
/* This routine handles page faults. It determines the address,
and the problem then passes it off to one of the appropriate
routines. */
-void do_page_fault (unsigned long *esp, unsigned long error_code)
+void do_page_fault(unsigned long *esp, unsigned long error_code)
{
unsigned long address;
/* get the address */
- __asm__ ("movl %%cr2,%0":"=r" (address));
+ __asm__("movl %%cr2,%0":"=r" (address));
if (!(error_code & 1)) {
do_no_page(error_code, address, current);
return;
diff --git a/mm/page.s b/mm/page.s
deleted file mode 100644
index bd1c586..0000000
--- a/mm/page.s
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * linux/mm/page.s
- *
- * (C) 1991 Linus Torvalds
- */
-
-/*
- * page.s contains the low-level page-exception code.
- * the real work is done in mm.c
- */
-
-.globl _page_fault
-
-_page_fault:
- xchgl %eax,(%esp)
- pushl %ecx
- pushl %edx
- push %ds
- push %es
- push %fs
- movl $0x10,%edx
- mov %dx,%ds
- mov %dx,%es
- mov %dx,%fs
- movl %cr2,%edx
- pushl %edx
- pushl %eax
- testl $1,%eax
- jne 1f
- call _do_no_page
- jmp 2f
-1: call _do_wp_page
-2: addl $8,%esp
- pop %fs
- pop %es
- pop %ds
- popl %edx
- popl %ecx
- popl %eax
- iret
diff --git a/mm/swap.c b/mm/swap.c
index 4c621d0..5c7e883 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -155,37 +155,38 @@ int swap_out(void)
static int dir_entry = 1024;
static int page_entry = -1;
int counter = VM_PAGES;
- int pg_table = 0;
+ int pg_table;
-repeat:
- while (counter > 0) {
+check_dir:
+ if (counter < 0)
+ goto no_swap;
+ if (dir_entry >= 1024)
+ dir_entry = FIRST_VM_PAGE>>10;
+ if (!(1 & (pg_table = pg_dir[dir_entry]))) {
+ if (pg_table) {
+ printk("bad page-table at pg_dir[%d]: %08x\n\r",
+ dir_entry,pg_table);
+ pg_dir[dir_entry] = 0;
+ }
counter -= 1024;
dir_entry++;
- if (dir_entry >= 1024)
- dir_entry = FIRST_VM_PAGE>>10;
- if (pg_table = pg_dir[dir_entry])
- break;
- }
- if (counter <= 0) {
- printk("Out of swap-memory\n");
- return 0;
- }
- if (!(pg_table & 1)) {
- printk("bad page-table at pg_dir[%d]: %08x\n\r",dir_entry,
- pg_table);
- return 0;
+ goto check_dir;
}
pg_table &= 0xfffff000;
- while (counter > 0) {
- counter--;
- page_entry++;
- if (page_entry >= 1024) {
- page_entry = -1;
- goto repeat;
- }
- if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
- return 1;
+check_table:
+ if (counter < 0)
+ goto no_swap;
+ counter--;
+ page_entry++;
+ if (page_entry >= 1024) {
+ page_entry = -1;
+ dir_entry++;
+ goto check_dir;
}
+ if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
+ return 1;
+ goto check_table;
+no_swap:
printk("Out of swap-memory\n\r");
return 0;
}