aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1993-01-01 22:38:37 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:11 -0400
commit533790deaad93ea1eacf12b7831c42ff0bb45a61 (patch)
tree1b178ed40798bc683f26508a98ea709c3589e00f
parentd99dedeec6209a2772ff0525eea13509181b9a2c (diff)
downloadarchive-533790deaad93ea1eacf12b7831c42ff0bb45a61.tar.gz
linux-0.99 patchlevel 2v0.99-pl2
Yes, as you've probably noticed, it's now 1993 and I still haven't released 1.0. Sorry about that, and I have only another patchlevel to offer. The new kernel should mainly fix some of the keyboard problems people have experienced, but does contain some other minor fixes. Linux 0.99.2 is available now at nic.funet.fi: pub/OS/Linux/PEOPLE/Linus as both sources and diffs against 0.99.1 the diffs are essentially the same as the second alpha-diffs I released for limited testing, with only minor fixes to fs/exec.c and fs/open.c. Please try out 0.99.2: the more feedback (hopefully positive) I get on it, the faster 1.0 will be out. Changes from pl1 are mainly: - pretty much rewritten low-level keyboard handling IO - this time actually trying to do it by the book. It now handles resend requests from the keyboard etc. - you can run executables from filesystems without bmap support. This mainly means NFS and msdos. Note that while it's possible, it's slower and less memory-efficient than using a "normal" linux filesystem, and should generally be avoided. - /proc filesystem changes: /proc/kmsg can be used to log the kernel messages under X11 (instead of using the older system call to do the same), and there are changes to the statistics routines (WCHAN). + various minor fixes (non-existent devices are handled better, some changes to socket bind behaviour etc). Linus
-rw-r--r--Makefile7
-rw-r--r--boot/head.S21
-rw-r--r--boot/setup.S41
-rw-r--r--config.in4
-rw-r--r--fs/exec.c128
-rw-r--r--fs/ext/blkdev.c10
-rw-r--r--fs/ext/chrdev.c10
-rw-r--r--fs/ext/file.c8
-rw-r--r--fs/ext/namei.c5
-rw-r--r--fs/isofs/blkdev.c10
-rw-r--r--fs/isofs/chrdev.c10
-rw-r--r--fs/minix/blkdev.c10
-rw-r--r--fs/minix/chrdev.c10
-rw-r--r--fs/minix/file.c6
-rw-r--r--fs/minix/namei.c5
-rw-r--r--fs/msdos/inode.c3
-rw-r--r--fs/msdos/namei.c2
-rw-r--r--fs/nfs/blkdev.c10
-rw-r--r--fs/nfs/chrdev.c10
-rw-r--r--fs/open.c4
-rw-r--r--fs/proc/Makefile2
-rw-r--r--fs/proc/array.c31
-rw-r--r--fs/proc/inode.c12
-rw-r--r--fs/proc/kmsg.c61
-rw-r--r--fs/proc/root.c5
-rw-r--r--fs/select.c4
-rw-r--r--include/asm/irq.h10
-rw-r--r--include/asm/system.h13
-rw-r--r--include/linux/autoconf.h33
-rw-r--r--include/linux/config.h2
-rw-r--r--include/linux/config_rel.h1
-rw-r--r--include/linux/config_ver.h1
-rw-r--r--include/linux/interrupt.h8
-rw-r--r--include/linux/lp.h13
-rw-r--r--include/linux/minix_fs.h32
-rw-r--r--include/linux/proc_fs.h1
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/types.h2
-rw-r--r--init/main.c6
-rw-r--r--kernel/FPU-emu/get_address.c2
-rw-r--r--kernel/blk_drv/scsi/scsi.c5
-rw-r--r--kernel/blk_drv/scsi/sd.c4
-rw-r--r--kernel/blk_drv/scsi/seagate.c29
-rw-r--r--kernel/blk_drv/scsi/seagate.h3
-rw-r--r--kernel/blk_drv/scsi/sr.c4
-rw-r--r--kernel/blk_drv/scsi/st.c4
-rw-r--r--kernel/blk_drv/scsi/wd7000.c17
-rw-r--r--kernel/chr_drv/keyboard.c186
-rw-r--r--kernel/chr_drv/sound/sound_stub.c4
-rw-r--r--kernel/chr_drv/tty_io.c2
-rw-r--r--kernel/chr_drv/tty_ioctl.c31
-rw-r--r--kernel/irq.c94
-rw-r--r--kernel/sched.c4
-rw-r--r--kernel/sys_call.S9
-rw-r--r--net/tcp/dev.c2
-rw-r--r--net/unix.c58
-rw-r--r--tools/build.c39
57 files changed, 628 insertions, 422 deletions
diff --git a/Makefile b/Makefile
index d740d50..4fe2894 100644
--- a/Makefile
+++ b/Makefile
@@ -66,7 +66,7 @@ SVGA_MODE= -DSVGA_MODE=1
# You should use one of the values 4096 (SB), 16384 (SB Pro), 32768 (PAS+)
# or 65536 (PAS16). The SBC_IRQ defines the IRQ line used by SoundBlaster and
# the PAS_IRQ is the IRQ number for ProAudioSpectrum.
-# NOTE! The ProAudioSpectrum support is not available yet.
+#
SOUND_SUPPORT = -DKERNEL_SOUNDCARD -DDSP_BUFFSIZE=16384 -DSBC_IRQ=7 -DPAS_IRQ=5
@@ -97,6 +97,7 @@ CC =gcc -DKERNEL
MAKE =make
CPP =$(CC) -E
AR =ar
+STRIP =strip
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o
FILESYSTEMS =fs/filesystems.a
@@ -141,7 +142,7 @@ linuxsubdirs: dummy
Version: dummy
@./makever.sh
- @echo \#define UTS_RELEASE \"0.99.pl1-`cat .version`\" > tools/version.h
+ @echo \#define UTS_RELEASE \"0.99.pl2-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@@ -149,7 +150,7 @@ Version: dummy
Image: $(CONFIGURATION) boot/bootsect boot/setup tools/system tools/build
cp tools/system system.tmp
- strip system.tmp
+ $(STRIP) system.tmp
tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
rm system.tmp
sync
diff --git a/boot/head.S b/boot/head.S
index 63812b2..7497241 100644
--- a/boot/head.S
+++ b/boot/head.S
@@ -35,7 +35,19 @@ startup_32:
movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
je 1b
+/*
+ * Initialize eflags. Some BIOS's leave bits like NT set. This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+ pushl $0
+ popfl
/* check if it is 486 or 386. */
+/*
+ * XXX - this does a lot of unnecessary setup. Alignment checks don't
+ * apply at our cpl of 0 and the stack ought to be aligned already, and
+ * we don't need to preserve eflags.
+ */
movl %esp,%edi # save stack pointer
andl $0xfffffffc,%esp # align stack to avoid AC fault
pushfl # push EFLAGS
@@ -46,8 +58,9 @@ startup_32:
popfl # set EFLAGS
pushfl # get new EFLAGS
popl %eax # put it in eax
- xorl %ecx,%eax # check if AC bit is changed. zero is 486.
- jz 1f # 486
+ xorl %ecx,%eax # change in flags
+ andl $0x40000,%eax # check if AC bit changed
+ jnz 1f # 486
pushl %ecx # restore original EFLAGS
popfl
movl %edi,%esp # restore esp
@@ -60,13 +73,15 @@ startup_32:
* mode. Then it would be unnecessary with the "verify_area()"-calls.
* 486 users probably want to set the NE (#5) bit also, so as to use
* int 16 for math errors.
+ * XXX - the above is out of date. We set all the bits, but don't take
+ * advantage of WP (26 Dec 92).
*/
1: pushl %ecx # restore original EFLAGS
popfl
movl %edi,%esp # restore esp
movl %cr0,%eax # 486
andl $0x80000011,%eax # Save PG,PE,ET
- orl $0x10022,%eax # set NE and MP
+ orl $0x50022,%eax # set AM, WP, NE and MP
2: movl %eax,%cr0
call check_x87
call setup_paging
diff --git a/boot/setup.S b/boot/setup.S
index 194ca1b..0fa8efc 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -253,17 +253,15 @@ no_output:
getkey:
in al,#0x60 ! Quick and dirty...
.word 0x00eb,0x00eb ! jmp $+2, jmp $+2
- mov bl,al
- in al,#0x61
- .word 0x00eb,0x00eb
- mov ah,al
- or al,#0x80
- out #0x61,al
- .word 0x00eb,0x00eb
- mov al,ah
- out #0x61,al
+ ret
+
+!
+! Flush the keyboard buffer
+!
+flush: in al,#0x60
.word 0x00eb,0x00eb
- mov al,bl
+ cmp al,#0x82
+ jae flush
ret
! Routine trying to recognize type of SVGA-board present (if any)
@@ -287,11 +285,8 @@ chsvga: cld
jne svga
lea si,msg1
call prtstr
-flush: in al,#0x60 ! Flush the keyboard buffer
- cmp al,#0x82
- jb nokey
- jmp flush
-nokey: call getkey
+ call flush
+nokey: call getkey
cmp al,#0x9c ! enter ?
je svga ! yes - svga selection
cmp al,#0xb9 ! space ?
@@ -317,7 +312,18 @@ extvga:
mov ax,#0x5032 ! return 80x50
ret
/* svga modes */
-svga: cld
+svga: cld
+ lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk)
+ mov di,#0x10a ! id string is at c000:010a
+ mov cx,#0x21 ! length
+ repe
+ cmpsb
+ jne nf1280
+ lea si,dscf1280
+ lea di,mof1280
+ lea cx,selmod
+ jmp cx
+nf1280: cld
lea si,idati ! Check ATI 'clues'
mov di,#0x31
mov cx,#0x09
@@ -701,6 +707,7 @@ idcandt: .byte 0xa5
idgenoa: .byte 0x77, 0x00, 0x66, 0x99
idparadise: .ascii "VGA="
idoakvga: .ascii "OAK VGA "
+idf1280: .ascii "Orchid Technology Fahrenheit 1280"
! Manufacturer: Numofmodes: Mode:
@@ -715,6 +722,7 @@ motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51
+mof1280: .byte 0x02, 0x54, 0x55
! msb = Cols lsb = Rows:
@@ -729,6 +737,7 @@ dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C
+dscf1280: .word 0x842b, 0x8419
modesave: .word SVGA_MODE
.text
diff --git a/config.in b/config.in
index 0514139..12c8abc 100644
--- a/config.in
+++ b/config.in
@@ -33,8 +33,6 @@ Adaptec AHA1542 support
CONFIG_SCSI_AHA1542 y/n y
Adaptec AHA1740 support
CONFIG_SCSI_AHA1740 y/n y
-Always IN support
-CONFIG_SCSI_ALWAYS y/n y
Future Domain SCSI support
CONFIG_SCSI_FUTURE_DOMAIN y/n y
Seagate ST-02 SCSI support
@@ -62,7 +60,7 @@ CONFIG_ISO9660_FS y/n n
Various character device drivers..
.
Autoconfigure serial IRQ lines at bootup
-CONFIG_AUTOIRQ y/n n
+CONFIG_AUTO_IRQ y/n n
AST Fourport serial driver support
CONFIG_AST_FOURPORT y/n n
Accent Async 4 serial support
diff --git a/fs/exec.c b/fs/exec.c
index 2942228..1350142 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -194,6 +194,10 @@ int sys_uselib(const char * library)
iput(inode);
return -EACCES;
}
+ if (!inode->i_op || !inode->i_op->bmap) {
+ iput(inode);
+ return -ENOEXEC;
+ }
if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
iput(inode);
return -EACCES;
@@ -365,35 +369,42 @@ static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
return data_limit;
}
-static void read_omagic(struct inode *inode, int bytes)
+/*
+ * Read in the complete executable. This is used for "-N" files
+ * that aren't on a block boundary, and for files on filesystems
+ * without bmap support.
+ */
+static int read_exec(struct inode *inode, unsigned long offset,
+ char * addr, unsigned long count)
{
- struct buffer_head *bh;
- int n, blkno, blk = 0;
- char *dest = (char *) 0;
- unsigned int block_size;
+ struct file file;
+ int result = -ENOEXEC;
- block_size = 1024;
- if (inode->i_sb)
- block_size = inode->i_sb->s_blocksize;
- while (bytes > 0) {
- n = (blk ? block_size : block_size - sizeof(struct exec));
- if (bytes < n)
- n = bytes;
- blkno = bmap(inode, blk);
- if (blkno) {
- bh = bread(inode->i_dev, blkno, block_size);
- if (!bh)
- sys_exit(-1);
- memcpy_tofs(dest, (blk ? bh->b_data :
- bh->b_data + sizeof(struct exec)), n);
- brelse(bh);
- }
- ++blk;
- dest += n;
- bytes -= n;
- }
- iput(inode);
- current->executable = NULL;
+ if (!inode->i_op || !inode->i_op->default_file_ops)
+ goto end_readexec;
+ file.f_mode = 1;
+ 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_readexec;
+ if (!file.f_op || !file.f_op->read)
+ goto close_readexec;
+ if (file.f_op->lseek) {
+ if (file.f_op->lseek(inode,&file,offset,0) != offset)
+ goto close_readexec;
+ } else
+ file.f_pos = offset;
+ result = file.f_op->read(inode, &file, addr, count);
+close_readexec:
+ if (file.f_op->release)
+ file.f_op->release(inode,&file);
+end_readexec:
+ return result;
}
/*
@@ -406,7 +417,8 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
char ** argv, char ** envp)
{
struct inode * inode;
- struct buffer_head * bh;
+ char buf[128];
+ unsigned long old_fs;
struct exec ex;
unsigned long page[MAX_ARG_PAGES];
int i,argc,envc;
@@ -463,32 +475,35 @@ restart_interp:
retval = -EACCES;
goto exec_error2;
}
- if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
- retval = -EACCES;
+ memset(buf,0,sizeof(buf));
+ old_fs = get_fs();
+ set_fs(get_ds());
+ retval = read_exec(inode,0,buf,128);
+ set_fs(old_fs);
+ if (retval < 0)
goto exec_error2;
- }
- if (!IS_RDONLY(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- ex = *((struct exec *) bh->b_data); /* read exec-header */
- if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
+ ex = *((struct exec *) buf); /* exec-header */
+ if ((buf[0] == '#') && (buf[1] == '!') && (!sh_bang)) {
/*
* This section does the #! interpretation.
* Sorta complicated, but hopefully it will work. -TYT
*/
- char buf[128], *cp, *interp, *i_name, *i_arg;
- unsigned long old_fs;
+ char *cp, *interp, *i_name, *i_arg;
- strncpy(buf, bh->b_data+2, 127);
- brelse(bh);
iput(inode);
buf[127] = '\0';
- if ((cp = strchr(buf, '\n')) != NULL) {
- *cp = '\0';
- for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
+ if ((cp = strchr(buf, '\n')) == NULL)
+ cp = buf+127;
+ *cp = '\0';
+ while (cp > buf) {
+ cp--;
+ if ((*cp == ' ') || (*cp == '\t'))
+ *cp = '\0';
+ else
+ break;
}
+ for (cp = buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
if (!cp || *cp == '\0') {
retval = -ENOEXEC; /* No interpreter name found */
goto exec_error1;
@@ -499,10 +514,10 @@ restart_interp:
if (*cp == '/')
i_name = cp+1;
}
- if (*cp) {
+ while ((*cp == ' ') || (*cp == '\t'))
*cp++ = '\0';
+ if (*cp)
i_arg = cp;
- }
/*
* OK, we've parsed out the interpreter name and
* (optional) argument.
@@ -542,7 +557,6 @@ restart_interp:
goto exec_error1;
goto restart_interp;
}
- brelse(bh);
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
ex.a_trsize || ex.a_drsize ||
ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
@@ -569,12 +583,13 @@ restart_interp:
if (ch == '/')
i = 0;
else
- if (i < 8)
+ if (i < 15)
current->comm[i++] = ch;
- if (i < 8)
- current->comm[i] = '\0';
- if (current->executable)
+ current->comm[i] = '\0';
+ if (current->executable) {
iput(current->executable);
+ current->executable = NULL;
+ }
i = current->numlibraries;
while (i-- > 0) {
iput(current->libraries[i].library);
@@ -584,7 +599,6 @@ restart_interp:
!permission(inode,MAY_READ))
current->dumpable = 0;
current->numlibraries = 0;
- current->executable = inode;
current->signal = 0;
for (i=0 ; i<32 ; i++) {
current->sigaction[i].sa_mask = 0;
@@ -610,8 +624,14 @@ restart_interp:
current->rss = (TASK_SIZE - p + PAGE_SIZE-1) / PAGE_SIZE;
current->suid = current->euid = e_uid;
current->sgid = current->egid = e_gid;
- if (N_MAGIC(ex) == OMAGIC)
- read_omagic(inode, ex.a_text+ex.a_data);
+ if (N_MAGIC(ex) == OMAGIC) {
+ read_exec(inode, 32, (char *) 0, ex.a_text+ex.a_data);
+ iput(inode);
+ } else if (!inode->i_op || !inode->i_op->bmap) {
+ read_exec(inode, 1024, (char *) 0, ex.a_text+ex.a_data);
+ iput(inode);
+ } else
+ current->executable = inode;
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
diff --git a/fs/ext/blkdev.c b/fs/ext/blkdev.c
index 031678a..381e44d 100644
--- a/fs/ext/blkdev.c
+++ b/fs/ext/blkdev.c
@@ -25,11 +25,11 @@ static int blkdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ return -ENODEV;
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/ext/chrdev.c b/fs/ext/chrdev.c
index 5d31e39..44976a0 100644
--- a/fs/ext/chrdev.c
+++ b/fs/ext/chrdev.c
@@ -25,11 +25,11 @@ static int chrdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ return -ENODEV;
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/ext/file.c b/fs/ext/file.c
index bb70d50..b86ce20 100644
--- a/fs/ext/file.c
+++ b/fs/ext/file.c
@@ -118,14 +118,14 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
buffers and caches. */
do {
- bhrequest = 0;
- uptodate = 1;
+ bhrequest = 0;
+ uptodate = 1;
while (blocks) {
--blocks;
*bhb = ext_getblk(inode, block++, 0);
if (*bhb && !(*bhb)->b_uptodate) {
- uptodate = 0;
- bhreq[bhrequest++] = *bhb;
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
}
if (++bhb == &buflist[NBUF])
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index b094fbe..bfb0171 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -808,6 +808,11 @@ start_up:
retval = -EEXIST;
goto end_rename;
}
+ retval = -EPERM;
+ if (new_inode && (new_dir->i_mode & S_ISVTX) &&
+ current->euid != new_inode->i_uid &&
+ current->euid != new_dir->i_uid && !suser())
+ goto end_rename;
if (S_ISDIR(old_inode->i_mode)) {
retval = -EEXIST;
if (new_bh)
diff --git a/fs/isofs/blkdev.c b/fs/isofs/blkdev.c
index 7b93d74..04934c7 100644
--- a/fs/isofs/blkdev.c
+++ b/fs/isofs/blkdev.c
@@ -24,11 +24,11 @@ static int blkdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ return -ENODEV;
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/isofs/chrdev.c b/fs/isofs/chrdev.c
index fc69b12..868690d 100644
--- a/fs/isofs/chrdev.c
+++ b/fs/isofs/chrdev.c
@@ -24,11 +24,11 @@ static int chrdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ return -ENODEV;
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/minix/blkdev.c b/fs/minix/blkdev.c
index 061fc5c..73fa71a 100644
--- a/fs/minix/blkdev.c
+++ b/fs/minix/blkdev.c
@@ -19,11 +19,11 @@ static int blkdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ return -ENODEV;
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/minix/chrdev.c b/fs/minix/chrdev.c
index 6f5e9d6..1e791e6 100644
--- a/fs/minix/chrdev.c
+++ b/fs/minix/chrdev.c
@@ -19,11 +19,11 @@ static int chrdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ return -ENODEV;
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 9643009..8273931 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -113,13 +113,13 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
do {
bhrequest = 0;
- uptodate = 1;
+ uptodate = 1;
while (blocks) {
--blocks;
*bhb = minix_getblk(inode, block++, 0);
if (*bhb && !(*bhb)->b_uptodate) {
- uptodate = 0;
- bhreq[bhrequest++] = *bhb;
+ uptodate = 0;
+ bhreq[bhrequest++] = *bhb;
}
if (++bhb == &buflist[NBUF])
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index ec6cb63..c2ba87f 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -683,6 +683,11 @@ start_up:
retval = -EEXIST;
goto end_rename;
}
+ retval = -EPERM;
+ if (new_inode && (new_dir->i_mode & S_ISVTX) &&
+ current->euid != new_inode->i_uid &&
+ current->euid != new_dir->i_uid && !suser())
+ goto end_rename;
if (S_ISDIR(old_inode->i_mode)) {
retval = -EEXIST;
if (new_bh)
diff --git a/fs/msdos/inode.c b/fs/msdos/inode.c
index 346c1f2..bd5b7d8 100644
--- a/fs/msdos/inode.c
+++ b/fs/msdos/inode.c
@@ -169,7 +169,6 @@ printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,se=%d,ts=%d]\n",
printk("Unsupported FS parameters\n");
return NULL;
}
- if (!MSDOS_CAN_BMAP(MSDOS_SB(s))) printk("No bmap support\n");
s->s_magic = MSDOS_SUPER_MAGIC;
MSDOS_SB(s)->name_check = check;
MSDOS_SB(s)->conversion = conversion;
@@ -266,7 +265,7 @@ void msdos_read_inode(struct inode *inode)
raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
[inode->i_ino & (MSDOS_DPB-1)];
if ((raw_entry->attr & ATTR_DIR) && *raw_entry->name && *(unsigned char *)
- raw_entry->name != DELETED_FLAG) {
+ raw_entry->name != DELETED_FLAG) {
inode->i_mode = MSDOS_MKMODE(raw_entry->attr,0777 &
~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR;
inode->i_op = &msdos_dir_inode_operations;
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 6fda997..e38a92c 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -226,7 +226,7 @@ static void dump_fat(struct super_block *sb,int start)
printk("[");
while (start) {
printk("%d ",start);
- start = fat_access(sb,start,-1);
+ start = fat_access(sb,start,-1);
if (!start) {
printk("ERROR");
break;
diff --git a/fs/nfs/blkdev.c b/fs/nfs/blkdev.c
index 7df82f6..6b4e0b4 100644
--- a/fs/nfs/blkdev.c
+++ b/fs/nfs/blkdev.c
@@ -19,11 +19,11 @@ static int blkdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ return -ENODEV;
+ filp->f_op = blkdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/nfs/chrdev.c b/fs/nfs/chrdev.c
index 458b4c7..f568bd1 100644
--- a/fs/nfs/chrdev.c
+++ b/fs/nfs/chrdev.c
@@ -19,11 +19,11 @@ static int chrdev_open(struct inode * inode, struct file * filp)
int i;
i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
+ if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ return -ENODEV;
+ filp->f_op = chrdev_fops[i];
+ if (filp->f_op->open)
+ return filp->f_op->open(inode,filp);
return 0;
}
diff --git a/fs/open.c b/fs/open.c
index 27a4981..174af7f 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -243,6 +243,8 @@ int sys_fchmod(unsigned int fd, mode_t mode)
if (IS_RDONLY(inode))
return -EROFS;
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
+ if (!suser() && !in_group_p(inode->i_gid))
+ inode->i_mode &= ~S_ISGID;
inode->i_dirt = 1;
return notify_change(inode);
}
@@ -264,6 +266,8 @@ int sys_chmod(const char * filename, mode_t mode)
return -EROFS;
}
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
+ if (!suser() && !in_group_p(inode->i_gid))
+ inode->i_mode &= ~S_ISGID;
inode->i_dirt = 1;
error = notify_change(inode);
iput(inode);
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 9af56d3..cc16676 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
-OBJS= inode.o root.o base.o mem.o link.o fd.o array.o
+OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o
proc.o: $(OBJS)
$(LD) -r -o proc.o $(OBJS)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f9e4b0e..5cd30ad 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -26,8 +26,6 @@
#define SSIZE(stack) (KSTK_ESP(stack) ? _SSIZE(stack) : 0)
#define VSIZE(task,stack) ((task)->brk + 1023 + SSIZE(stack))
-#define SIZE(task,stack) (((task)->brk - (task)->end_code + 1023 + \
- SSIZE(stack)) / 1024)
static int get_loadavg(char * buffer)
@@ -140,19 +138,42 @@ static int get_arg(int pid, char * buffer)
return get_array(p, (*p)->arg_start, (*p)->arg_end, buffer);
}
+static unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long ebp, eip;
+ unsigned long stack_page;
+ int count = 0;
+
+ if (!p || p == current)
+ return 0;
+ ebp = p->tss.ebp;
+ stack_page = p->kernel_stack_page;
+ do {
+ if (ebp < stack_page || ebp >= 4092+stack_page)
+ return 0;
+ eip = *(unsigned long *) (ebp+4);
+ if ((void *)eip != sleep_on &&
+ (void *)eip != interruptible_sleep_on)
+ return eip;
+ ebp = *(unsigned long *) ebp;
+ } while (count++ < 16);
+ return 0;
+}
+
static int get_stat(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
- unsigned long sigignore=0, sigcatch=0, bit=1;
+ unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
int i;
char state;
if (!p || !*p)
return 0;
- if ((*p)->state < 0)
+ if ((*p)->state < 0 || (*p)->state > 5)
state = '.';
else
state = "RSDZTD"[(*p)->state];
+ wchan = get_wchan(*p);
for(i=0; i<32; ++i) {
switch((int) (*p)->sigaction[i].sa_handler) {
case 1: sigignore |= bit; break;
@@ -200,7 +221,7 @@ static int get_stat(int pid, char * buffer)
(*p)->blocked,
sigignore,
sigcatch,
- (*p)->tss.eip);
+ wchan);
}
static int get_statm(int pid, char * buffer)
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 07ceb81..81492a8 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -67,16 +67,6 @@ void proc_statfs(struct super_block *sb, struct statfs *buf)
/* Don't know what value to put in buf->f_fsid */
}
-int proc_bmap(struct inode * inode,int block)
-{
- return 0;
-}
-
-int proc_create_block(struct inode * inode, int block)
-{
- return 0;
-}
-
void proc_read_inode(struct inode * inode)
{
unsigned long ino, pid;
@@ -111,6 +101,8 @@ void proc_read_inode(struct inode * inode)
if (!pid) {
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_array_inode_operations;
+ if (ino == 5)
+ inode->i_op = &proc_kmsg_inode_operations;
return;
}
ino &= 0x0000ffff;
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
new file mode 100644
index 0000000..2cc2605
--- /dev/null
+++ b/fs/proc/kmsg.c
@@ -0,0 +1,61 @@
+/*
+ * linux/fs/proc/kmsg.c
+ *
+ * Copyright (C) 1992 by Linus Torvalds
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+extern int sys_syslog(int type, char * bug, int count);
+
+static int kmsg_open(struct inode * inode, struct file * file)
+{
+ return sys_syslog(1,NULL,0);
+}
+
+static void kmsg_release(struct inode * inode, struct file * file)
+{
+ (void) sys_syslog(0,NULL,0);
+}
+
+static int kmsg_read(struct inode * inode, struct file * file,char * buf, int count)
+{
+ return sys_syslog(2,buf,count);
+}
+
+static struct file_operations proc_kmsg_operations = {
+ NULL, /* kmsg_lseek */
+ kmsg_read,
+ NULL, /* kmsg_write */
+ NULL, /* kmsg_readdir */
+ NULL, /* kmsg_select */
+ NULL, /* kmsg_ioctl */
+ NULL, /* mmap */
+ kmsg_open,
+ kmsg_release
+};
+
+struct inode_operations proc_kmsg_inode_operations = {
+ &proc_kmsg_operations, /* default base directory file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL /* truncate */
+};
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 2aa78a6..700f6b0 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -54,7 +54,8 @@ static struct proc_dir_entry root_dir[] = {
{ 2,7,"loadavg" },
{ 3,6,"uptime" },
{ 4,7,"meminfo" },
- { 5,4,"self" } /* will change inode # */
+ { 5,4,"kmsg" },
+ { 6,4,"self" } /* will change inode # */
};
#define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
@@ -81,7 +82,7 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len,
*result = dir;
return 0;
}
- if (ino == 5) /* self modifying inode ... */
+ if (ino == 6) /* self modifying inode ... */
ino = (current->pid << 16) + 2;
} else {
pid = 0;
diff --git a/fs/select.c b/fs/select.c
index ea97e58..1bf7f15 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -18,6 +18,8 @@
#include <asm/segment.h>
#include <asm/system.h>
+#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+
/*
* Ok, Peter made a complicated, but straightforward multiple_wait() function.
* I have rewritten this, taking some shortcuts: This code may not be easy to
@@ -198,7 +200,7 @@ int sys_select( unsigned long *buffer )
timeout = 0xffffffff;
if (tvp) {
timeout = jiffies;
- timeout += get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
+ timeout += ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
if (timeout <= jiffies)
timeout = 0;
diff --git a/include/asm/irq.h b/include/asm/irq.h
index a492dc8..da69d1f 100644
--- a/include/asm/irq.h
+++ b/include/asm/irq.h
@@ -122,7 +122,15 @@ __asm__( \
"addl $8,%esp\n\t" \
"cli\n\t" \
UNBLK_##chip(mask) \
- "call _do_bottom_half\n\t"\
+ "decl _intr_count\n\t" \
+ "jne ret_from_sys_call\n\t" \
+ "cmpl $0,_bh_active\n\t" \
+ "je ret_from_sys_call\n\t" \
+ "incl _intr_count\n\t" \
+ "sti\n\t" \
+ "call _do_bottom_half\n\t" \
+ "cli\n\t" \
+ "decl _intr_count\n\t" \
"jmp ret_from_sys_call\n" \
"\n.align 2\n" \
"_fast_IRQ" #nr "_interrupt:\n\t" \
diff --git a/include/asm/system.h b/include/asm/system.h
index 45cb87d..4aee818 100644
--- a/include/asm/system.h
+++ b/include/asm/system.h
@@ -1,3 +1,6 @@
+#ifndef __ASM_SYSTEM_H
+#define __ASM_SYSTEM_H
+
#define move_to_user_mode() \
__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
@@ -17,6 +20,14 @@ __asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
#define cli() __asm__ __volatile__ ("cli"::)
#define nop() __asm__ __volatile__ ("nop"::)
+extern inline int tas(char * m)
+{
+ char res;
+
+ __asm__("xchg %0,%1":"=q" (res),"=m" (*m):"0" (0x1));
+ return res;
+}
+
#define save_flags(x) \
__asm__ __volatile__("pushfl ; popl %0":"=r" (x))
@@ -70,3 +81,5 @@ __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),231,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),23,"0x82")
+
+#endif
diff --git a/include/linux/autoconf.h b/include/linux/autoconf.h
deleted file mode 100644
index e6db1e5..0000000
--- a/include/linux/autoconf.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Automatically generated C config: don't edit
- */
-
-/*
- * General setup
- */
-#define CONFIG_BLK_DEV_HD 1
-#define CONFIG_TCPIP 1
-#define CONFIG_MAX_16M 1
-#define CONFIG_M486 1
-
-/*
- * SCSI support
- */
-
-/*
- * SCSI support type (disk, tape, CDrom)
- */
-
-/*
- * SCSI low-level drivers
- */
-
-/*
- * Filesystems
- */
-#define CONFIG_MINIX_FS 1
-#define CONFIG_PROC_FS 1
-
-/*
- * Various character device drivers..
- */
diff --git a/include/linux/config.h b/include/linux/config.h
index 59d2c69..c472335 100644
--- a/include/linux/config.h
+++ b/include/linux/config.h
@@ -22,7 +22,7 @@
#define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000
#define DEF_SETUPSEG 0x9020
-#define DEF_SYSSIZE 0x7000
+#define DEF_SYSSIZE 0x8000
/* internal svga startup constants */
#define NORMAL_VGA 0xffff /* 80x25 mode */
diff --git a/include/linux/config_rel.h b/include/linux/config_rel.h
deleted file mode 100644
index f875936..0000000
--- a/include/linux/config_rel.h
+++ /dev/null
@@ -1 +0,0 @@
-#define UTS_RELEASE "0.97.pl2-44"
diff --git a/include/linux/config_ver.h b/include/linux/config_ver.h
deleted file mode 100644
index 18a6d6e..0000000
--- a/include/linux/config_ver.h
+++ /dev/null
@@ -1 +0,0 @@
-#define UTS_VERSION "08/23/92"
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index f997e3c..812faf4 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -16,9 +16,15 @@ enum {
TIMER_BH = 0,
CONSOLE_BH,
SERIAL_BH,
- INET_BH
+ INET_BH,
+ KEYBOARD_BH
};
void do_bottom_half();
+extern inline void mark_bh(int nr)
+{
+ __asm__ __volatile__("btsl %1,%0":"=m" (bh_active):"ir" (nr));
+}
+
#endif
diff --git a/include/linux/lp.h b/include/linux/lp.h
index b73709c..c885ae2 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -30,32 +30,31 @@
* have extremely slow printing, or if the machine seems to slow down
* a lot when you print. If you have slow printing, increase this
* number and recompile, and if your system gets bogged down, decrease
- * this number. This can be changed with the tunelp(8) command.
+ * this number. This can be changed with the tunelp(8) command as well.
*/
-#define LP_INIT_CHAR 250
+#define LP_INIT_CHAR 1000
/* The parallel port specs apparently say that there needs to be
* a .5usec wait before and after the strobe. Since there are wildly
* different computers running linux, I can't come up with a perfect
* value, but since it worked well on most printers before without,
- * and I have seen some improvement on my computer by making it a
- * small number, I'll initialize it to 2.
+ * I'll initialize it to 0.
*/
-#define LP_INIT_WAIT 2
+#define LP_INIT_WAIT 0
/* This is the amount of time that the driver waits for the printer to
* catch up when the printer's buffer appears to be filled. If you
* want to tune this and have a fast printer (i.e. HPIIIP), decrease
* this number, and if you have a slow printer, increase this number.
- * This is in hundredths of a second, the default 10 being .1 second.
+ * This is in hundredths of a second, the default 2 being .05 second.
* Or use the tunelp(8) command, which is especially nice if you want
* change back and forth between character and graphics printing, which
* are wildly different...
*/
-#define LP_INIT_TIME 10
+#define LP_INIT_TIME 2
/* IOCTL numbers */
#define LPCHAR 0x0001 /* corresponds to LP_INIT_CHAR */
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index f97fbcd..a8f3211 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -5,12 +5,20 @@
* The minix filesystem constants/structures
*/
+/*
+ * Thanks to Kees J Bot for sending me the definitions of the new
+ * minix filesystem (aka V2) with bigger inodes and 32-bit block
+ * pointers. It's not actually implemented yet, but I'll look into
+ * it.
+ */
+
#define MINIX_NAME_LEN 14
#define MINIX_ROOT_INO 1
-#define MINIX_I_MAP_SLOTS 8
-#define MINIX_Z_MAP_SLOTS 8
-#define MINIX_SUPER_MAGIC 0x137F
+#define MINIX_I_MAP_SLOTS 8
+#define MINIX_Z_MAP_SLOTS 8
+#define MINIX_SUPER_MAGIC 0x137F
+#define NEW_MINIX_SUPER_MAGIC 0x2468
#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
#define MINIX_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_dir_entry)))
@@ -26,6 +34,24 @@ struct minix_inode {
};
/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct new_minix_inode {
+ unsigned short i_mode;
+ unsigned short i_nlinks;
+ unsigned short i_uid;
+ unsigned short i_gid;
+ unsigned long i_size;
+ unsigned long i_atime;
+ unsigned long i_mtime;
+ unsigned long i_ctime;
+ unsigned long i_zone[10];
+};
+
+/*
* minix super-block data on disk
*/
struct minix_super_block {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index b8bc123..8ff2eba 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -27,6 +27,7 @@ extern struct inode_operations proc_root_inode_operations;
extern struct inode_operations proc_base_inode_operations;
extern struct inode_operations proc_mem_inode_operations;
extern struct inode_operations proc_array_inode_operations;
+extern struct inode_operations proc_kmsg_inode_operations;
extern struct inode_operations proc_link_inode_operations;
extern struct inode_operations proc_fd_inode_operations;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d52d65c..e6fdbfb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -184,7 +184,7 @@ struct task_struct {
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
unsigned short rss; /* number of resident pages */
- char comm[8];
+ char comm[16];
struct vm86_struct * vm86_info;
unsigned long screen_bitmap;
/* file system info */
diff --git a/include/linux/types.h b/include/linux/types.h
index ff3db4b..968a49e 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -82,7 +82,7 @@ typedef unsigned long tcflag_t;
#define __FDSET_LONGS 8
typedef struct fd_set {
- unsigned long __bits [__FDSET_LONGS];
+ unsigned long fds_bits [__FDSET_LONGS];
} fd_set;
#undef __NFDBITS
diff --git a/init/main.c b/init/main.c
index cb47e84..9f8b16f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -100,7 +100,7 @@ extern unsigned long scsi_dev_init(unsigned long, unsigned long);
*/
#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
+outb_p(addr,0x70); \
inb_p(0x71); \
})
@@ -109,7 +109,11 @@ inb_p(0x71); \
static void time_init(void)
{
struct mktime time;
+ int i;
+ for (i = 0 ; i < 1000000 ; i++)
+ if (!(CMOS_READ(10) & 0x80))
+ break;
do {
time.sec = CMOS_READ(0);
time.min = CMOS_READ(2);
diff --git a/kernel/FPU-emu/get_address.c b/kernel/FPU-emu/get_address.c
index 75b149e..3d5e97f 100644
--- a/kernel/FPU-emu/get_address.c
+++ b/kernel/FPU-emu/get_address.c
@@ -115,7 +115,7 @@ void get_address(unsigned char FPU_modrm)
{
unsigned char mod;
long *cpu_reg_ptr;
- int offset;
+ int offset = 0;
mod = (FPU_modrm >> 6) & 3;
diff --git a/kernel/blk_drv/scsi/scsi.c b/kernel/blk_drv/scsi/scsi.c
index 369d474..40093a0 100644
--- a/kernel/blk_drv/scsi/scsi.c
+++ b/kernel/blk_drv/scsi/scsi.c
@@ -104,11 +104,9 @@ extern int last_reset[];
char * revision; /* Latest revision known to be bad. Not used yet */
};
-#if 0
static struct blist blacklist[] =
{{"TANDBERG","TDC 3600","U07"}, /* Locks up if polled for lun != 0 */
{"SEAGATE","ST296","921"}, /* Responds to all lun */
- {"NEWBURY","NDR3380S","2.10"}, /* Responds to all lun */
{NULL, NULL, NULL}};
static int blacklisted(char * response_data){
@@ -122,7 +120,6 @@ static int blacklisted(char * response_data){
return 1;
};
};
-#endif
/*
* As the actual SCSI command runs in the background, we must set up a
@@ -324,11 +321,9 @@ static void scan_scsis (void)
};
++NR_SCSI_DEVICES;
-#if 0
/* Some scsi devices cannot be polled for lun != 0
due to firmware bugs */
if(blacklisted(scsi_result)) break;
-#endif
/* Some scsi-1 peripherals do not handle lun != 0.
I am assuming that scsi-2 peripherals do better */
if((scsi_result[2] & 0x07) == 1 &&
diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c
index 9f1e83b..ca3c935 100644
--- a/kernel/blk_drv/scsi/sd.c
+++ b/kernel/blk_drv/scsi/sd.c
@@ -62,7 +62,7 @@ static int sd_open(struct inode * inode, struct file * filp)
target = DEVICE_NR(MINOR(inode->i_rdev));
if(target >= NR_SD || !rscsi_disks[target].device)
- return -EACCES; /* No such device */
+ return -ENODEV; /* No such device */
/* Make sure that only one process can do a check_change_disk at one time.
This is also used to lock out further access when the partition table is being re-read. */
@@ -761,6 +761,7 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
+ blkdev_fops[MAJOR_NR] = &sd_fops; /* to get sd_open in table */
if (MAX_SD == 0) return memory_start;
sd_sizes = (int *) memory_start;
@@ -779,7 +780,6 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
i = sd_init_onedisk(i);
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blkdev_fops[MAJOR_NR] = &sd_fops;
/* If our host adapter is capable of scatter-gather, then we increase
the read-ahead to 8 blocks (16 sectors). If not, we use
diff --git a/kernel/blk_drv/scsi/seagate.c b/kernel/blk_drv/scsi/seagate.c
index 7b11506..5214b22 100644
--- a/kernel/blk_drv/scsi/seagate.c
+++ b/kernel/blk_drv/scsi/seagate.c
@@ -61,7 +61,7 @@ static volatile int st0x_aborted=0; /*
detect routine - but this
overides it.
*/
-
+static unsigned char controller_type; /* set to SEAGATE for ST0x boards or FD for TMC-88x boards */
#define retcode(result) (((result) << 16) | (message << 8) | status)
#define STATUS (*(unsigned char *) st0x_cr_sr)
@@ -76,11 +76,12 @@ typedef struct
char *signature ;
unsigned offset;
unsigned length;
+ unsigned char type;
} Signature;
static const Signature signatures[] = {
#ifdef CONFIG_SCSI_SEAGATE
-{"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
+{"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
/*
The following two lines are NOT mistakes. One detects
@@ -90,9 +91,8 @@ static const Signature signatures[] = {
are probably "good enough"
*/
-{"SEAGATE SCSI BIOS ",16, 17},
-{"SEAGATE SCSI BIOS ",17, 17},
-#endif
+{"SEAGATE SCSI BIOS ",16, 17, SEAGATE},
+{"SEAGATE SCSI BIOS ",17, 17, SEAGATE},
/*
This is for the Future Domain 88x series. I've been told that
@@ -101,8 +101,9 @@ static const Signature signatures[] = {
I believe it.
*/
-#ifdef CONFIG_SCSI_FD_88x
-{"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
+{"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46, FD},
+{"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FD},
+{"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD},
#endif
}
;
@@ -168,14 +169,16 @@ static struct sigaction seagate_sigaction = {
for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
if (!memcmp ((void *) (seagate_bases[i] +
signatures[j].offset), (void *) signatures[j].signature,
- signatures[j].length))
+ signatures[j].length)) {
base_address = (void *) seagate_bases[i];
+ controller_type = signatures[j].type;
+ }
#endif
if (base_address)
{
- st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
- st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
+ st0x_cr_sr =(void *) (((unsigned char *) base_address) + (controller_type == SEAGATE ? 0x1a00 : 0x1c00));
+ st0x_dr = (void *) (((unsigned char *) base_address ) + (controller_type == SEAGATE ? 0x1c00 : 0x1e00));
#ifdef DEBUG
printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
#endif
@@ -369,7 +372,7 @@ static int internal_command(unsigned char target, unsigned char lun, const void
#endif
- if (target > 6)
+ if (target == (controller_type == SEAGATE ? 7 : 6))
return DID_BAD_TARGET;
/*
@@ -410,7 +413,7 @@ static int internal_command(unsigned char target, unsigned char lun, const void
* ID off of the BUS.
*/
- if (!((temp = DATA) & 0x80))
+ if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40)))
{
#if (DEBUG & PHASE_RESELECT)
printk("scsi%d : detected reconnect request to different target.\n"
@@ -518,7 +521,7 @@ static int internal_command(unsigned char target, unsigned char lun, const void
/*
* We must assert both our ID and our target's ID on the bus.
*/
- DATA = (unsigned char) ((1 << target) | 0x80);
+ DATA = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));
/*
* If we are allowing ourselves to reconnect, then I will keep
diff --git a/kernel/blk_drv/scsi/seagate.h b/kernel/blk_drv/scsi/seagate.h
index b40b706..efbbe05 100644
--- a/kernel/blk_drv/scsi/seagate.h
+++ b/kernel/blk_drv/scsi/seagate.h
@@ -125,6 +125,9 @@ extern volatile int seagate_st0x_timeout;
#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::)
+#define SEAGATE 1 /* these determine the type of the controller */
+#define FD 2
+
#endif
diff --git a/kernel/blk_drv/scsi/sr.c b/kernel/blk_drv/scsi/sr.c
index 9f9fb33..63a7509 100644
--- a/kernel/blk_drv/scsi/sr.c
+++ b/kernel/blk_drv/scsi/sr.c
@@ -257,7 +257,7 @@ static void rw_intr (Scsi_Cmnd * SCpnt)
static int sr_open(struct inode * inode, struct file * filp)
{
if(MINOR(inode->i_rdev) >= NR_SR ||
- !scsi_CDs[MINOR(inode->i_rdev)].device) return -EACCES; /* No such device */
+ !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENODEV; /* No such device */
check_disk_change(inode->i_rdev);
@@ -601,6 +601,7 @@ unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
+ blkdev_fops[MAJOR_NR] = &sr_fops;
if(MAX_SR == 0) return memory_start;
sr_sizes = (int *) memory_start;
@@ -628,6 +629,5 @@ unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
else
read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
- blkdev_fops[MAJOR_NR] = &sr_fops;
return memory_start;
}
diff --git a/kernel/blk_drv/scsi/st.c b/kernel/blk_drv/scsi/st.c
index 9ede064..c648768 100644
--- a/kernel/blk_drv/scsi/st.c
+++ b/kernel/blk_drv/scsi/st.c
@@ -292,7 +292,7 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
dev = inode->i_rdev & 127;
if (dev >= NR_ST)
- return (-ENXIO);
+ return (-ENODEV);
if (scsi_tapes[dev].in_use) {
printk("st%d: Device already in use.\n", dev);
return (-EBUSY);
@@ -1227,12 +1227,12 @@ unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
{
int i;
+ chrdev_fops[MAJOR_NR] = &st_fops;
if (NR_ST == 0) return mem_start;
#ifdef DEBUG
printk("st: Init tape.\n");
#endif
- chrdev_fops[MAJOR_NR] = &st_fops;
for (i=0; i < NR_ST; ++i) {
scsi_tapes[i].capacity = 0xfffff;
diff --git a/kernel/blk_drv/scsi/wd7000.c b/kernel/blk_drv/scsi/wd7000.c
index 61b5437..cbd55b4 100644
--- a/kernel/blk_drv/scsi/wd7000.c
+++ b/kernel/blk_drv/scsi/wd7000.c
@@ -61,8 +61,6 @@
indices need not be involved.
*/
-static void wd7000_set_sync(int id);
-
static struct {
struct wd_mailbox ogmb[OGMB_CNT];
struct wd_mailbox icmb[ICMB_CNT];
@@ -576,21 +574,6 @@ const char *wd7000_info(void)
return info;
}
-
-void wd7000_set_sync(int id)
-{
- volatile unchar icb[ICB_LEN] = {0x8a};
- unchar speedval = 0x2c; /* Sets 4MHz for SBIC Revision A */
- any2scsi(icb+2,1); /* Transfer 1 byte */
- any2scsi(icb+5,&speedval); /* The speed buffer address */
- icb[8]=0; icb[9]=2*id; /* The index into the table */
-
- icb[ICB_PHASE] = 1;
- mail_out( (struct scb *) icb );
- while (icb[ICB_PHASE]) /* wait for completion */;
-}
-
-
int wd7000_abort(Scsi_Cmnd * SCpnt, int i)
{
#ifdef DEBUG
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index 5f43db0..2ca72d3 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/ptrace.h>
#include <linux/keyboard.h>
+#include <linux/interrupt.h>
/*
* The default IO slowdown is doing 'inb()'s from 0x61, which should be
@@ -39,6 +40,9 @@ struct kbd_struct kbd_table[NR_CONSOLES];
static struct kbd_struct * kbd = kbd_table;
static struct tty_struct * tty = NULL;
+static volatile unsigned char acknowledge = 0;
+static volatile unsigned char resend = 0;
+
typedef void (*fptr)(int);
static int diacr = -1;
@@ -53,57 +57,87 @@ static unsigned int handle_diacr(unsigned int);
static struct pt_regs * pt_regs;
+static inline void kb_wait(void)
+{
+ int i;
+
+ for (i=0; i<0x10000; i++)
+ if ((inb_p(0x64) & 0x02) == 0)
+ break;
+}
+
+/*
+ * send_cmd() sends a command byte to the keyboard.
+ */
+static inline void send_cmd(unsigned char c)
+{
+ kb_wait();
+ outb(c,0x64);
+}
+
+static inline unsigned char get_scancode(void)
+{
+ kb_wait();
+ if (inb_p(0x64) & 0x01)
+ return inb(0x60);
+ return 0;
+}
+
static void keyboard_interrupt(int int_pt_regs)
{
static unsigned char rep = 0xff;
unsigned char scancode;
pt_regs = (struct pt_regs *) int_pt_regs;
- while (inb_p(0x64) & 1) {
- kbd_prev_dead_keys |= kbd_dead_keys;
- if (!kbd_dead_keys)
- kbd_prev_dead_keys = 0;
- kbd_dead_keys = 0;
- scancode = inb_p(0x60);
- tty = TTY_TABLE(0);
- kbd = kbd_table + fg_console;
- if (vc_kbd_flag(kbd,VC_RAW)) {
- kbd_flags = 0;
- put_queue(scancode);
- continue;
- }
- if (scancode == 0xe0) {
- set_kbd_dead(KGD_E0);
- continue;
- } else if (scancode == 0xe1) {
- set_kbd_dead(KGD_E1);
- continue;
- }
- /*
- * The keyboard maintains its own internal caps lock and num lock
- * statuses. In caps lock mode E0 AA precedes make code and E0 2A
- * follows break code. In num lock mode, E0 2A precedes make
- * code and E0 AA follows break code. We do our own book-keeping,
- * so we will just ignore these.
- */
- if (kbd_dead(KGD_E0) && (scancode == 0x2a || scancode == 0xaa))
- continue;
- /*
- * Repeat a key only if the input buffers are empty or the
- * characters get echoed locally. This makes key repeat usable
- * with slow applications and unders heavy loads.
- */
- if (scancode == rep) {
- if (!(vc_kbd_flag(kbd,VC_REPEAT) && tty &&
- (L_ECHO(tty) ||
- (EMPTY(&tty->secondary) &&
- EMPTY(&tty->read_q)))))
- continue;
- }
- rep = scancode;
- key_table[scancode](scancode);
+ kbd_prev_dead_keys |= kbd_dead_keys;
+ if (!kbd_dead_keys)
+ kbd_prev_dead_keys = 0;
+ kbd_dead_keys = 0;
+ send_cmd(0xAD);
+ scancode = get_scancode();
+ if (scancode == 0xfa) {
+ acknowledge = 1;
+ goto end_kbd_intr;
+ } else if (scancode == 0xfe) {
+ resend = 1;
+ goto end_kbd_intr;
+ }
+ tty = TTY_TABLE(0);
+ kbd = kbd_table + fg_console;
+ if (vc_kbd_flag(kbd,VC_RAW)) {
+ kbd_flags = 0;
+ put_queue(scancode);
+ goto end_kbd_intr;
}
+ if (scancode == 0xe0) {
+ set_kbd_dead(KGD_E0);
+ goto end_kbd_intr;
+ } else if (scancode == 0xe1) {
+ set_kbd_dead(KGD_E1);
+ goto end_kbd_intr;
+ }
+ /*
+ * The keyboard maintains its own internal caps lock and num lock
+ * statuses. In caps lock mode E0 AA precedes make code and E0 2A
+ * follows break code. In num lock mode, E0 2A precedes make
+ * code and E0 AA follows break code. We do our own book-keeping,
+ * so we will just ignore these.
+ */
+ if (kbd_dead(KGD_E0) && (scancode == 0x2a || scancode == 0xaa))
+ goto end_kbd_intr;
+ /*
+ * Repeat a key only if the input buffers are empty or the
+ * characters get echoed locally. This makes key repeat usable
+ * with slow applications and unders heavy loads.
+ */
+ if ((scancode != rep) ||
+ (vc_kbd_flag(kbd,VC_REPEAT) && tty &&
+ (L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q)))))
+ key_table[scancode](scancode);
+ rep = scancode;
+end_kbd_intr:
do_keyboard_interrupt();
+ send_cmd(0xAE);
}
static void put_queue(int ch)
@@ -1273,51 +1307,48 @@ static void none(int sc)
}
/*
- * kb_wait waits for the keyboard controller buffer to empty.
+ * send_data sends a character to the keyboard and waits
+ * for a acknowledge, possibly retrying if asked to. Returns
+ * the success status.
*/
-static void kb_wait(void)
+static int send_data(unsigned char data)
{
+ int retries = 3;
int i;
- for (i=0; i<0x10000; i++)
- if ((inb(0x64)&0x02) == 0)
- break;
+ do {
+ kb_wait();
+ acknowledge = 0;
+ resend = 0;
+ outb_p(data, 0x60);
+ for(i=0; i<0x20000; i++) {
+ inb_p(0x64); /* just as a delay */
+ if (acknowledge)
+ return 1;
+ if (resend)
+ goto repeat;
+ }
+ return 0;
+repeat:
+ } while (retries-- > 0);
+ return 0;
}
-/*
- * kb_ack waits for 0xfa to appear in port 0x60
- *
- * Suggested by Bruce Evans
- * Added by Niels Skou Olsen [NSO]
- * April 21, 1992
- *
- * Heavily inspired by kb_wait :-)
- * I don't know how much waiting actually is required,
- * but this seems to work
- */
-static void kb_ack(void)
+static void kbd_bh(void * unused)
{
- int i;
+ static unsigned char old_leds = -1;
+ unsigned char leds = kbd_table[fg_console].flags & LED_MASK;
- for(i=0; i<0x10000; i++)
- if (inb(0x60) == 0xfa)
- break;
+ if (leds == old_leds)
+ return;
+ old_leds = leds;
+ if (!send_data(0xed) || !send_data(leds))
+ send_data(0xf4); /* re-enable kbd if any errors */
}
void set_leds(void)
{
- static unsigned char old_leds = -1;
- unsigned char leds = kbd_table[fg_console].flags & LED_MASK;
-
- if (leds != old_leds) {
- old_leds = leds;
- kb_wait();
- outb(0xed, 0x60); /* set leds command */
- kb_ack();
- kb_wait();
- outb(leds, 0x60);
- kb_ack();
- }
+ mark_bh(KEYBOARD_BH);
}
long no_idt[2] = {0, 0};
@@ -1332,7 +1363,7 @@ void hard_reset_now(void)
int i, j;
extern unsigned long pg0[1024];
- sti();
+ cli();
/* rebooting needs to touch the page at absolute addr 0 */
pg0[0] = 7;
*((unsigned short *)0x472) = 0x1234;
@@ -1425,6 +1456,7 @@ unsigned long kbd_init(unsigned long kmem_start)
kbd->default_flags = KBD_DEFFLAGS;
kbd->kbd_flags = KBDFLAGS;
}
+ bh_base[KEYBOARD_BH].routine = kbd_bh;
request_irq(KEYBOARD_IRQ,keyboard_interrupt);
keyboard_interrupt(0);
return kmem_start;
diff --git a/kernel/chr_drv/sound/sound_stub.c b/kernel/chr_drv/sound/sound_stub.c
index 33cc58d..a64e035 100644
--- a/kernel/chr_drv/sound/sound_stub.c
+++ b/kernel/chr_drv/sound/sound_stub.c
@@ -13,3 +13,7 @@ long soundcard_init(long mem_start)
{
return mem_start;
}
+
+#ifdef CONFIG_SOUND
+#error The Sound Driver not installed.
+#endif
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 00e4952..4d3f5a9 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -1130,9 +1130,9 @@ long tty_init(long kmem_start)
tty_table[i] = 0;
tty_termios[i] = 0;
}
+ kmem_start = kbd_init(kmem_start);
kmem_start = con_init(kmem_start);
kmem_start = rs_init(kmem_start);
- kmem_start = kbd_init(kmem_start);
printk("%d virtual consoles\n\r",NR_CONSOLES);
return kmem_start;
}
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index 7021f2e..7eb6e4e 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -61,18 +61,24 @@ void flush_output(struct tty_struct * tty)
void wait_until_sent(struct tty_struct * tty)
{
- while (!(current->signal & ~current->blocked) &&
- !EMPTY(&tty->write_q)) {
+ struct wait_queue wait = { current, NULL };
+
+ TTY_WRITE_FLUSH(tty);
+ if (EMPTY(&tty->write_q))
+ return;
+ add_wait_queue(&tty->write_q.proc_list, &wait);
+ current->counter = 0; /* make us low-priority */
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (current->signal & ~current->blocked)
+ break;
TTY_WRITE_FLUSH(tty);
- current->counter = 0;
- cli();
if (EMPTY(&tty->write_q))
break;
- else
- interruptible_sleep_on(&tty->write_q.proc_list);
- sti();
+ schedule();
}
- sti();
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&tty->write_q.proc_list, &wait);
}
static int do_get_ps_info(int arg)
@@ -333,7 +339,14 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCNXCL:
return -EINVAL; /* not implemented */
case TIOCSCTTY:
- return -EINVAL; /* set controlling term NI */
+ if (current->leader && current->tty < 0
+ && tty->session == 0) {
+ current->tty = dev;
+ tty->session = current->session;
+ tty->pgrp = current->pgrp;
+ return 0;
+ }
+ return -EPERM;
case TIOCGPGRP:
verify_area((void *) arg,4);
put_fs_long(termios_tty->pgrp,(unsigned long *) arg);
diff --git a/kernel/irq.c b/kernel/irq.c
index 55ec8c7..c3fe514 100644
--- a/kernel/irq.c
+++ b/kernel/irq.c
@@ -32,8 +32,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-
-void irq13(void);
+#define CR0_NE 32
static unsigned long intr_count=0;
@@ -41,55 +40,25 @@ static unsigned long intr_count=0;
int bh_active=0;
struct bh_struct bh_base[32];
-/* interrupts should be on at the interrupt priority controller level. */
-/* returns with interrupts off at the processor level. */
-
+/*
+ * do_bottom_half() runs at normal kernel priority: all interrupts
+ * enabled. do_bottom_half() is atomic with respect to itself: a
+ * bottom_half handler need not be re-entrant. This function is
+ * called only when bh_active is non-zero and when there aren't any
+ * nested irq's active.
+ */
void do_bottom_half(void)
{
struct bh_struct *bh;
- int mask;
- int count;
- static int in_bh = 0;
-
- cli();
- if (intr_count > 1) {
- intr_count--;
- return;
- }
- /* don't just decrement it in case it is already 0 */
-
- intr_count = 0;
-
- /* any sort of real time test should go here. */
- if (in_bh != 0) {
- return;
- }
-
- in_bh = 1;
- do {
- count = 0;
- for (mask = 1, bh = bh_base; mask ; bh++, mask = mask << 1) {
- if (mask > bh_active)
- break;
- if (!(mask & bh_active))
- continue;
+ int nr;
- count++;
- bh_active &= ~mask;
-
- /* turn the interrupts back on. */
- sti();
-
- if (bh->routine != NULL)
- bh->routine(bh->data);
- else
- printk ("irq.c:bad bottom half entry.\n");
-
- /* and back off. */
- cli();
- }
- } while (count > 0);
- in_bh = 0;
+ __asm__ __volatile__("bsfl %1,%0":"=r" (nr):"m" (bh_active));
+ __asm__ __volatile__("btcl %1,%0":"=m" (bh_active):"r" (nr));
+ bh = bh_base+nr;
+ if (bh->routine != NULL)
+ bh->routine(bh->data);
+ else
+ printk ("irq.c:bad bottom half entry.\n");
}
/*
@@ -267,12 +236,24 @@ void free_irq(unsigned int irq)
extern void do_coprocessor_error(long,long);
+/*
+ * Note that on a 486, we don't want to do a SIGFPE on a irq13
+ * as the irq is unreliable, and exception 16 works correctly
+ * (ie as explained in the intel litterature). On a 386, you
+ * can't use exception 16 due to bad IBM design, so we have to
+ * rely on the less exact irq13.
+ */
static void math_error_irq(int cpl)
{
outb(0,0xF0);
do_coprocessor_error(0,0);
}
+static void math_error_irq_486(int cpl)
+{
+ outb(0,0xF0); /* even this is probably not needed.. */
+}
+
static void no_action(int cpl) { }
static struct sigaction ignore_IRQ = {
@@ -285,20 +266,25 @@ static struct sigaction ignore_IRQ = {
void init_IRQ(void)
{
int i;
+ unsigned long cr0;
for (i = 0; i < 16 ; i++)
set_intr_gate(0x20+i,bad_interrupt[i]);
if (irqaction(2,&ignore_IRQ))
printk("Unable to get IRQ2 for cascade\n");
- if (request_irq(13,math_error_irq))
+ __asm__("movl %%cr0,%%eax":"=a" (cr0));
+ if (cr0 & CR0_NE)
+ i = request_irq(13,math_error_irq_486);
+ else
+ i = request_irq(13,math_error_irq);
+ if (i)
printk("Unable to get IRQ13 for math-error handler\n");
/* intialize the bottom half routines. */
- for (i = 0; i < 32; i++)
- {
- bh_base[i].routine = NULL;
- bh_base[i].data = NULL;
- }
+ for (i = 0; i < 32; i++) {
+ bh_base[i].routine = NULL;
+ bh_base[i].data = NULL;
+ }
bh_active = 0;
-
+ intr_count = 0;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 69e3543..3276ac2 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -74,11 +74,11 @@ void math_state_restore()
{
if (last_task_used_math == current)
return;
- __asm__("fwait");
if (last_task_used_math) {
__asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
}
- last_task_used_math=current;
+ __asm__("fwait");
+ last_task_used_math = current;
if (current->used_math) {
__asm__("frstor %0"::"m" (current->tss.i387));
} else {
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
index 3507ed3..fa58a9a 100644
--- a/kernel/sys_call.S
+++ b/kernel/sys_call.S
@@ -149,6 +149,9 @@ _system_call:
call _schedule
.align 4,0x90
ret_from_sys_call:
+/*
+ * XXX - interrupts are masked here about 3 times in 1000. Fishy.
+ */
movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
testl $VM_MASK,%eax # different then
jne 4f
@@ -172,11 +175,11 @@ ret_from_sys_call:
movl blocked(%eax),%ecx
notl %ecx
andl %ebx,%ecx
+ je 2f # XXX - branch is almost always taken
bsfl %ecx,%ecx
- je 2f
- btrl %ecx,%ebx
+ btrl %ecx,signal(%eax) # change atomically (%ebx is stale)
+ jnc 2f # bit became clear (can't happen?)
incl %ecx
- movl %ebx,signal(%eax)
movl %esp,%ebx
testl $VM_MASK,EFLAGS(%esp)
je 3f
diff --git a/net/tcp/dev.c b/net/tcp/dev.c
index 3a8cb12..00b8eff 100644
--- a/net/tcp/dev.c
+++ b/net/tcp/dev.c
@@ -286,7 +286,7 @@ dev_rint(unsigned char *buff, long len, int flags,
sti();
if (backlog != NULL)
- bh_active |= 1 << INET_BH;
+ mark_bh(INET_BH);
return (0);
}
diff --git a/net/unix.c b/net/unix.c
index ec2c4d5..c15247f 100644
--- a/net/unix.c
+++ b/net/unix.c
@@ -184,29 +184,9 @@ unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
return (unix_proto_read (sock, buff, len, nonblock));
}
-/*
- * Since unix domain sockets use filenames to communicate, two sockets are
- * the same if their strings are the same, even if their lengths are different
- * (due to possible null terminations). Verified under SunOS 4.1.2
- */
-static int
-same_path(char *s1, int l1, char *s2, int l2)
-{
- /*
- * Skip chars while they're equal
- */
- for (; l1 && l2 && *s1 == *s2; ++s1, ++s2, --l1, --l2);
-
- /*
- * Both must be exhausted, or one must be null terminated and the
- * other either exhausted or null terminated, for the paths to be
- * equivalent
- */
- return ((l1 == 0 || *s1 == '\0') && (l2 == 0 || *s2 == '\0'));
-}
-
static struct unix_proto_data *
-unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
+unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
+ struct inode *inode)
{
struct unix_proto_data *upd;
@@ -214,9 +194,7 @@ unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
if (upd->refcnt && upd->socket &&
upd->socket->state == SS_UNCONNECTED &&
upd->sockaddr_un.sun_family == sockun->sun_family &&
- same_path(sockun->sun_path, sockaddr_len - UN_PATH_OFFSET,
- upd->sockaddr_un.sun_path,
- upd->sockaddr_len - UN_PATH_OFFSET))
+ upd->inode == inode)
return upd;
}
return NULL;
@@ -386,6 +364,7 @@ unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
#ifdef SOCK_DEBUG
sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
#endif
+ PRINTK("to inode 0x%x\n", upd->inode);
return 0;
}
@@ -400,6 +379,9 @@ unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
int i;
struct unix_proto_data *serv_upd;
struct sockaddr_un sockun;
+ char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
+ unsigned long old_fs;
+ struct inode *inode;
PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
sockaddr_len);
@@ -423,8 +405,28 @@ unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
sockun.sun_family, AF_UNIX);
return -EINVAL;
}
- if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
- PRINTK("unix_proto_connect: can't locate peer\n");
+
+ /*
+ * try to open the name in the filesystem - this is how we
+ * identify ourselves and our server. Note that we don't
+ * hold onto the inode that long, just enough to find our
+ * server. When we're connected, we mooch off the server.
+ */
+ memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
+ fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
+ old_fs = get_fs();
+ set_fs(get_ds());
+ i = open_namei(fname, 0, S_IFSOCK, &inode, NULL);
+ set_fs(old_fs);
+ if (i < 0) {
+ PRINTK("unix_proto_connect: can't open socket %s\n", fname);
+ return i;
+ }
+ serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
+ iput(inode);
+ if (!serv_upd) {
+ PRINTK("unix_proto_connect: can't locate peer %s at inode 0x%x\n",
+ fname, inode);
return -EINVAL;
}
if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
@@ -437,7 +439,7 @@ unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
}
/*
- * to do a socketpair, we make just connect the two datas, easy! since we
+ * to do a socketpair, we just connect the two datas, easy! since we
* always wait on the socket inode, they're no contention for a wait area,
* and deadlock prevention in the case of a process writing to itself is,
* ignored, in true unix fashion!
diff --git a/tools/build.c b/tools/build.c
index d7005c6..8dd7ccf 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -28,11 +28,12 @@
#include <sys/sysmacros.h>
#include <unistd.h> /* contains read/write */
#include <fcntl.h>
+#include <linux/config.h>
#define MINIX_HEADER 32
#define GCC_HEADER 1024
-#define SYS_SIZE 0x7000
+#define SYS_SIZE DEF_SYSSIZE
#define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0
@@ -43,6 +44,32 @@
#define STRINGIFY(x) #x
+typedef union {
+ long l;
+ short s[2];
+ char b[4];
+} conv;
+
+long intel_long(long l)
+{
+ conv t;
+
+ t.b[0] = l & 0xff; l >>= 8;
+ t.b[1] = l & 0xff; l >>= 8;
+ t.b[2] = l & 0xff; l >>= 8;
+ t.b[3] = l & 0xff; l >>= 8;
+ return t.l;
+}
+
+short intel_short(short l)
+{
+ conv t;
+
+ t.b[0] = l & 0xff; l >>= 8;
+ t.b[1] = l & 0xff; l >>= 8;
+ return t.s[0];
+}
+
void die(char * str)
{
fprintf(stderr,"%s\n",str);
@@ -85,9 +112,9 @@ int main(int argc, char ** argv)
die("Unable to open 'boot'");
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
die("Unable to read header of 'boot'");
- if (((long *) buf)[0]!=0x04100301)
+ if (((long *) buf)[0]!=intel_long(0x04100301))
die("Non-Minix header of 'boot'");
- if (((long *) buf)[1]!=MINIX_HEADER)
+ if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'boot'");
if (((long *) buf)[3]!=0)
die("Illegal data segment in 'boot'");
@@ -101,7 +128,7 @@ int main(int argc, char ** argv)
fprintf(stderr,"Boot sector %d bytes.\n",i);
if (i != 512)
die("Boot block must be exactly 512 bytes");
- if ((*(unsigned short *)(buf+510)) != 0xAA55)
+ if ((*(unsigned short *)(buf+510)) != (unsigned short)intel_short(0xAA55))
die("Boot block hasn't got boot flag (0xAA55)");
buf[508] = (char) minor_root;
buf[509] = (char) major_root;
@@ -114,9 +141,9 @@ int main(int argc, char ** argv)
die("Unable to open 'setup'");
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
die("Unable to read header of 'setup'");
- if (((long *) buf)[0]!=0x04100301)
+ if (((long *) buf)[0]!=intel_long(0x04100301))
die("Non-Minix header of 'setup'");
- if (((long *) buf)[1]!=MINIX_HEADER)
+ if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'setup'");
if (((long *) buf)[3]!=0)
die("Illegal data segment in 'setup'");