aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Benedict Torvalds <torvalds@klaava.Helsinki.FI>1992-06-04 22:56:21 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:04 -0400
commit13f296db85e43116f5e1de944b6997dd98093640 (patch)
tree7658905de163908272cc1291b5ad5c858356c7ac
parent46d255794351e97e7b06958d2859b6ec7c373f73 (diff)
downloadarchive-13f296db85e43116f5e1de944b6997dd98093640.tar.gz
Second patch to 0.96av0.96a-pl2
I have just sent off the second patch to 0.96a: it should be on the normal ftp-sites (nic, tsx-11 and banjo), although the only site which I can make it directly readable on is banjo, so on the other sites it will take the site-managers to make the patch available. Patch 2 implements: - itimers (by Darren Senn), which are now also used to implement the alarm() system call. - ultrastor scsi driver patches (by gentzel) - [f]statfs() system call is implemented (so df can be made fs- independent). Also some other minor fs-changes for the upcoming new filesystem. Patches by Remy Card. - preliminary core-file dumping code (linux creates a core-file, but it's not in the correct format yet [*]). - minor changes/bugfixes. While patching in patch1 is a good idea for anybody, patch 2 isn't really vital. I've made it available just so kernel hackers can keep up with the kernel I have right now if they wish. Patch 2 is relative to patch 1: you have to patch that in first. [*] The current core-file is very simple, and the kernel code is there just so that some enterprising character can expand it. A core-file looks like this right now: offset data 0x0000 "core-dump: regs=\n" 0x0040 struct pt_regs (see <sys/ptrace.c>) 0x0400 "floating-point regs:\n" 0x0440 struct i387 (see <linux/sched.h>) 0x0800 the first 1kB of user-space Not very practical, but it /might/ help if the X-server dies of a segmentation fault or similar (you can use pt_regs.eip to see where it happened). The kernel code is very easy to change to accomodate for the real core-file format, I just didn't know what it should be. Linus
-rw-r--r--boot/bootsect.S3
-rw-r--r--fs/exec.c88
-rw-r--r--fs/minix/bitmap.c42
-rw-r--r--fs/minix/blkdev.c3
-rw-r--r--fs/minix/chrdev.c2
-rw-r--r--fs/minix/dir.c6
-rw-r--r--fs/minix/file.c12
-rw-r--r--fs/minix/inode.c33
-rw-r--r--fs/minix/symlink.c6
-rw-r--r--fs/namei.c2
-rw-r--r--fs/open.c32
-rw-r--r--fs/pipe.c1
-rw-r--r--include/asm/io.h4
-rw-r--r--include/linux/fs.h14
-rw-r--r--include/linux/minix_fs.h3
-rw-r--r--include/linux/sched.h9
-rw-r--r--include/linux/sys.h4
-rw-r--r--include/linux/unistd.h3
-rw-r--r--include/signal.h3
-rw-r--r--include/sys/time.h3
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/blk_drv/blk.h63
-rw-r--r--kernel/blk_drv/floppy.c5
-rw-r--r--kernel/blk_drv/hd.c61
-rw-r--r--kernel/blk_drv/ll_rw_blk.c5
-rw-r--r--kernel/blk_drv/scsi/ultrastor.c359
-rw-r--r--kernel/blk_drv/scsi/ultrastor.h34
-rw-r--r--kernel/chr_drv/console.c4
-rw-r--r--kernel/chr_drv/keyboard.c2
-rw-r--r--kernel/chr_drv/tty_io.c27
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/itimer.c111
-rw-r--r--kernel/math/ea.c2
-rw-r--r--kernel/sched.c45
-rw-r--r--kernel/signal.c56
-rw-r--r--kernel/sys.c12
-rw-r--r--kernel/sys_call.S3
-rw-r--r--lib/Makefile2
-rw-r--r--tools/build.c2
39 files changed, 767 insertions, 304 deletions
diff --git a/boot/bootsect.S b/boot/bootsect.S
index 837be32..22ebdea 100644
--- a/boot/bootsect.S
+++ b/boot/bootsect.S
@@ -224,8 +224,7 @@ got_sectors:
mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18
je root_defined
-undef_root:
- jmp undef_root
+ mov ax,#0x0200 ! /dev/fd0 - autodetect
root_defined:
seg cs
mov root_dev,ax
diff --git a/fs/exec.c b/fs/exec.c
index 48d727f..48cc8ed 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -21,7 +21,9 @@
#include <errno.h>
#include <linux/string.h>
#include <sys/stat.h>
+#include <sys/ptrace.h>
#include <a.out.h>
+#include <fcntl.h>
#include <linux/fs.h>
#include <linux/sched.h>
@@ -40,6 +42,86 @@ extern int sys_close(int fd);
#define MAX_ARG_PAGES 32
/*
+ * These are the only things you should do on a core-file: use only these
+ * macros to write out all the necessary info.
+ */
+#define DUMP_WRITE(addr,nr) \
+while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
+
+#define DUMP_SEEK(offset) \
+if (file.f_op->lseek) { \
+ if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
+ goto close_coredump; \
+} else file.f_pos = (offset)
+
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently only a stub-function.
+ *
+ * Note that setuid/setgid files won't make a core-dump if the uid/gid
+ * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
+ * field, which also makes sure the core-dumps won't be recursive if the
+ * dumping of the process results in another error..
+ */
+int core_dump(long signr, struct pt_regs * regs)
+{
+ struct inode * inode = NULL;
+ struct file file;
+ unsigned short fs;
+ int has_dumped = 0;
+
+ if (!current->dumpable)
+ return 0;
+ current->dumpable = 0;
+ __asm__("mov %%fs,%0":"=r" (fs));
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode))
+ goto end_coredump;
+ if (!S_ISREG(inode->i_mode))
+ goto end_coredump;
+ if (!inode->i_op || !inode->i_op->default_file_ops)
+ goto end_coredump;
+ file.f_mode = 3;
+ file.f_flags = 0;
+ file.f_count = 1;
+ file.f_inode = inode;
+ file.f_pos = 0;
+ file.f_reada = 0;
+ file.f_op = inode->i_op->default_file_ops;
+ if (file.f_op->open)
+ if (file.f_op->open(inode,&file))
+ goto end_coredump;
+ if (!file.f_op->write)
+ goto close_coredump;
+ has_dumped = 1;
+/* write and seek example: from kernel space */
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ DUMP_WRITE("core-dump, regs=\n",17);
+ DUMP_SEEK(64);
+ DUMP_WRITE(regs,sizeof(*regs));
+ if (current->used_math) {
+ if (last_task_used_math == current)
+ __asm__("clts ; fnsave %0"::"m" (current->tss.i387));
+ DUMP_SEEK(1024);
+ DUMP_WRITE("floating-point regs=\n",21);
+ DUMP_SEEK(1088);
+ DUMP_WRITE(&current->tss.i387,sizeof(current->tss.i387));
+ }
+/* now we start writing out the user space info */
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
+/* the dummy dump-file contains the first block of user space... */
+ DUMP_SEEK(2048);
+ DUMP_WRITE(0,1024);
+close_coredump:
+ if (file.f_op->release)
+ file.f_op->release(inode,&file);
+end_coredump:
+ __asm__("mov %0,%%fs"::"r" (fs));
+ iput(inode);
+ return has_dumped;
+}
+
+/*
* Note that a shared library must be both readable and executable due to
* security reasons.
*
@@ -406,6 +488,7 @@ restart_interp:
}
}
/* OK, This is the point of no return */
+ current->dumpable = 1;
for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
if (ch == '/')
i = 0;
@@ -421,6 +504,9 @@ restart_interp:
iput(current->libraries[i].library);
current->libraries[i].library = NULL;
}
+ if (e_uid != current->euid || e_gid != current->egid ||
+ !permission(inode,MAY_READ))
+ current->dumpable = 0;
current->numlibraries = 0;
current->executable = inode;
current->signal = 0;
@@ -454,7 +540,7 @@ restart_interp:
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
- send_sig(SIGTRAP, current, 0);
+ send_sig(SIGTRAP, current, 0);
return 0;
exec_error2:
iput(inode);
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index a7fd3c3..fe185a7 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/bitmap.c
+ * linux/fs/minix/bitmap.c
*
* (C) 1991 Linus Torvalds
*/
@@ -44,6 +44,35 @@ __asm__("cld\n" \
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;})
+static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
+
+static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
+ unsigned numbits)
+{
+ unsigned i, j, end, sum = 0;
+ struct buffer_head *bh;
+
+ for (i=0; (i<numblocks) && numbits; i++) {
+ if (!(bh=map[i]))
+ return(0);
+ if (numbits >= (8*BLOCK_SIZE)) {
+ end = BLOCK_SIZE;
+ numbits -= 8*BLOCK_SIZE;
+ } else {
+ int tmp;
+ end = numbits >> 3;
+ numbits &= 0x7;
+ tmp = bh->b_data[end] & ((1<<numbits)-1);
+ sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
+ numbits = 0;
+ }
+ for (j=0; j<end; j++)
+ sum += nibblemap[bh->b_data[j] & 0xf]
+ + nibblemap[(bh->b_data[j]>>4)&0xf];
+ }
+ return(sum);
+}
+
int minix_free_block(int dev, int block)
{
struct super_block * sb;
@@ -107,6 +136,12 @@ int minix_new_block(int dev)
return j;
}
+unsigned long minix_count_free_blocks(struct super_block *sb)
+{
+ return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
+ << sb->s_log_zone_size;
+}
+
void minix_free_inode(struct inode * inode)
{
struct buffer_head * bh;
@@ -182,3 +217,8 @@ struct inode * minix_new_inode(int dev)
inode->i_op = NULL;
return inode;
}
+
+unsigned long minix_count_free_inodes(struct super_block *sb)
+{
+ return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
+}
diff --git a/fs/minix/blkdev.c b/fs/minix/blkdev.c
index fec1bc9..a70b513 100644
--- a/fs/minix/blkdev.c
+++ b/fs/minix/blkdev.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/chrdev.c
+ * linux/fs/minix/blkdev.c
*
* (C) 1991 Linus Torvalds
*/
@@ -19,7 +19,6 @@ static int blkdev_open(struct inode * inode, struct file * filp)
{
int i;
- check_disk_change(inode->i_rdev);
i = MAJOR(inode->i_rdev);
if (i < MAX_BLKDEV) {
filp->f_op = blkdev_fops[i];
diff --git a/fs/minix/chrdev.c b/fs/minix/chrdev.c
index 489849f..8957eb4 100644
--- a/fs/minix/chrdev.c
+++ b/fs/minix/chrdev.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/chrdev.c
+ * linux/fs/minix/chrdev.c
*
* (C) 1991 Linus Torvalds
*/
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index d09585a..467d227 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -1,7 +1,9 @@
/*
- * linux/fs/minix/dir.c
+ * linux/fs/minix/dir.c
*
- * minix directory hadnling functions
+ * (C) 1991 Linus Torvalds
+ *
+ * minix directory handling functions
*/
#include <errno.h>
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 9ebeebb..7b6e033 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -1,7 +1,9 @@
/*
- * linux/fs/minix/file.c
+ * linux/fs/minix/file.c
*
- * minix regular file handling primitives
+ * (C) 1991 Linus Torvalds
+ *
+ * minix regular file handling primitives
*/
#include <errno.h>
@@ -212,10 +214,8 @@ static int minix_file_write(struct inode * inode, struct file * filp, char * buf
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
- if (!(filp->f_flags & O_APPEND)) {
- filp->f_pos = pos;
- inode->i_ctime = CURRENT_TIME;
- }
+ inode->i_ctime = CURRENT_TIME;
+ filp->f_pos = pos;
inode->i_dirt = 1;
return written;
}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 4ddf5c2..df68ec5 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
+#include <asm/segment.h>
int sync_dev(int dev);
@@ -40,12 +41,14 @@ static struct super_operations minix_sops = {
minix_read_inode,
minix_write_inode,
minix_put_inode,
- minix_put_super
+ minix_put_super,
+ minix_statfs
};
struct super_block *minix_read_super(struct super_block *s,void *data)
{
struct buffer_head *bh;
+ struct minix_super_block *ms;
int i,dev=s->s_dev,block;
lock_super(s);
@@ -55,8 +58,17 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
printk("bread failed\n");
return NULL;
}
- *((struct minix_super_block *) s) =
- *((struct minix_super_block *) bh->b_data);
+/* *((struct minix_super_block *) s) =
+ *((struct minix_super_block *) bh->b_data); */
+ ms = (struct minix_super_block *) bh->b_data;
+ s->s_ninodes = ms->s_ninodes;
+ s->s_nzones = ms->s_nzones;
+ s->s_imap_blocks = ms->s_imap_blocks;
+ s->s_zmap_blocks = ms->s_zmap_blocks;
+ s->s_firstdatazone = ms->s_firstdatazone;
+ s->s_log_zone_size = ms->s_log_zone_size;
+ s->s_max_size = ms->s_max_size;
+ s->s_magic = ms->s_magic;
brelse(bh);
if (s->s_magic != MINIX_SUPER_MAGIC) {
s->s_dev = 0;
@@ -103,6 +115,21 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
return s;
}
+void minix_statfs (struct super_block *sb, struct statfs *buf)
+{
+ long tmp;
+
+ put_fs_long(MINIX_SUPER_MAGIC, &buf->f_type);
+ put_fs_long(1024, &buf->f_bsize);
+ put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
+ tmp = minix_count_free_blocks(sb);
+ put_fs_long(tmp, &buf->f_bfree);
+ put_fs_long(tmp, &buf->f_bavail);
+ put_fs_long(sb->s_ninodes, &buf->f_files);
+ put_fs_long(minix_count_free_inodes(sb), &buf->f_ffree);
+ /* Don't know what value to put in buf->f_fsid */
+}
+
static int _minix_bmap(struct inode * inode,int block,int create)
{
struct buffer_head * bh;
diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c
index 70fbeb0..0b5c5dc 100644
--- a/fs/minix/symlink.c
+++ b/fs/minix/symlink.c
@@ -1,7 +1,9 @@
/*
- * linux/fs/minix/symlink.c
+ * linux/fs/minix/symlink.c
*
- * minix symlink handling code
+ * (C) 1991 Linus Torvalds
+ *
+ * minix symlink handling code
*/
#include <errno.h>
diff --git a/fs/namei.c b/fs/namei.c
index c4f4acc..0a59da8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -201,7 +201,7 @@ int open_namei(const char * pathname, int flag, int mode,
if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
flag |= O_WRONLY;
- mode &= 0777 & ~current->umask;
+ mode &= 07777 & ~current->umask;
mode |= I_REGULAR;
if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
return -ENOENT;
diff --git a/fs/open.c b/fs/open.c
index 3e47592..33e3957 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -33,14 +33,34 @@ int sys_ustat(int dev, struct ustat * ubuf)
int sys_statfs(const char * path, struct statfs * buf)
{
- printk("statfs not implemented\n");
- return -ENOSYS;
+ struct inode * inode;
+
+ verify_area(buf, sizeof(struct statfs));
+ if (!(inode = namei(path)))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs) {
+ iput(inode);
+ return -ENOSYS;
+ }
+ inode->i_sb->s_op->statfs(inode->i_sb, buf);
+ iput(inode);
+ return 0;
}
int sys_fstatfs(unsigned int fd, struct statfs * buf)
{
- printk("fstatfs not implemented\n");
- return -ENOSYS;
+ struct inode * inode;
+ struct file * file;
+
+ verify_area(buf, sizeof(struct statfs));
+ if (fd >= NR_OPEN || !(file = current->filp[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs)
+ return -ENOSYS;
+ inode->i_sb->s_op->statfs(inode->i_sb, buf);
+ return 0;
}
int sys_truncate(const char * path, unsigned int length)
@@ -256,13 +276,13 @@ int sys_open(const char * filename,int flag,int mode)
if (!current->filp[fd])
break;
if (fd>=NR_OPEN)
- return -EINVAL;
+ return -EMFILE;
current->close_on_exec &= ~(1<<fd);
f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break;
if (i>=NR_FILE)
- return -EINVAL;
+ return -ENFILE;
(current->filp[fd] = f)->f_count++;
if ((i = open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
diff --git a/fs/pipe.c b/fs/pipe.c
index 1657ccb..fa91c01 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -174,6 +174,7 @@ int sys_pipe(unsigned long * fildes)
}
f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0;
+ f[0]->f_flags = f[1]->f_flags = 0;
f[0]->f_op = &read_pipe_fops;
f[0]->f_mode = 1; /* read */
f[1]->f_op = &write_pipe_fops;
diff --git a/include/asm/io.h b/include/asm/io.h
index af1c72f..dd7cb44 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -18,9 +18,11 @@ __asm__ volatile ("outb %0,%1"
extern void inline outb_p(char value, unsigned short port)
{
__asm__ volatile ("outb %0,%1\n\t"
+#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
+#endif
"outb %0,$0x80"
::"a" ((char) value),"d" ((unsigned short) port));
}
@@ -37,9 +39,11 @@ extern unsigned char inline inb_p(unsigned short port)
{
unsigned char _v;
__asm__ volatile ("inb %1,%0\n\t"
+#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
+#endif
"outb %0,$0x80"
:"=a" (_v):"d" ((unsigned short) port));
return _v;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c4bcb84..304b374 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -8,6 +8,7 @@
#include <sys/types.h>
#include <sys/dirent.h>
+#include <sys/vfs.h>
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
@@ -135,12 +136,12 @@ typedef struct select_table_struct {
} select_table;
struct super_block {
- unsigned short s_ninodes;
- unsigned short s_nzones;
- unsigned short s_imap_blocks;
- unsigned short s_zmap_blocks;
- unsigned short s_firstdatazone;
- unsigned short s_log_zone_size;
+ unsigned long s_ninodes;
+ unsigned long s_nzones;
+ unsigned long s_imap_blocks;
+ unsigned long s_zmap_blocks;
+ unsigned long s_firstdatazone;
+ unsigned long s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
/* These are only in memory */
@@ -191,6 +192,7 @@ struct super_operations {
void (*write_inode) (struct inode *inode);
void (*put_inode) (struct inode *inode);
void (*put_super)(struct super_block *sb);
+ void (*statfs) (struct super_block *sb, struct statfs *buf);
};
struct file_system_type {
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index a51b60c..76f8f51 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -60,8 +60,10 @@ extern int minix_rename(struct inode * old_dir, const char * old_name, int old_l
struct inode * new_dir, const char * new_name, int new_len);
extern struct inode * minix_new_inode(int dev);
extern void minix_free_inode(struct inode * inode);
+extern unsigned long minix_count_free_inodes(struct super_block *sb);
extern int minix_new_block(int dev);
extern int minix_free_block(int dev, int block);
+extern unsigned long minix_count_free_blocks(struct super_block *sb);
extern int minix_create_block(struct inode *, int);
extern int minix_bmap(struct inode *,int);
@@ -72,6 +74,7 @@ extern struct super_block *minix_read_super(struct super_block *,void *);
extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *);
+extern void minix_statfs(struct super_block *, struct statfs *);
extern int minix_lseek(struct inode *, struct file *, off_t, int);
extern int minix_read(struct inode *, struct file *, char *, int);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b52578d..e301b34 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -119,6 +119,7 @@ struct task_struct {
long blocked; /* bitmap of masked signals */
/* various fields */
int exit_code;
+ int dumpable;
unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,pgrp,session,leader;
int groups[NGROUPS];
@@ -134,7 +135,9 @@ struct task_struct {
struct task_struct *next_wait;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
- unsigned long timeout,alarm;
+ unsigned long timeout;
+ unsigned long it_real_value, it_prof_value, it_virt_value;
+ unsigned long it_real_incr, it_prof_incr, it_virt_incr;
long utime,stime,cutime,cstime,start_time;
unsigned long min_flt, maj_flt;
unsigned long cmin_flt, cmaj_flt;
@@ -181,12 +184,12 @@ struct task_struct {
#define INIT_TASK \
/* state etc */ { 0,15,15, \
/* signals */ 0,{{},},0, \
-/* ec,brk... */ 0,0,0,0,0,0, \
+/* ec,brk... */ 0,0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \
/* 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, \
+/* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
/* min_flt */ 0,0,0,0, \
/* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
{0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
diff --git a/include/linux/sys.h b/include/linux/sys.h
index d35b1d7..79640f1 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -106,6 +106,8 @@ extern int sys_fstatfs();
extern int sys_ioperm();
extern int sys_socketcall();
extern int sys_syslog();
+extern int sys_getitimer();
+extern int sys_setitimer();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
@@ -126,7 +128,7 @@ sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
-sys_socketcall, sys_syslog };
+sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/include/linux/unistd.h b/include/linux/unistd.h
index 21e19ba..a9e8501 100644
--- a/include/linux/unistd.h
+++ b/include/linux/unistd.h
@@ -117,6 +117,9 @@
extern int errno;
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
diff --git a/include/signal.h b/include/signal.h
index e4126d3..91df52e 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -43,9 +43,10 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGPOLL SIGIO
#define SIGXCPU 24
#define SIGXFSZ 25
+*/
+
#define SIGVTALRM 26
#define SIGPROF 27
-*/
#define SIGWINCH 28
diff --git a/include/sys/time.h b/include/sys/time.h
index 1165c26..9d1f785 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -54,6 +54,9 @@ struct itimerval {
struct timeval it_value; /* current value */
};
+int getitimer(int which, struct itimerval *value);
+int setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
+
#include <time.h>
#include <sys/types.h>
diff --git a/kernel/Makefile b/kernel/Makefile
index 716bcfd..8930f3f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -28,7 +28,7 @@ CPP =cpp -nostdinc -I../include
OBJS = sched.o sys_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
- signal.o mktime.o ptrace.o ioport.o
+ signal.o mktime.o ptrace.o ioport.o itimer.o
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS)
diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h
index 1bc455c..4535f6d 100644
--- a/kernel/blk_drv/blk.h
+++ b/kernel/blk_drv/blk.h
@@ -149,47 +149,40 @@ extern inline void unlock_buffer(struct buffer_head * bh)
wake_up(&bh->b_wait);
}
-extern inline void end_request(int uptodate)
+static void end_request(int uptodate)
{
- struct request * tmp;
-
- tmp = CURRENT;
- DEVICE_OFF(tmp->dev);
- CURRENT = tmp->next;
- if (tmp->bh) {
- tmp->bh->b_uptodate = uptodate;
- unlock_buffer(tmp->bh);
- }
- if (!uptodate) {
- printk(DEVICE_NAME " I/O error\n\r");
- printk("dev %04x, block %d\n\r",tmp->dev,
- tmp->bh->b_blocknr);
- }
- wake_up(&tmp->waiting);
- tmp->dev = -1;
- wake_up(&wait_for_request);
-}
-
-extern inline void next_buffer(int uptodate)
-{
- struct buffer_head *tmp;
+ struct request * req;
+ struct buffer_head * bh;
- tmp = CURRENT->bh;
- CURRENT->bh = tmp->b_reqnext;
- tmp->b_reqnext = NULL;
- tmp->b_uptodate = uptodate;
- unlock_buffer(tmp);
+ req = CURRENT;
+ req->errors = 0;
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
- printk("dev %04x, block %d\n\r",tmp->b_dev, tmp->b_blocknr);
+ printk("dev %04x, sector %d\n\r",req->dev,req->sector);
+ req->nr_sectors--;
+ req->nr_sectors &= ~1;
+ req->sector += 2;
+ req->sector &= ~1;
}
- if (!CURRENT->bh) {
- printk("next_buffer: request buffer list destroyed\r\n");
- end_request(0);
- return;
+ if (bh = req->bh) {
+ req->bh = bh->b_reqnext;
+ bh->b_reqnext = NULL;
+ bh->b_uptodate = uptodate;
+ unlock_buffer(bh);
+ if (bh = req->bh) {
+ if (req->nr_sectors < 2) {
+ req->nr_sectors = 2;
+ printk("end_request: buffer-list destroyed\n");
+ }
+ req->buffer = bh->b_data;
+ return;
+ }
}
- CURRENT->buffer = CURRENT->bh->b_data;
- CURRENT->errors = 0;
+ DEVICE_OFF(req->dev);
+ CURRENT = req->next;
+ wake_up(&req->waiting);
+ req->dev = -1;
+ wake_up(&wait_for_request);
}
#ifdef DEVICE_INTR
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index 2b9d238..c4af79e 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -35,7 +35,7 @@
/*
* Automatic floppy-detection and formatting written by Werner Almesberger
* (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
- * the floppy-change signa| detection.
+ * the floppy-change signal detection.
*/
#include <linux/sched.h>
@@ -942,7 +942,8 @@ static void config_types(void)
{
printk("Floppy drive(s): ");
base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
- if (((CMOS_READ(0x14) >> 6) & 1) == 0) base_type[0] = NULL;
+ if (((CMOS_READ(0x14) >> 6) & 1) == 0)
+ base_type[1] = NULL;
else {
printk(", ");
base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index 6244567..e573315 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -24,6 +24,8 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
+
+#define REALLY_SLOW_IO
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
@@ -423,17 +425,8 @@ static void bad_rw_intr(void)
if (!CURRENT)
return;
if (++CURRENT->errors >= MAX_ERRORS)
- if (CURRENT->bh && CURRENT->nr_sectors > 2) {
- CURRENT->nr_sectors--;
- CURRENT->sector++;
- if (CURRENT->nr_sectors & 1) {
- CURRENT->nr_sectors--;
- CURRENT->sector++;
- }
- next_buffer(0);
- } else
- end_request(0);
- if (CURRENT->errors > MAX_ERRORS/2)
+ end_request(0);
+ else if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
else
recalibrate = 1;
@@ -457,16 +450,15 @@ static void read_intr(void)
if ((i & STAT_MASK) != STAT_OK)
goto bad_read;
CURRENT->errors = 0;
- if (CURRENT->bh && (CURRENT->nr_sectors&1) && CURRENT->nr_sectors > 2)
- next_buffer(1);
- else
- CURRENT->buffer += 512;
+ CURRENT->buffer += 512;
CURRENT->sector++;
- if (--CURRENT->nr_sectors) {
+ i = --CURRENT->nr_sectors;
+ if (!i || (CURRENT->bh && !(i&1)))
+ end_request(1);
+ if (i > 0) {
SET_INTR(&read_intr);
return;
}
- end_request(1);
#if (HD_DELAY > 0)
last_req = read_timer();
#endif
@@ -487,24 +479,22 @@ static void write_intr(void)
i = (unsigned) inb_p(HD_STATUS);
if ((i & STAT_MASK) != STAT_OK)
goto bad_write;
- if (CURRENT->nr_sectors < 2) {
+ if (CURRENT->nr_sectors > 1 && !(i & DRQ_STAT))
+ goto bad_write;
+ CURRENT->sector++;
+ i = --CURRENT->nr_sectors;
+ CURRENT->buffer += 512;
+ if (!i || (CURRENT->bh && !(i & 1)))
end_request(1);
+ if (i > 0) {
+ SET_INTR(&write_intr);
+ port_write(HD_DATA,CURRENT->buffer,256);
+ } else {
#if (HD_DELAY > 0)
last_req = read_timer();
#endif
do_hd_request();
- return;
}
- if (!(i & DRQ_STAT))
- goto bad_write;
- CURRENT->sector++;
- CURRENT->nr_sectors--;
- if (CURRENT->bh && !(CURRENT->nr_sectors & 1))
- next_buffer(1);
- else
- CURRENT->buffer += 512;
- SET_INTR(&write_intr);
- port_write(HD_DATA,CURRENT->buffer,256);
return;
bad_write:
if (i & ERR_STAT)
@@ -534,16 +524,7 @@ static void hd_times_out(void)
printk("HD timeout\n\r");
cli();
if (++CURRENT->errors >= MAX_ERRORS)
- if (CURRENT->bh && CURRENT->nr_sectors > 2) {
- CURRENT->nr_sectors--;
- CURRENT->sector++;
- if (CURRENT->nr_sectors & 1) {
- CURRENT->nr_sectors--;
- CURRENT->sector++;
- }
- next_buffer(0);
- } else
- end_request(0);
+ end_request(0);
do_hd_request();
}
@@ -558,7 +539,7 @@ static void do_hd_request(void)
dev = MINOR(CURRENT->dev);
block = CURRENT->sector;
nsect = CURRENT->nr_sectors;
- if (dev >= (NR_HD<<6) || block+nsect > hd[dev].nr_sects) {
+ if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
end_request(0);
goto repeat;
}
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index 18f58d4..cd6aef7 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -125,6 +125,11 @@ static void make_request(int major,int rw, struct buffer_head * bh)
printk("Bad block dev command, must be R/W/RA/WA\n");
return;
}
+ if (blk_size[major])
+ if (blk_size[major][MINOR(bh->b_dev)] <= bh->b_blocknr) {
+ bh->b_dirt = bh->b_uptodate = 0;
+ return;
+ }
lock_buffer(bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
unlock_buffer(bh);
diff --git a/kernel/blk_drv/scsi/ultrastor.c b/kernel/blk_drv/scsi/ultrastor.c
index 049fdd8..085e10f 100644
--- a/kernel/blk_drv/scsi/ultrastor.c
+++ b/kernel/blk_drv/scsi/ultrastor.c
@@ -1,16 +1,39 @@
/*
* ultrastor.c (C) 1991 David B. Gentzel
- * Low-level scsi driver for UltraStor 14F
+ * Low-level SCSI driver for UltraStor 14F
* by David B. Gentzel, Whitfield Software Services, Carnegie, PA
* (gentzel@nova.enet.dec.com)
* Thanks to UltraStor for providing the necessary documentation
*/
-/* ??? Caveats:
- This driver is VERY stupid. It takes no advantage of much of the power of
- the UltraStor controller. We just sit-and-spin while waiting for commands
- to complete. I hope to go back and beat it into shape, but PLEASE, anyone
- else who would like to, please make improvements! */
+/*
+ * NOTES:
+ * The UltraStor 14F is an intelligent, high performance ISA SCSI-2 host
+ * adapter. It is essentially an ISA version of the UltraStor 24F EISA
+ * adapter. It supports first-party DMA, command queueing, and
+ * scatter/gather I/O. It can also emulate the standard AT MFM/RLL/IDE
+ * interface for use with OS's which don't support SCSI.
+ *
+ * This driver may also work (with some small changes) with the UltraStor
+ * 24F. I have no way of confirming this...
+ *
+ * Places flagged with a triple question-mark are things which are either
+ * unfinished, questionable, or wrong.
+ */
+
+/*
+ * CAVEATS: ???
+ * This driver is VERY stupid. It takes no advantage of much of the power
+ * of the UltraStor controller. We just sit-and-spin while waiting for
+ * commands to complete. I hope to go back and beat it into shape, but
+ * PLEASE, anyone else who would like to, please make improvements!
+ *
+ * By defining USE_QUEUECOMMAND as TRUE in ultrastor.h, you enable the
+ * queueing feature of the mid-level SCSI driver. This should improve
+ * performance somewhat. However, it does not seem to work. I believe
+ * this is due to a bug in the mid-level driver, but I haven't looked
+ * too closely.
+ */
#include <linux/config.h>
@@ -19,22 +42,20 @@
#include <stddef.h>
#include <linux/string.h>
-#include <linux/config.h>
#include <linux/sched.h>
-#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/system.h>
+#define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */
#include "ultrastor.h"
#include "scsi.h"
#include "hosts.h"
-#define VERSION "1.0 alpha"
+#define VERSION "1.0 beta"
#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
+#define BIT(n) (1ul << (n))
#define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
/* Simply using "unsigned long" in these structures won't work as it causes
@@ -44,21 +65,32 @@ typedef struct {
unsigned char bytes[4];
} Longword;
+/* Used to fetch the configuration info from the config i/o registers. We
+ then store (in a friendlier format) in config. */
+struct config_1 {
+ unsigned char bios_segment: 3;
+ unsigned char reserved: 1;
+ unsigned char interrupt: 2;
+ unsigned char dma_channel: 2;
+};
+struct config_2 {
+ unsigned char ha_scsi_id: 3;
+ unsigned char mapping_mode: 2;
+ unsigned char bios_drive_number: 1;
+ unsigned char tfr_port: 2;
+};
+
/* Used to store configuration info read from config i/o registers. Most of
this is not used yet, but might as well save it. */
struct config {
- struct {
- unsigned char bios_segment: 3;
- unsigned char reserved: 1;
- unsigned char interrupt: 2;
- unsigned char dma_channel: 2;
- } config_1;
- struct {
- unsigned char ha_scsi_id: 3;
- unsigned char mapping_mode: 2;
- unsigned char bios_drive_number: 1;
- unsigned char tfr_port: 2;
- } config_2;
+ unsigned short port_address;
+ const void *bios_segment;
+ unsigned char interrupt: 4;
+ unsigned char dma_channel: 3;
+ unsigned char ha_scsi_id: 3;
+ unsigned char heads: 6;
+ unsigned char sectors: 6;
+ unsigned char bios_drive_number: 1;
};
/* MailBox SCSI Command Packet. Basic command structure for communicating
@@ -97,12 +129,11 @@ static const unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
/* Allowed DMA channels for 14f (0 indicates reserved) */
static const unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
-#if 0 /* Not currently used, head/sector mappings allowed by 14f */
+/* Head/sector mappings allowed by 14f */
static const struct {
unsigned char heads;
unsigned char sectors;
} mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
-#endif
/* Config info */
static struct config config;
@@ -114,8 +145,7 @@ static int host_number;
#ifdef PORT_OVERRIDE
# define PORT_ADDRESS PORT_OVERRIDE
#else
-static unsigned short port_address = 0;
-# define PORT_ADDRESS port_address
+# define PORT_ADDRESS (config.port_address)
#endif
static volatile int aborted = 0;
@@ -126,6 +156,10 @@ static const unsigned short ultrastor_ports[] = {
};
#endif
+void ultrastor_interrupt(void);
+
+static void (*ultrastor_done)(int, int) = 0;
+
static const struct {
const char *signature;
size_t offset;
@@ -138,75 +172,105 @@ int ultrastor_14f_detect(int hostnum)
{
size_t i;
unsigned char in_byte;
- const void *base_address;
+ struct config_1 config_1;
+ struct config_2 config_2;
-#ifdef DEBUG
- printk("ultrastor_14f_detect: called\n");
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: called\n");
#endif
#ifndef PORT_OVERRIDE
-/* ??? This is easy to implement, but I'm not sure how "friendly" it is to
- go off and read random i/o ports. */
-# error Not implemented!
+ PORT_ADDRESS = 0;
+ for (i = 0; i < ARRAY_SIZE(ultrastor_ports); i++) {
+ PORT_ADDRESS = ultrastor_ports[i];
#endif
- if (!PORT_ADDRESS) {
-#ifdef DEBUG
- printk("ultrastor_14f_detect: no port address found!\n");
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: testing port address %03X\n", PORT_ADDRESS);
#endif
- return FALSE;
- }
-#ifdef DEBUG
- printk("ultrastor_14f_detect: port address = %X\n", PORT_ADDRESS);
+ in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
+ if (in_byte != US14F_PRODUCT_ID_0) {
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+# ifdef PORT_OVERRIDE
+ printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
+# else
+ printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
+# endif
#endif
-
- in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
- if (in_byte != US14F_PRODUCT_ID_0) {
-#ifdef DEBUG
- printk("ultrastor_14f_detect: unknown product ID 0 - %02X\n", in_byte);
+#ifdef PORT_OVERRIDE
+ return FALSE;
+#else
+ continue;
#endif
- return FALSE;
- }
- in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
- /* Only upper nibble is defined for Product ID 1 */
- if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
-#ifdef DEBUG
- printk("ultrastor_14f_detect: unknown product ID 1 - %02X\n", in_byte);
+ }
+ in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
+ /* Only upper nibble is defined for Product ID 1 */
+ if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+# ifdef PORT_OVERRIDE
+ printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
+# else
+ printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
+# endif
+#endif
+#ifdef PORT_OVERRIDE
+ return FALSE;
+#else
+ continue;
#endif
+ }
+#ifndef PORT_OVERRIDE
+ break;
+ }
+ if (i == ARRAY_SIZE(ultrastor_ports)) {
+# if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: no port address found!\n");
+# endif
return FALSE;
}
+#endif
+
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: adapter found at port address %03X\n",
+ PORT_ADDRESS);
+#endif
/* All above tests passed, must be the right thing. Get some useful
info. */
- *(char *)&config.config_1 = inb(CONFIG(PORT_ADDRESS + 0));
- *(char *)&config.config_2 = inb(CONFIG(PORT_ADDRESS + 1));
+ *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
+ *(char *)&config_2 = inb(CONFIG(PORT_ADDRESS + 1));
+ config.bios_segment = bios_segment_table[config_1.bios_segment];
+ config.interrupt = interrupt_table[config_1.interrupt];
+ config.dma_channel = dma_channel_table[config_1.dma_channel];
+ config.ha_scsi_id = config_2.ha_scsi_id;
+ config.heads = mapping_table[config_2.mapping_mode].heads;
+ config.sectors = mapping_table[config_2.mapping_mode].sectors;
+ config.bios_drive_number = config_2.bios_drive_number;
/* To verify this card, we simply look for the UltraStor SCSI from the
BIOS version notice. */
- base_address = bios_segment_table[config.config_1.bios_segment];
- if (base_address != NULL) {
+ if (config.bios_segment != NULL) {
int found = 0;
for (i = 0; !found && i < ARRAY_SIZE(signatures); i++)
- if (memcmp((char *)base_address + signatures[i].offset,
+ if (memcmp((char *)config.bios_segment + signatures[i].offset,
signatures[i].signature, signatures[i].length))
found = 1;
if (!found)
- base_address = NULL;
+ config.bios_segment = NULL;
}
- if (!base_address) {
-#ifdef DEBUG
- printk("ultrastor_14f_detect: not detected.\n");
+ if (!config.bios_segment) {
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: not detected.\n");
#endif
return FALSE;
}
/* Final consistancy check, verify previous info. */
- if (!dma_channel_table[config.config_1.dma_channel]
- || !(config.config_2.tfr_port & 0x2)) {
-#ifdef DEBUG
- printk("ultrastor_14f_detect: consistancy check failed\n");
+ if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: consistancy check failed\n");
#endif
return FALSE;
}
@@ -216,18 +280,25 @@ int ultrastor_14f_detect(int hostnum)
exhausted! */
/* Finally! Now I'm satisfied... */
-#ifdef DEBUG
- printk("ultrastor_14f_detect: detect succeeded\n"
+#if (ULTRASTOR_DEBUG & UD_DETECT)
+ printk("US14F: detect: detect succeeded\n"
+ " Port address: %03X\n"
" BIOS segment: %05X\n"
- " Interrupt: %d\n"
- " DMA channel: %d\n"
- " H/A SCSI ID: %d\n",
- base_address, interrupt_table[config.config_1.interrupt],
- dma_channel_table[config.config_1.dma_channel],
- config.config_2.ha_scsi_id);
+ " Interrupt: %u\n"
+ " DMA channel: %u\n"
+ " H/A SCSI ID: %u\n",
+ PORT_ADDRESS, config.bios_segment, config.interrupt,
+ config.dma_channel, config.ha_scsi_id);
#endif
host_number = hostnum;
- scsi_hosts[hostnum].this_id = config.config_2.ha_scsi_id;
+ scsi_hosts[hostnum].this_id = config.ha_scsi_id;
+#if USE_QUEUECOMMAND
+ set_intr_gate(0x20 + config.interrupt, ultrastor_interrupt);
+ /* gate to PIC 2 */
+ outb_p(inb_p(0x21) & ~BIT(2), 0x21);
+ /* enable the interrupt */
+ outb(inb_p(0xA1) & ~BIT(config.interrupt - 8), 0xA1);
+#endif
return TRUE;
}
@@ -238,64 +309,86 @@ const char *ultrastor_14f_info(void)
" by David B. Gentzel\n";
}
-#if 0
+static struct mscp mscp = {
+ OP_SCSI, DTD_SCSI, FALSE, TRUE, FALSE /* This stuff doesn't change */
+};
+
int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
void *buff, int bufflen, void (*done)(int, int))
-#else
-int ultrastor_14f_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen)
-#endif
{
- struct mscp mscp = {
- OP_SCSI, DTD_SCSI, FALSE, TRUE, FALSE,
- target, 0, 0 /* LUN??? */,
- *(Longword *)&buff,
- *(Longword *)&bufflen,
- { 0, 0, 0, 0 },
- 0,
- 0,
- 0,
- ((*(char *)cmnd <= 0x1F) ? 6 : 10),
- { 0 }, /* Filled in via memcpy below */
- 0,
- 0,
- { 0, 0, 0, 0 }
- };
unsigned char in_byte;
+#if (ULTRASTOR_DEBUG & UD_COMMAND)
+ printk("US14F: queuecommand: called\n");
+#endif
+
+ /* Skip first (constant) byte */
+ memset((char *)&mscp + 1, 0, sizeof (struct mscp) - 1);
+ mscp.target_id = target;
+ /* mscp.lun = ???; */
+ mscp.transfer_data = *(Longword *)&buff;
+ mscp.transfer_data_length = *(Longword *)&bufflen,
+ mscp.length_of_scsi_cdbs = ((*(unsigned char *)cmnd <= 0x1F) ? 6 : 10);
memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
/* Find free OGM slot (OGMINT bit is 0) */
do
- in_byte = inb(LCL_DOORBELL_INTR(PORT_ADDRESS));
+ in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
while (!aborted && (in_byte & 1));
if (aborted)
/* ??? is this right? */
return (aborted << 16);
/* Store pointer in OGM address bytes */
- outb(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
- outb(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
- outb(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
- outb(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
+ outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
+ outb_p(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
+ outb_p(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
+ outb_p(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
/* Issue OGM interrupt */
- outb(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
+ outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
+
+ ultrastor_done = done;
+
+#if (ULTRASTOR_DEBUG & UD_COMMAND)
+ printk("US14F: queuecommand: returning\n");
+#endif
+
+ return 0;
+}
+
+#if !USE_QUEUECOMMAND
+int ultrastor_14f_command(unsigned char target, const void *cmnd,
+ void *buff, int bufflen)
+{
+ unsigned char in_byte;
+
+#if (ULTRASTOR_DEBUG & UD_COMMAND)
+ printk("US14F: command: called\n");
+#endif
+
+ (void)ultrastor_14f_queuecommand(target, cmnd, buff, bufflen, 0);
/* Wait for ICM interrupt */
do
- in_byte = inb(SYS_DOORBELL_INTR(PORT_ADDRESS));
+ in_byte = inb_p(SYS_DOORBELL_INTR(PORT_ADDRESS));
while (!aborted && !(in_byte & 1));
if (aborted)
/* ??? is this right? */
return (aborted << 16);
/* Clean ICM slot (set ICMINT bit to 0) */
- outb(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
+ outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
+
+#if (ULTRASTOR_DEBUG & UD_COMMAND)
+ printk("US14F: command: returning %08X\n",
+ (mscp.adapter_status << 16) | mscp.target_status);
+#endif
/* ??? not right, but okay for now? */
return (mscp.adapter_status << 16) | mscp.target_status;
}
+#endif
int ultrastor_14f_abort(int code)
{
@@ -307,23 +400,71 @@ int ultrastor_14f_reset(void)
{
unsigned char in_byte;
-#ifdef DEBUG
- printk("ultrastor_14f_reset: called\n");
+#if (ULTRASTOR_DEBUG & UD_RESET)
+ printk("US14F: reset: called\n");
#endif
/* Issue SCSI BUS reset */
- outb(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
+ outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
+
/* Wait for completion... */
do
- in_byte = inb(LCL_DOORBELL_INTR(PORT_ADDRESS));
+ in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
while (in_byte & 0x20);
aborted = DID_RESET;
-#ifdef DEBUG
- printk("ultrastor_14f_reset: returning\n");
+#if (ULTRASTOR_DEBUG & UD_RESET)
+ printk("US14F: reset: returning\n");
#endif
return 0;
}
+#if USE_QUEUECOMMAND
+void ultrastor_interrupt_service(void)
+{
+ if (ultrastor_done == 0) {
+ printk("US14F: unexpected ultrastor interrupt\n\r");
+ /* ??? Anything else we should do here? Reset? */
+ return;
+ }
+ printk("US14F: got an ultrastor interrupt: %u\n\r",
+ (mscp.adapter_status << 16) | mscp.target_status);
+ ultrastor_done(host_number,
+ (mscp.adapter_status << 16) | mscp.target_status);
+ ultrastor_done = 0;
+}
+
+__asm__("
+_ultrastor_interrupt:
+ cld
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ push %ds
+ push %es
+ push %fs
+ movl $0x10,%eax
+ mov %ax,%ds
+ mov %ax,%es
+ movl $0x17,%eax
+ mov %ax,%fs
+ movb $0x20,%al
+ outb %al,$0xA0 # EOI to interrupt controller #1
+ outb %al,$0x80 # give port chance to breathe
+ outb %al,$0x80
+ outb %al,$0x80
+ outb %al,$0x80
+ outb %al,$0x20
+ call _ultrastor_interrupt_service
+ pop %fs
+ pop %es
+ pop %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ iret
+");
+#endif
+
#endif
diff --git a/kernel/blk_drv/scsi/ultrastor.h b/kernel/blk_drv/scsi/ultrastor.h
index 13ded23..dfe34ee 100644
--- a/kernel/blk_drv/scsi/ultrastor.h
+++ b/kernel/blk_drv/scsi/ultrastor.h
@@ -9,10 +9,6 @@
#ifndef _ULTRASTOR_H
#define _ULTRASTOR_H
-/* ??? Some of the stuff in this file is really private to ultrastor.c and
- should be moved elsewhere (as this file is included by higher-level driver
- files). */
-
/* ??? These don't really belong here */
#ifndef TRUE
# define TRUE 1
@@ -21,32 +17,40 @@
# define FALSE 0
#endif
+/* ??? This should go eventually, once the queueing bug is fixed */
+#define USE_QUEUECOMMAND FALSE
+
int ultrastor_14f_detect(int);
const char *ultrastor_14f_info(void);
-#if 0 /* ??? Future direction... */
int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
void *buff, int bufflen,
void (*done)(int, int));
-#else
+#if !USE_QUEUECOMMAND
int ultrastor_14f_command(unsigned char target, const void *cmnd,
void *buff, int bufflen);
#endif
int ultrastor_14f_abort(int);
int ultrastor_14f_reset(void);
-#if 0 /* ??? Future direction... */
-# define ULTRASTOR_14F \
- { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
- ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
- TRUE, 0, 0 }
-#else
-# define ULTRASTOR_14F \
+#if !USE_QUEUECOMMAND
+#define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
FALSE, 0, 0 }
+#else
+#define ULTRASTOR_14F \
+ { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
+ ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
+ TRUE, 0, 0 }
#endif
-#define PORT_OVERRIDE 0x330
+#define UD_DETECT 0x1
+#define UD_COMMAND 0x2
+#define UD_RESET 0x4
+
+#ifdef ULTRASTOR_PRIVATE
+
+/* #define PORT_OVERRIDE 0x330 */
/* Port addresses (relative to the base address) */
#define LCL_DOORBELL_MASK(port) ((port) + 0x0)
@@ -82,3 +86,5 @@ int ultrastor_14f_reset(void);
#define HA_CMD_WRITE_BUFF 0x4
#endif
+
+#endif
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index 8709a22..746692c 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -883,6 +883,8 @@ void con_init(void)
char *display_ptr;
int currcons = 0;
long base;
+ int orig_x = ORIG_X;
+ int orig_y = ORIG_Y;
video_num_columns = ORIG_VIDEO_COLS;
video_size_row = video_num_columns * 2;
@@ -975,7 +977,7 @@ void con_init(void)
vt_cons[0].vt_mode = KD_TEXT;
vc_cons[0].vc_bold_attr = -1;
- gotoxy(currcons,ORIG_X,ORIG_Y);
+ gotoxy(currcons,orig_x,orig_y);
for (currcons = 1; currcons<NR_CONSOLES; currcons++) {
vc_cons[currcons] = vc_cons[0];
vt_cons[currcons] = vt_cons[0];
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index 1398059..82f711d 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -1012,7 +1012,7 @@ void kb_ack(void)
int i;
for(i=0; i<0x10000; i++)
- if (inb(0x64) == 0xfa)
+ if (inb(0x60) == 0xfa)
break;
}
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 413ee86..e5cb171 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -25,6 +25,9 @@
#include <asm/segment.h>
#include <asm/system.h>
+#include <sys/kd.h>
+#include "vt_kern.h"
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -65,6 +68,8 @@ struct tty_queue * table_list[]={
void change_console(unsigned int new_console)
{
+ if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
+ return;
if (new_console == fg_console || new_console >= NR_CONSOLES)
return;
table_list[0] = con_queues + 0 + new_console*3;
@@ -124,9 +129,14 @@ void copy_to_cooked(struct tty_struct * tty)
((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
(c==EOF_CHAR(tty))))) {
if (L_ECHO(tty)) {
- if (c<32)
- PUTCH(127,tty->write_q);
- PUTCH(127,tty->write_q);
+ if (c<32) {
+ PUTCH(8,tty->write_q);
+ PUTCH(' ',tty->write_q);
+ PUTCH(8,tty->write_q);
+ }
+ PUTCH(8,tty->write_q);
+ PUTCH(' ',tty->write_q);
+ PUTCH(8,tty->write_q);
TTY_WRITE_FLUSH(tty);
}
DEC(tty->secondary->head);
@@ -141,9 +151,14 @@ void copy_to_cooked(struct tty_struct * tty)
(c==EOF_CHAR(tty))))
continue;
if (L_ECHO(tty)) {
- if (c<32)
- PUTCH(127,tty->write_q);
- PUTCH(127,tty->write_q);
+ if (c<32) {
+ PUTCH(8,tty->write_q);
+ PUTCH(' ',tty->write_q);
+ PUTCH(8,tty->write_q);
+ }
+ PUTCH(8,tty->write_q);
+ PUTCH(32,tty->write_q);
+ PUTCH(8,tty->write_q);
TTY_WRITE_FLUSH(tty);
}
DEC(tty->secondary->head);
diff --git a/kernel/fork.c b/kernel/fork.c
index 8a0dbe8..784cbad 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -116,7 +116,8 @@ int sys_fork(long ebx,long ecx,long edx,
current->p_cptr = p;
p->counter = p->priority;
p->signal = 0;
- p->alarm = 0;
+ p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
+ p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
diff --git a/kernel/itimer.c b/kernel/itimer.c
new file mode 100644
index 0000000..7362dc8
--- /dev/null
+++ b/kernel/itimer.c
@@ -0,0 +1,111 @@
+/*
+ * linux/kernel/itimer.c
+ *
+ * (C) 1992 Darren Senn
+ */
+
+/* These are all the functions necessary to implement itimers */
+
+#include <linux/sched.h>
+#include <asm/segment.h>
+
+#include <signal.h>
+#include <sys/time.h>
+#include <errno.h>
+
+static unsigned long tvtojiffies(struct timeval *value)
+{
+ return((unsigned long )value->tv_sec * HZ +
+ (unsigned long )value->tv_usec / (1000000 / HZ));
+}
+
+static void jiffiestotv(unsigned long jiffies, struct timeval *value)
+{
+ value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
+ value->tv_sec = jiffies / HZ;
+ return;
+}
+
+int _getitimer(int which, struct itimerval *value)
+{
+ register unsigned long val, interval;
+
+ switch (which) {
+ case ITIMER_REAL:
+ val = current->it_real_value;
+ interval = current->it_real_incr;
+ break;
+ case ITIMER_VIRTUAL:
+ val = current->it_virt_value;
+ interval = current->it_virt_incr;
+ break;
+ case ITIMER_PROF:
+ val = current->it_prof_value;
+ interval = current->it_prof_incr;
+ break;
+ default:
+ return(-EINVAL);
+ }
+ jiffiestotv(val, &value->it_value);
+ jiffiestotv(interval, &value->it_interval);
+ return(0);
+}
+
+int sys_getitimer(int which, struct itimerval *value)
+{
+ struct itimerval get_buffer;
+ int k;
+
+ if (!value)
+ return -EFAULT;
+ k = _getitimer(which, &get_buffer);
+ if (k < 0)
+ return k;
+ verify_area(value, sizeof(struct itimerval));
+ memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
+ return 0;
+}
+
+int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+{
+ register unsigned long i, j;
+ int k;
+
+ i = tvtojiffies(&value->it_interval);
+ j = tvtojiffies(&value->it_value);
+ if (ovalue && (k = _getitimer(which, ovalue)) < 0)
+ return k;
+ switch (which) {
+ case ITIMER_REAL:
+ current->it_real_value = j;
+ current->it_real_incr = i;
+ break;
+ case ITIMER_VIRTUAL:
+ current->it_virt_value = j;
+ current->it_virt_incr = i;
+ break;
+ case ITIMER_PROF:
+ current->it_prof_value = j;
+ current->it_prof_incr = i;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+{
+ struct itimerval set_buffer, get_buffer;
+ int k;
+
+ if (!value)
+ return -EFAULT;
+ memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
+ k = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
+ if (k < 0 || !ovalue)
+ return k;
+ verify_area(ovalue, sizeof(struct itimerval));
+ memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
+ return 0;
+}
diff --git a/kernel/math/ea.c b/kernel/math/ea.c
index 85a1131..c4a219b 100644
--- a/kernel/math/ea.c
+++ b/kernel/math/ea.c
@@ -58,7 +58,7 @@ static char * sib(struct info * info, int mod)
char * ea(struct info * info, unsigned short code)
{
unsigned char mod,rm;
- long * tmp = &EAX;
+ long * tmp;
int offset = 0;
mod = (code >> 6) & 3;
diff --git a/kernel/sched.c b/kernel/sched.c
index 01d04a9..2d960bb 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -18,6 +18,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
+#include <sys/time.h>
#include <signal.h>
#include <errno.h>
@@ -68,7 +69,7 @@ union task_union {
char stack[PAGE_SIZE];
};
-static union task_union init_task = {INIT_TASK,};
+static union task_union init_task = {INIT_TASK, };
unsigned long volatile jiffies=0;
unsigned long startup_time=0;
@@ -134,10 +135,6 @@ void schedule(void)
(*p)->timeout = 0;
(*p)->state = TASK_RUNNING;
}
- if ((*p)->alarm && (*p)->alarm < jiffies) {
- (*p)->signal |= (1<<(SIGALRM-1));
- (*p)->alarm = 0;
- }
if (((*p)->signal & ~(*p)->blocked) &&
(*p)->state==TASK_INTERRUPTIBLE)
(*p)->state=TASK_RUNNING;
@@ -352,7 +349,7 @@ static unsigned long cexp[3] = {
2014, /* 0.9834714538216174 * FSCALE, exp(-1/60) */
2037, /* 0.9944598480048967 * FSCALE, exp(-1/180) */
};
-unsigned long averunnable[3]; /* fixed point numbers */
+unsigned long averunnable[3] = { 0, }; /* fixed point numbers */
void update_avg(void)
{
@@ -376,7 +373,8 @@ void do_timer(long cpl)
{
unsigned long mask;
struct timer_struct *tp = timer_table+0;
- static int avg_cnt;
+ struct task_struct ** task_p;
+ static int avg_cnt = 0;
for (mask = 1 ; mask ; tp++,mask += mask) {
if (mask > timer_active)
@@ -390,6 +388,25 @@ void do_timer(long cpl)
sti();
}
+ /* Update ITIMER_REAL for every task */
+ for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
+ if (*task_p && (*task_p)->it_real_value
+ && !(--(*task_p)->it_real_value)) {
+ (*task_p)->signal |= (1<<(SIGALRM-1));
+ (*task_p)->it_real_value = (*task_p)->it_real_incr;
+ need_resched = 1;
+ }
+ /* Update ITIMER_PROF for the current task */
+ if (current->it_prof_value && !(--current->it_prof_value)) {
+ current->it_prof_value = current->it_prof_incr;
+ current->signal |= (1<<(SIGPROF-1));
+ }
+ /* Update ITIMER_VIRT for current task if not in a system call */
+ if (cpl && current->it_virt_value && !(--current->it_virt_value)) {
+ current->it_virt_value = current->it_virt_incr;
+ current->signal |= (1<<(SIGVTALRM-1));
+ }
+
if (cpl)
current->utime++;
else
@@ -420,12 +437,14 @@ void do_timer(long cpl)
int sys_alarm(long seconds)
{
- int old = current->alarm;
-
- if (old)
- old = (old - jiffies) / HZ;
- current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
- return (old);
+ extern int _setitimer(int, struct itimerval *, struct itimerval *);
+ struct itimerval new, old;
+
+ new.it_interval.tv_sec = new.it_interval.tv_usec = 0;
+ new.it_value.tv_sec = seconds;
+ new.it_value.tv_usec = 0;
+ _setitimer(ITIMER_REAL, &new, &old);
+ return(old.it_value.tv_sec + (old.it_value.tv_usec / 1000000));
}
int sys_getpid(void)
diff --git a/kernel/signal.c b/kernel/signal.c
index d1d5afd..77dd96d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -10,8 +10,11 @@
#include <signal.h>
#include <sys/wait.h>
+#include <sys/ptrace.h>
#include <errno.h>
+extern int core_dump(long signr,struct pt_regs * regs);
+
int sys_sgetmask()
{
return current->blocked;
@@ -117,44 +120,29 @@ int sys_sigaction(int signum, const struct sigaction * action,
return 0;
}
-/*
- * Routine writes a core dump image in the current directory.
- * Currently not implemented.
- */
-int core_dump(long signr)
-{
- return(0); /* We didn't do a dump */
-}
-
extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
-int do_signal(long signr,long ebx, long ecx, long edx,
- long esi, long edi, long ebp, long eax,
- long ds, long es, long fs, long gs,
- long orig_eax,
- long eip, long cs, long eflags,
- unsigned long * esp, long ss)
+int do_signal(long signr,struct pt_regs * regs)
{
unsigned long sa_handler;
- long old_eip=eip;
+ long old_eip = regs->eip;
struct sigaction * sa = current->sigaction + signr - 1;
int longs;
-
unsigned long * tmp_esp;
#ifdef notdef
printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
- current->pid, signr, eax, orig_eax,
+ current->pid, signr, regs->eax, regs->orig_eax,
sa->sa_flags & SA_INTERRUPT);
#endif
- if ((orig_eax != -1) &&
- ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {
- if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
+ if ((regs->orig_eax != -1) &&
+ ((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
+ if ((regs->eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
signr < SIGCONT || signr > SIGTTOU))
- *(&eax) = -EINTR;
+ regs->eax = -EINTR;
else {
- *(&eax) = orig_eax;
- *(&eip) = old_eip -= 2;
+ regs->eax = regs->orig_eax;
+ regs->eip = old_eip -= 2;
}
}
sa_handler = (unsigned long) sa->sa_handler;
@@ -191,7 +179,7 @@ int do_signal(long signr,long ebx, long ecx, long edx,
case SIGIOT:
case SIGFPE:
case SIGSEGV:
- if (core_dump(signr))
+ if (core_dump(signr,regs))
do_exit(signr|0x80);
/* fall through */
default:
@@ -203,19 +191,19 @@ int do_signal(long signr,long ebx, long ecx, long edx,
*/
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- *(&eip) = sa_handler;
- longs = (sa->sa_flags & SA_NOMASK)?7:8;
- *(&esp) -= longs;
- verify_area(esp,longs*4);
- tmp_esp=esp;
+ regs->eip = sa_handler;
+ longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
+ regs->esp -= longs;
+ tmp_esp = (unsigned long *) regs->esp;
+ verify_area(tmp_esp,longs);
put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++);
- put_fs_long(eax,tmp_esp++);
- put_fs_long(ecx,tmp_esp++);
- put_fs_long(edx,tmp_esp++);
- put_fs_long(eflags,tmp_esp++);
+ put_fs_long(regs->eax,tmp_esp++);
+ put_fs_long(regs->ecx,tmp_esp++);
+ put_fs_long(regs->edx,tmp_esp++);
+ put_fs_long(regs->eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask;
/* force a supervisor-mode page-in of the signal handler to reduce races */
diff --git a/kernel/sys.c b/kernel/sys.c
index 2318a7e..75a86ba 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -180,14 +180,14 @@ void ctrl_alt_del(void)
*/
int sys_setregid(int rgid, int egid)
{
- if (rgid>0) {
+ if (rgid >= 0) {
if ((current->gid == rgid) ||
suser())
current->gid = rgid;
else
return(-EPERM);
}
- if (egid>0) {
+ if (egid >= 0) {
if ((current->gid == egid) ||
(current->egid == egid) ||
suser()) {
@@ -267,17 +267,17 @@ int sys_setreuid(int ruid, int euid)
{
int old_ruid = current->uid;
- if (ruid>0) {
+ if (ruid >= 0) {
if ((current->euid==ruid) ||
- (old_ruid == ruid) ||
+ (old_ruid == ruid) ||
suser())
current->uid = ruid;
else
return(-EPERM);
}
- if (euid>0) {
+ if (euid >= 0) {
if ((old_ruid == euid) ||
- (current->euid == euid) ||
+ (current->euid == euid) ||
suser()) {
current->euid = euid;
current->suid = euid;
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
index ad70318..41014da 100644
--- a/kernel/sys_call.S
+++ b/kernel/sys_call.S
@@ -187,10 +187,13 @@ ret_from_sys_call:
je 2f
btrl %ecx,%ebx
movl %ebx,signal(%eax)
+ movl %esp,%ebx
+ pushl %ebx
incl %ecx
pushl %ecx
call _do_signal
popl %ecx
+ popl %ebx
testl %eax, %eax
jne 1b # see if we need to switch tasks, or do more signals
2: popl %ebx
diff --git a/lib/Makefile b/lib/Makefile
index 94b649f..e58abc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,7 +23,7 @@ CPP =gcc -E -nostdinc -I../include
-c -o $*.o $<
OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
- execve.o wait.o string.o malloc.o
+ execve.o wait.o string.o malloc.o itimer.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/tools/build.c b/tools/build.c
index 1fa477b..e3a8a73 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -81,7 +81,7 @@ int main(int argc, char ** argv)
}
fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
if ((major_root != 2) && (major_root != 3) &&
- (major_root != 0)) {
+ (major_root != 8) && (major_root != 0)) {
fprintf(stderr, "Illegal root device (major = %d)\n",
major_root);
die("Bad root device --- major #");