]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.98.3 (October 27, 1992) 0.98.3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:06 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:06 +0000 (15:09 -0500)
More networking updates.. Ross Biro is still struggling with net-1.

Michael Johnson (now RH kernel release manager) works on line printer
driver.

Locking function cleanups (for inodes, superblocks, buffer heads).  We
also now pass in the superblock pointer instead of the device number to
the filesystem routines.  That cleans up use and locking of
"get_super()" a lot.

[Original announcement below]

Ok, I already sent out an announcement last night, but due to the time
(6AM over here) I wasn't really in a mood to write a real annoucement.
Here it is.

linux-0.98.3 is available by anonymous ftp at least on nic.funet.fi:
pub/OS/Linux/testing/Linus, both as context diffs against 0.98.2 and the
pre-version of 0.98.3 and as complete source. The complete source
package was done by directly applying the diffs - this means that the
Makefile dependancies are probably not 100% up-to-date as I remove those
from the diffs. It shouldn't be any problem, and you can always do a
"make dep ; make clean" before actually compiling the kernel.

0.98 pl3 fixes several bugs, and should remove all known NULL-pointer
problems that made 0.98.2 unusable for most people. In addition to the
NULL pointer fixes, the following things have changed:

- removed most of the cli-sti pairs in the filesystem code by rewriting
  the locking routines to use a different algorithm, possible due to
  the rewritten wait-queue code that I did back in 0.96c or so.
  Interrupt latency should be better on slow machines, but I don't know
  if it's noticeable.
- Minor 387-emulation fixes by Bill Metzenthen - only noticeable under
  special conditions.
- Corrected various error-returns in the fs (thanks to Bruce Evans for
  running some error diagnostics). Error messages when opening (and
  renaming etc) files that had a non-directory in the path were wrong,
  and should be ok now (ie giving ENOTDIR instead of EACCESS or ENOENT).
  Some other problems reported by Bruce fixed.
- Changed the interface for some fs-related functions due to cleaning
  up super-block handling. Most noticeably, iget() and related
  functions no longer specify the inode with a device and inode number,
  but instead with a super-block pointer and inode number. This is
  more logical, and should make unnamed devices (ie internal
  filesystems like nfs and /proc) cleaner. Also note that the calling
  sequence for sb->s_op->put_inode() also has changed since 0.98. This
  is of interest only if you are writing filesystem drivers..
- ASK_SVGA was broken in 0.98.2 - it should be ok now.

Also, various minor fixes as usual. No new features, but I hope 0.98.3
will be a lot less bug-prone due to the changes since 0.98.1. Some
minor tcp/ip corrections (but most of them were in the pre-release), and
I removed a race-condition in the tty-handling code.

Note that people who use math without a co-processor should certainly
upgrade to 0.98.3: the new emulator is much better than my original one
both in speed and accuracy/exception handling. x11perf is very much
bearable now even without a 387, and things like ray-tracing etc
shouldn't be a problem any more. It's slower than hardware fp, of
course, but at least it works.

The new emulator also means there is no reason for a separate soft-float
library, so I'd assume that will be gone in the next gcc release for
linux.

As usual, a new kernel version probably means you'll have to recompile
'ps' and friends. But at least the same 'ps' sources that worked for
0.97.6 should still work.

                Linus

87 files changed:
Makefile
boot/head.S
boot/setup.S
fs/buffer.c
fs/ext/file.c
fs/ext/freelists.c
fs/ext/inode.c
fs/ext/namei.c
fs/ext/truncate.c
fs/inode.c
fs/minix/bitmap.c
fs/minix/file.c
fs/minix/inode.c
fs/minix/namei.c
fs/minix/truncate.c
fs/msdos/inode.c
fs/msdos/misc.c
fs/msdos/namei.c
fs/namei.c
fs/open.c
fs/proc/base.c
fs/proc/fd.c
fs/proc/inode.c
fs/proc/root.c
fs/super.c
include/asm/dma.h [new file with mode: 0644]
include/asm/segment.h
include/linux/config.h
include/linux/ext_fs.h
include/linux/fs.h
include/linux/kernel.h
include/linux/locks.h [new file with mode: 0644]
include/linux/lp.h
include/linux/minix_fs.h
include/linux/sched.h
include/linux/string.h
init/main.c
kernel/FPU-emu/Makefile
kernel/FPU-emu/errors.c
kernel/FPU-emu/reg_ld_str.c
kernel/FPU-emu/reg_mul.c
kernel/FPU-emu/reg_u_add.S
kernel/FPU-emu/reg_u_sub.S
kernel/FPU-emu/version.h
kernel/Makefile
kernel/blk_drv/blk.h
kernel/blk_drv/floppy.c
kernel/blk_drv/ll_rw_blk.c
kernel/blk_drv/ramdisk.c
kernel/blk_drv/scsi/7000fasst.h
kernel/blk_drv/scsi/aha1542.c
kernel/blk_drv/scsi/aha1542.h
kernel/blk_drv/scsi/fdomain.h
kernel/blk_drv/scsi/hosts.h
kernel/blk_drv/scsi/scsi.c
kernel/blk_drv/scsi/scsi.h
kernel/blk_drv/scsi/scsi_ioctl.c
kernel/blk_drv/scsi/sd.c
kernel/blk_drv/scsi/sd.h
kernel/blk_drv/scsi/seagate.h
kernel/blk_drv/scsi/sr.c
kernel/blk_drv/scsi/sr.h
kernel/blk_drv/scsi/st.c
kernel/blk_drv/scsi/st.h
kernel/blk_drv/scsi/ultrastor.h
kernel/chr_drv/keyboard.c
kernel/chr_drv/lp.c
kernel/chr_drv/mem.c
kernel/chr_drv/serial.c
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c
kernel/dma.c [new file with mode: 0644]
kernel/exit.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/vsprintf.c
lib/malloc.c
mm/memory.c
net/tcp/arp.c
net/tcp/dev.c
net/tcp/eth.c
net/tcp/loopback.c
net/tcp/sock.c
net/tcp/tcp.c
net/tcp/udp.c
net/tcp/we.c

index c2715175d3d1dc0555556eb2e2b0b6e91c25071a..723dd23c144a1eeb56b661e05b6531a132f1f945 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -45,7 +45,7 @@ KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
 # KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x9F
 # KEYBOARD = -DKBD_SF -DKBDFLAGS=0
 # KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x9F
-# KEYBOARD = -DKDB_NO
+# KEYBOARD = -DKBD_NO -DKBDFLAGS=0
 
 #
 # comment this line if you don't want the emulation-code
@@ -127,7 +127,7 @@ linuxsubdirs: dummy
 
 Version:
        @./makever.sh
-       @echo \#define UTS_RELEASE \"0.98.pl2-`cat .version`\" > tools/version.h
+       @echo \#define UTS_RELEASE \"0.98.pl3-`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
@@ -170,10 +170,10 @@ boot/setup: boot/setup.s
        $(AS86) -o boot/setup.o boot/setup.s
        $(LD86) -s -o boot/setup boot/setup.o
 
-boot/setup.s:  boot/setup.S include/linux/config.h
+boot/setup.s:  boot/setup.S include/linux/config.h Makefile
        $(CPP) -traditional $(SVGA_MODE) boot/setup.S -o boot/setup.s
 
-boot/bootsect.s:       boot/bootsect.S include/linux/config.h
+boot/bootsect.s: boot/bootsect.S include/linux/config.h
        $(CPP) -traditional boot/bootsect.S -o boot/bootsect.s
 
 boot/bootsect: boot/bootsect.s
index 47355cb69a1261819b87b3c76ab5c66b3c7241c6..aef714a5167d259364bd4792edebad8e3c9cb57c 100644 (file)
  * the page directory.
  */
 .text
-.globl _idt,_gdt,_swapper_pg_dir,_tmp_floppy_area,_floppy_track_buffer
+.globl _idt,_gdt,
+.globl _swapper_pg_dir,_pg0
 .globl _empty_bad_page
 .globl _empty_bad_page_table
+.globl _tmp_floppy_area,_floppy_track_buffer
 
 /*
  * swapper_pg_dir is the main page directory, address 0x00001000
@@ -125,7 +127,7 @@ _swapper_pg_dir:
  * tables are set up later depending on memory size.
  */
 .org 0x2000
-pg0:
+_pg0:
 
 .org 0x3000
 _empty_bad_page:
@@ -232,10 +234,10 @@ setup_paging:
        movl $_swapper_pg_dir,%edi      /* swapper_pg_dir is at 0x1000 */
        cld;rep;stosl
 /* Identity-map the kernel in low 4MB memory for ease of transition */
-       movl $pg0+7,_swapper_pg_dir             /* set present bit/user r/w */
+       movl $_pg0+7,_swapper_pg_dir            /* set present bit/user r/w */
 /* But the real place is at 0xC0000000 */
-       movl $pg0+7,_swapper_pg_dir+3072        /* set present bit/user r/w */
-       movl $pg0+4092,%edi
+       movl $_pg0+7,_swapper_pg_dir+3072       /* set present bit/user r/w */
+       movl $_pg0+4092,%edi
        movl $0x03ff007,%eax            /*  4Mb - 4096 + 7 (r/w user,p) */
        std
 1:     stosl                   /* fill the page backwards - more efficient :-) */
index 320c0cf4fbf3b580998d0b37c71c3f039e7c1d92..5316dcf3777757ec074d10f8cc088f89d405940e 100644 (file)
@@ -1,5 +1,5 @@
 !
-!      setup.s         Copyright (C) 1991, 1992 Linus Torvalds
+!      setup.S         Copyright (C) 1991, 1992 Linus Torvalds
 !
 ! setup.s is responsible for getting the system data from the BIOS,
 ! and putting them into the appropriate places in system memory.
 
 ! NOTE! These had better be the same as in bootsect.s!
 #include <linux/config.h>
-#define NORMAL_VGA 0xffff
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
 
 INITSEG  = DEF_INITSEG ! we move boot here - out of the way
 SYSSEG   = DEF_SYSSEG  ! system loaded at 0x10000 (65536).
@@ -265,8 +268,14 @@ chsvga:    cld
        pop     ds
        mov     ax,#0xc000
        mov     es,ax
+       mov     ax,modesave
+       cmp     ax,#NORMAL_VGA
+       je      defvga
+       cmp     ax,#EXTENDED_VGA
+       je      extvga
+       cmp     ax,#ASK_VGA
+       jne     svga
        lea     si,msg1
-#ifndef SVGA_MODE
        call    prtstr
 flush: in      al,#0x60                ! Flush the keyboard buffer
        cmp     al,#0x82
@@ -277,12 +286,27 @@ nokey:    call getkey
        je      svga                    ! yes - svga selection
        cmp     al,#0xb9                ! space ?
        jne     nokey                   ! no - repeat
-#endif
-#if !defined(SVGA_MODE) || SVGA_MODE == NORMAL_VGA
-       mov     ax,#0x5019
+defvga:        mov     ax,#0x5019
        pop     ds
        ret
-#endif
+/* extended vga mode: 80x50 */
+extvga:
+       mov     ax,#0x1112
+       mov     bl,#0
+       int     0x10            ! use 8x8 font set (50 lines on VGA)
+       mov     ax,#0x1200
+       mov     bl,#0x20
+       int     0x10            ! use alternate print screen
+       mov     ax,#0x1201
+       mov     bl,#0x34
+       int     0x10            ! turn off cursor emulation
+       mov     ah,#0x01
+       mov     cx,#0x0607
+       int     0x10            ! turn on cursor (scan lines 6 to 7)
+       pop     ds
+       mov     ax,#0x5032      ! return 80x50
+       ret
+/* svga modes */
 svga:  cld
        lea     si,idati                ! Check ATI 'clues'
        mov     di,#0x31
@@ -532,9 +556,11 @@ tbl:       pop     bx
        call    prtstr
        pop     si
        add     cl,#0x80
-#if defined(SVGA_MODE) && SVGA_MODE != NORMAL_VGA
-       mov     al,#SVGA_MODE           ! Preset SVGA mode 
-#else
+       mov     ax,modesave
+       cmp     ax,#ASK_VGA
+       je      nonum
+       cmp     ax,#NORMAL_VGA
+       jne     gotmode
 nonum: call    getkey
        cmp     al,#0x82
        jb      nonum
@@ -546,8 +572,7 @@ nonum:      call    getkey
 zero:  sub     al,#0x0a
 nozero:        sub     al,#0x80
        dec     al
-#endif
-       xor     ah,ah
+gotmode:       xor     ah,ah
        add     di,ax
        inc     di
        push    ax
@@ -560,25 +585,7 @@ nozero:    sub     al,#0x80
        pop     ds
        ret
 novid7:
-       mov     ax,#0x1112
-       mov     bl,#0
-       int     0x10            ! use 8x8 font set (50 lines on VGA)
-
-       mov     ax,#0x1200
-       mov     bl,#0x20
-       int     0x10            ! use alternate print screen
-
-       mov     ax,#0x1201
-       mov     bl,#0x34
-       int     0x10            ! turn off cursor emulation
-
-       mov     ah,#0x01
-       mov     cx,#0x0607
-       int     0x10            ! turn on cursor (scan lines 6 to 7)
-
-       pop     ds
-       mov     ax,#0x5032      ! return 80x50
-       ret
+       br extvga
 
 ! Routine that 'tabs' to next col.
 
@@ -712,6 +719,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
+modesave:      .word   SVGA_MODE
        
 .text
 endtext:
index 7203b659497acfe12ba196871fabe5723154acc9..d02e39f2d025124a58b01423de6b2084ab5e56e0 100644 (file)
@@ -7,9 +7,7 @@
 /*
  *  'buffer.c' implements the buffer-cache functions. Race-conditions have
  * been avoided by NEVER letting a interrupt change a buffer (except for the
- * data, of course), but instead letting the caller do it. NOTE! As interrupts
- * can wake up a caller, some cli-sti sequences are needed to check for
- * sleep-on-calls. These should be extremely quick, though (I hope).
+ * data, of course), but instead letting the caller do it.
  */
 
 /*
@@ -24,6 +22,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -46,15 +45,29 @@ static struct wait_queue * buffer_wait = NULL;
 int nr_buffers = 0;
 int nr_buffer_heads = 0;
 
-static inline void wait_on_buffer(struct buffer_head * bh)
+/*
+ * Rewrote the wait-routines to use the "new" wait-queue functionality,
+ * and getting rid of the cli-sti pairs. The wait-queue routines still
+ * need cli-sti, but now it's just a couple of 386 instructions or so.
+ *
+ * Note that the real wait_on_buffer() is an inline function that checks
+ * if 'b_wait' is set before calling this, so that the queues aren't set
+ * up unnecessarily.
+ */
+void __wait_on_buffer(struct buffer_head * bh)
 {
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
+       add_wait_queue(&bh->b_wait,&current->wait);
+repeat:
+       current->state = TASK_UNINTERRUPTIBLE;
+       if (bh->b_lock) {
+               schedule();
+               goto repeat;
+       }
+       remove_wait_queue(&bh->b_wait,&current->wait);
+       current->state = TASK_RUNNING;
 }
 
-static void sync_buffers(int dev)
+static void sync_buffers(dev_t dev)
 {
        int i;
        struct buffer_head * bh;
@@ -69,35 +82,21 @@ static void sync_buffers(int dev)
        }
 }
 
-int sys_sync(void)
+void sync_dev(dev_t dev)
 {
-       int i;
-
-       for (i=0 ; i<NR_SUPER ; i++)
-               if (super_block[i].s_dev
-                   && super_block[i].s_op 
-                   && super_block[i].s_op->write_super 
-                   && super_block[i].s_dirt)
-                       super_block[i].s_op->write_super(&super_block[i]);
-       sync_inodes();          /* write out inodes into buffers */
-       sync_buffers(0);
-       return 0;
+       sync_buffers(dev);
+       sync_supers(dev);
+       sync_inodes(dev);
+       sync_buffers(dev);
 }
 
-int sync_dev(int dev)
+int sys_sync(void)
 {
-       struct super_block * sb;
-
-       if (sb = get_super (dev))
-               if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
-                       sb->s_op->write_super (sb);
-       sync_buffers(dev);
-       sync_inodes();
-       sync_buffers(dev);
+       sync_dev(0);
        return 0;
 }
 
-void invalidate_buffers(int dev)
+void invalidate_buffers(dev_t dev)
 {
        int i;
        struct buffer_head * bh;
@@ -126,7 +125,7 @@ void invalidate_buffers(int dev)
  * and that mount/open needn't know that floppies/whatever are
  * special.
  */
-void check_disk_change(int dev)
+void check_disk_change(dev_t dev)
 {
        int i;
        struct buffer_head * bh;
@@ -251,7 +250,7 @@ static inline void insert_into_queues(struct buffer_head * bh)
                bh->b_next->b_prev = bh;
 }
 
-static struct buffer_head * find_buffer(int dev, int block, int size)
+static struct buffer_head * find_buffer(dev_t dev, int block, int size)
 {              
        struct buffer_head * tmp;
 
@@ -273,7 +272,7 @@ static struct buffer_head * find_buffer(int dev, int block, int size)
  * will force it bad). This shouldn't really happen currently, but
  * the code is ready.
  */
-struct buffer_head * get_hash_table(int dev, int block, int size)
+struct buffer_head * get_hash_table(dev_t dev, int block, int size)
 {
        struct buffer_head * bh;
 
@@ -301,7 +300,7 @@ struct buffer_head * get_hash_table(int dev, int block, int size)
  * when the filesystem starts to get full of dirty blocks (I hope).
  */
 #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
-struct buffer_head * getblk(int dev, int block, int size)
+struct buffer_head * getblk(dev_t dev, int block, int size)
 {
        struct buffer_head * bh, * tmp;
        int buffers;
@@ -377,7 +376,7 @@ void brelse(struct buffer_head * buf)
  * bread() reads a specified block and returns the buffer that contains
  * it. It returns NULL if the block was unreadable.
  */
-struct buffer_head * bread(int dev, int block, int size)
+struct buffer_head * bread(dev_t dev, int block, int size)
 {
        struct buffer_head * bh;
 
@@ -408,7 +407,7 @@ __asm__("cld\n\t" \
  * all at the same time, not waiting for one to be read, and then another
  * etc.
  */
-void bread_page(unsigned long address,int dev,int b[4])
+void bread_page(unsigned long address, dev_t dev, int b[4])
 {
        struct buffer_head * bh[4];
        int i;
@@ -434,7 +433,7 @@ void bread_page(unsigned long address,int dev,int b[4])
  * blocks for reading as well. End the argument list with a negative
  * number.
  */
-struct buffer_head * breada(int dev,int first, ...)
+struct buffer_head * breada(dev_t dev,int first, ...)
 {
        va_list args;
        struct buffer_head * bh, *tmp;
index 39d33489145dc69b74f46dac27b25af92aadddba..fb7bb2b8bb0b47d95826e2658f3576ef053d13a4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #define        NBUF    16
 
 #include <linux/fs.h>
 #include <linux/ext_fs.h>
 
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
-}
-
 static int ext_file_read(struct inode *, struct file *, char *, int);
 static int ext_file_write(struct inode *, struct file *, char *, int);
 
index 848652809d97468b30780ada91f430b22307fc57..81b54f1cd6c9668d59a44c02f023d6f95f181fc6 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ext_fs.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/locks.h>
 
 #define clear_block(addr) \
 __asm__("cld\n\t" \
@@ -41,13 +42,12 @@ __asm__("cld\n\t" \
         "stosl" \
         ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
 
-void ext_free_block(int dev, int block)
+void ext_free_block(struct super_block * sb, int block)
 {
-       struct super_block * sb;
        struct buffer_head * bh;
        struct ext_free_block * efb;
 
-       if (!(sb = get_super(dev)))
+       if (!sb)
                panic("trying to free block on nonexistent device");
        lock_super (sb);
        if (block < sb->u.ext_sb.s_firstdatazone ||
@@ -55,7 +55,7 @@ void ext_free_block(int dev, int block)
                printk("trying to free block not in datazone\n");
                return;
        }
-       bh = get_hash_table(dev, block, sb->s_blocksize);
+       bh = get_hash_table(sb->s_dev, block, sb->s_blocksize);
        if (bh)
                bh->b_dirt=0;
        brelse(bh);
@@ -67,7 +67,7 @@ printk("ext_free_block: block full, skipping to %d\n", block);
 #endif
                if (sb->u.ext_sb.s_firstfreeblock)
                        brelse (sb->u.ext_sb.s_firstfreeblock);
-               if (!(sb->u.ext_sb.s_firstfreeblock = bread (dev,
+               if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
                        block, sb->s_blocksize)))
                        panic ("ext_free_block: unable to read block to free\n");
                efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
@@ -80,18 +80,17 @@ printk("ext_free_block: block full, skipping to %d\n", block);
        sb->u.ext_sb.s_freeblockscount ++;
        sb->s_dirt = 1;
        sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
-       free_super (sb);
+       unlock_super (sb);
        return;
 }
 
-int ext_new_block(int dev)
+int ext_new_block(struct super_block * sb)
 {
        struct buffer_head * bh;
-       struct super_block * sb;
        struct ext_free_block * efb;
        int j;
 
-       if (!(sb = get_super(dev)))
+       if (!sb)
                panic("trying to get new block from nonexistant device");
        if (!sb->u.ext_sb.s_firstfreeblock)
                return 0;
@@ -110,7 +109,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
                if (!sb->u.ext_sb.s_firstfreeblocknumber) {
                        sb->u.ext_sb.s_firstfreeblock = NULL;
                } else {
-                       if (!(sb->u.ext_sb.s_firstfreeblock = bread (dev,
+                       if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
                                sb->u.ext_sb.s_firstfreeblocknumber,
                                sb->s_blocksize)))
                                panic ("ext_new_block: unable to read next free block\n");
@@ -123,7 +122,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
        sb->u.ext_sb.s_freeblockscount --;
        sb->s_dirt = 1;
 
-       if (!(bh=getblk(dev, j, sb->s_blocksize)))
+       if (!(bh=getblk(sb->s_dev, j, sb->s_blocksize)))
                panic("new_block: cannot get block");
        if (bh->b_count != 1)
                panic("new block: count is != 1");
@@ -134,7 +133,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: allocating block %d\n", j);
 #endif
-       free_super (sb);
+       unlock_super (sb);
        return j;
 }
 
@@ -166,7 +165,7 @@ unsigned long ext_count_free_blocks(struct super_block *sb)
        }
 printk("ext_count_free_blocks: stored = %d, computed = %d\n",
        sb->u.ext_sb.s_freeblockscount, count);
-       free_super (sb);
+       unlock_super (sb);
        return count;
 #else
        return sb->u.ext_sb.s_freeblockscount;
@@ -200,7 +199,7 @@ void ext_free_inode(struct inode * inode)
        lock_super (inode->i_sb);
        if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.ext_sb.s_ninodes) {
                printk("free_inode: inode 0 or nonexistent inode\n");
-               free_super (inode->i_sb);
+               unlock_super (inode->i_sb);
                return;
        }
        if (inode->i_sb->u.ext_sb.s_firstfreeinodeblock)
@@ -227,57 +226,54 @@ printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
        inode->i_sb->u.ext_sb.s_freeinodescount ++;
        inode->i_sb->s_dirt = 1;
        inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
-       free_super (inode->i_sb);
+       unlock_super (inode->i_sb);
        memset(inode,0,sizeof(*inode));
 }
 
-struct inode * ext_new_inode(int dev)
+struct inode * ext_new_inode(struct super_block * sb)
 {
        struct inode * inode;
        struct ext_free_inode * efi;
        unsigned long block;
        int j;
 
-       if (!(inode=get_empty_inode()))
+       if (!sb || !(inode=get_empty_inode()))
                return NULL;
-       if (!(inode->i_sb = get_super(dev))) {
-               printk("new_inode: unknown device\n");
-               iput(inode);
-               return NULL;
-       }
-       inode->i_flags = inode->i_sb->s_flags;
-       if (!inode->i_sb->u.ext_sb.s_firstfreeinodeblock)
+       inode->i_sb = sb;
+       inode->i_flags = sb->s_flags;
+       if (!sb->u.ext_sb.s_firstfreeinodeblock)
                return 0;
-       lock_super (inode->i_sb);
-       efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
-               (inode->i_sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
+       lock_super (sb);
+       efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
+               (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
        if (efi->count) {
                j = efi->free[--efi->count];
-               inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
+               sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
        } else {
 #ifdef EXTFS_DEBUG
 printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
 #endif
-               j = inode->i_sb->u.ext_sb.s_firstfreeinodenumber;
-               if (efi->next > inode->i_sb->u.ext_sb.s_ninodes) {
+               j = sb->u.ext_sb.s_firstfreeinodenumber;
+               if (efi->next > sb->u.ext_sb.s_ninodes) {
                        printk ("efi->next = %d\n", efi->next);
                        panic ("ext_new_inode: bad inode number in free list\n");
                }
-               inode->i_sb->u.ext_sb.s_firstfreeinodenumber = efi->next;
+               sb->u.ext_sb.s_firstfreeinodenumber = efi->next;
                block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
-               brelse (inode->i_sb->u.ext_sb.s_firstfreeinodeblock);
-               if (!inode->i_sb->u.ext_sb.s_firstfreeinodenumber) {
-                       inode->i_sb->u.ext_sb.s_firstfreeinodeblock = NULL;
+               brelse (sb->u.ext_sb.s_firstfreeinodeblock);
+               if (!sb->u.ext_sb.s_firstfreeinodenumber) {
+                       sb->u.ext_sb.s_firstfreeinodeblock = NULL;
                } else {
-                       if (!(inode->i_sb->u.ext_sb.s_firstfreeinodeblock = bread (dev, block, inode->i_sb->s_blocksize)))
+                       if (!(sb->u.ext_sb.s_firstfreeinodeblock =
+                           bread(sb->s_dev, block, sb->s_blocksize)))
                                panic ("ext_new_inode: unable to read next free inode block\n");
                }
        }
-       inode->i_sb->u.ext_sb.s_freeinodescount --;
-       inode->i_sb->s_dirt = 1;
+       sb->u.ext_sb.s_freeinodescount --;
+       sb->s_dirt = 1;
        inode->i_count = 1;
        inode->i_nlink = 1;
-       inode->i_dev = dev;
+       inode->i_dev = sb->s_dev;
        inode->i_uid = current->euid;
        inode->i_gid = current->egid;
        inode->i_dirt = 1;
@@ -288,7 +284,7 @@ printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
 #ifdef EXTFS_DEBUG
 printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
 #endif
-       free_super (inode->i_sb);
+       unlock_super (sb);
        return inode;
 }
 
@@ -328,7 +324,7 @@ unsigned long ext_count_free_inodes(struct super_block *sb)
        }
 printk("ext_count_free_inodes: stored = %d, computed = %d\n",
        sb->u.ext_sb.s_freeinodescount, count);
-       free_super (sb);
+       unlock_super (sb);
        return count;
 #else
        return sb->u.ext_sb.s_freeinodescount;
index 7998402334f74a462a03beeb11420eb578f798b0..fe52dfb4d4ca3da98bc629f69b9b442d7557557a 100644 (file)
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
 
-int sync_dev(int dev);
-
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
-}
-
 void ext_put_inode(struct inode *inode)
 {
+       if (inode->i_nlink)
+               return;
        inode->i_size = 0;
        ext_truncate(inode);
        ext_free_inode(inode);
@@ -46,7 +39,7 @@ void ext_put_super(struct super_block *sb)
                brelse (sb->u.ext_sb.s_firstfreeinodeblock);
        if (sb->u.ext_sb.s_firstfreeblock)
                brelse (sb->u.ext_sb.s_firstfreeblock);
-       free_super(sb);
+       unlock_super(sb);
        return;
 }
 
@@ -68,7 +61,7 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
        lock_super(s);
        if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
                s->s_dev=0;
-               free_super(s);
+               unlock_super(s);
                printk("bread failed\n");
                return NULL;
        }
@@ -87,7 +80,7 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
        brelse(bh);
        if (s->s_magic != EXT_SUPER_MAGIC) {
                s->s_dev = 0;
-               free_super(s);
+               unlock_super(s);
                printk("magic match failed\n");
                return NULL;
        }
@@ -98,7 +91,7 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
                        s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
                        printk ("ext_read_super: unable to read first free block\n");
                        s->s_dev = 0;
-                       free_super(s);
+                       unlock_super(s);
                        return NULL;
                }
        if (!s->u.ext_sb.s_firstfreeinodenumber)
@@ -109,15 +102,15 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
                        printk ("ext_read_super: unable to read first free inode block\n");
                        brelse(s->u.ext_sb.s_firstfreeblock);
                        s->s_dev = 0;
-                       free_super (s);
+                       unlock_super (s);
                        return NULL;
                }
        }
-       free_super(s);
+       unlock_super(s);
        /* set up enough so that it can read an inode */
        s->s_dev = dev;
        s->s_op = &ext_sops;
-       if (!(s->s_mounted = iget(dev,EXT_ROOT_INO))) {
+       if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
                s->s_dev=0;
                printk("get root inode failed\n");
                return NULL;
@@ -235,12 +228,12 @@ repeat:
        }
        if (!create)
                return NULL;
-       tmp = ext_new_block(inode->i_dev);
+       tmp = ext_new_block(inode->i_sb);
        if (!tmp)
                return NULL;
        result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
        if (*p) {
-               ext_free_block(inode->i_dev,tmp);
+               ext_free_block(inode->i_sb,tmp);
                brelse(result);
                goto repeat;
        }
@@ -250,7 +243,8 @@ repeat:
        return result;
 }
 
-static struct buffer_head * block_getblk(struct buffer_head * bh, int nr, int create)
+static struct buffer_head * block_getblk(struct inode * inode,
+       struct buffer_head * bh, int nr, int create)
 {
        int tmp;
        unsigned long * p;
@@ -282,14 +276,14 @@ repeat:
                brelse(bh);
                return NULL;
        }
-       tmp = ext_new_block(bh->b_dev);
+       tmp = ext_new_block(inode->i_sb);
        if (!tmp) {
                brelse(bh);
                return NULL;
        }
        result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
        if (*p) {
-               ext_free_block(bh->b_dev,tmp);
+               ext_free_block(inode->i_sb,tmp);
                brelse(result);
                goto repeat;
        }
@@ -316,19 +310,19 @@ struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
        block -= 9;
        if (block<256) {
                bh = inode_getblk(inode,9,create);
-               return block_getblk(bh,block,create);
+               return block_getblk(inode,bh,block,create);
        }
        block -= 256;
        if (block<256*256) {
                bh = inode_getblk(inode,10,create);
-               bh = block_getblk(bh,block>>8,create);
-               return block_getblk(bh,block & 255,create);
+               bh = block_getblk(inode,bh,block>>8,create);
+               return block_getblk(inode,bh,block & 255,create);
        }
        block -= 256*256;
        bh = inode_getblk(inode,11,create);
-       bh = block_getblk(bh,block>>16,create);
-       bh = block_getblk(bh,(block>>8) & 255,create);
-       return block_getblk(bh,block & 255,create);
+       bh = block_getblk(inode,bh,block>>16,create);
+       bh = block_getblk(inode,bh,(block>>8) & 255,create);
+       return block_getblk(inode,bh,block & 255,create);
 }
 
 struct buffer_head * ext_bread(struct inode * inode, int block, int create)
index 6be0c48feec04f00e95183c4c532ecb4526eae85..d92cab8159edbc80c8dfbfe01ccec282f9d2caa7 100644 (file)
@@ -169,7 +169,7 @@ int ext_lookup(struct inode * dir,const char * name, int len,
        }
        ino = de->inode;
        brelse(bh);
-       if (!(*result = iget(dir->i_dev,ino))) {
+       if (!(*result = iget(dir->i_sb,ino))) {
                iput(dir);
                return -EACCES;
        }
@@ -307,7 +307,7 @@ int ext_create(struct inode * dir,const char * name, int len, int mode,
        *result = NULL;
        if (!dir)
                return -ENOENT;
-       inode = ext_new_inode(dir->i_dev);
+       inode = ext_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -345,7 +345,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
                iput(dir);
                return -EEXIST;
        }
-       inode = ext_new_inode(dir->i_dev);
+       inode = ext_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -403,7 +403,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
                iput(dir);
                return -EEXIST;
        }
-       inode = ext_new_inode(dir->i_dev);
+       inode = ext_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -509,9 +509,9 @@ static int empty_dir(struct inode * inode)
 static inline void ext_merge_entries (struct ext_dir_entry * de,
        struct ext_dir_entry * pde, struct ext_dir_entry * nde)
 {
-       if (nde->inode)
+       if (nde && !nde->inode)
                de->rec_len += nde->rec_len;
-       if (pde->inode)
+       if (pde && !pde->inode)
                pde->rec_len += de->rec_len;
 }
 
@@ -528,7 +528,7 @@ int ext_rmdir(struct inode * dir, const char * name, int len)
        if (!bh)
                goto end_rmdir;
        retval = -EPERM;
-       if (!(inode = iget(dir->i_dev, de->inode)))
+       if (!(inode = iget(dir->i_sb, de->inode)))
                goto end_rmdir;
        if ((dir->i_mode & S_ISVTX) && current->euid &&
           inode->i_uid != current->euid)
@@ -580,7 +580,7 @@ int ext_unlink(struct inode * dir, const char * name, int len)
        bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
        if (!bh)
                goto end_unlink;
-       if (!(inode = iget(dir->i_dev, de->inode)))
+       if (!(inode = iget(dir->i_sb, de->inode)))
                goto end_unlink;
        retval = -EPERM;
        if ((dir->i_mode & S_ISVTX) && !suser() &&
@@ -617,7 +617,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
        int i;
        char c;
 
-       if (!(inode = ext_new_inode(dir->i_dev))) {
+       if (!(inode = ext_new_inode(dir->i_sb))) {
                iput(dir);
                return -ENOSPC;
        }
@@ -674,6 +674,11 @@ int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int
                iput(dir);
                return -EPERM;
        }
+       if (oldinode->i_nlink > 32000) {
+               iput(oldinode);
+               iput(dir);
+               return -EMLINK;
+       }
        bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
        if (bh) {
                brelse(bh);
@@ -768,7 +773,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = iget(old_dir->i_dev, old_de->inode);
+       old_inode = iget(old_dir->i_sb, old_de->inode);
        if (!old_inode)
                goto end_rename;
        retval = -EPERM;
@@ -778,7 +783,7 @@ start_up:
                goto end_rename;
        new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
        if (new_bh) {
-               new_inode = iget(new_dir->i_dev, new_de->inode);
+               new_inode = iget(new_dir->i_sb, new_de->inode);
                if (!new_inode) {
                        brelse(new_bh);
                        new_bh = NULL;
index 9d94f6418abbd1353fb2f5fe7a66a3909cb1d0e8..d7a65063a0f20c736ede037a67f9edfccfc3e8b9 100644 (file)
@@ -56,7 +56,7 @@ repeat:
                *p = 0;
                inode->i_dirt = 1;
                brelse(bh);
-               ext_free_block(inode->i_dev,tmp);
+               ext_free_block(inode->i_sb,tmp);
        }
        return retry;
 }
@@ -105,7 +105,7 @@ repeat:
                *ind = 0;
                ind_bh->b_dirt = 1;
                brelse(bh);
-               ext_free_block(inode->i_dev,tmp);
+               ext_free_block(inode->i_sb,tmp);
        }
        ind = (unsigned long *) ind_bh->b_data;
        for (i = 0; i < 256; i++)
@@ -118,7 +118,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        inode->i_dirt = 1;
-                       ext_free_block(inode->i_dev,tmp);
+                       ext_free_block(inode->i_sb,tmp);
                }
        brelse(ind_bh);
        return retry;
@@ -168,7 +168,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        inode->i_dirt = 1;
-                       ext_free_block(inode->i_dev,tmp);
+                       ext_free_block(inode->i_sb,tmp);
                }
        brelse(dind_bh);
        return retry;
@@ -215,7 +215,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        inode->i_dirt = 1;
-                       ext_free_block(inode->i_dev,tmp);
+                       ext_free_block(inode->i_sb,tmp);
                }
        brelse(tind_bh);
        return retry;
index b30fca09737b303755bdc3b3272e332478212094..30e2e706e2f1bb0f290b7250585b227ab5880e39 100644 (file)
 
 #include <asm/system.h>
 
-struct inode inode_table[NR_INODE]={{0,},};
+static struct inode inode_table[NR_INODE];
+
+void inode_init(void)
+{
+       memset(inode_table,0,sizeof(inode_table));      
+}
+
+int fs_may_mount(dev_t dev)
+{
+       struct inode * inode;
+
+       for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
+               if (inode->i_dev != dev)
+                       continue;
+               if (inode->i_count || inode->i_dirt || inode->i_lock)
+                       return 0;
+               inode->i_dev = 0;
+       }
+       return 1;
+}
+
+int fs_may_umount(dev_t dev, struct inode * mount_root)
+{
+       struct inode * inode;
+
+       for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++)
+               if (inode->i_dev==dev && inode->i_count)
+                       if (inode == mount_root && inode->i_count == 1)
+                               continue;
+                       else
+                               return 0;
+       return 1;
+}
+
+/*
+ * The "new" scheduling primitives (new as of 0.97 or so) allow this to
+ * be done without disabling interrupts (other than in the actual queue
+ * updating things: only a couple of 386 instructions). This should be
+ * much better for interrupt latency.
+ */
+static void __wait_on_inode(struct inode * inode)
+{
+       add_wait_queue(&inode->i_wait,&current->wait);
+repeat:
+       current->state = TASK_UNINTERRUPTIBLE;
+       if (inode->i_lock) {
+               schedule();
+               goto repeat;
+       }
+       remove_wait_queue(&inode->i_wait,&current->wait);
+       current->state = TASK_RUNNING;
+}
 
 static inline void wait_on_inode(struct inode * inode)
 {
-       cli();
-       while (inode->i_lock)
-               sleep_on(&inode->i_wait);
-       sti();
+       if (inode->i_lock)
+               __wait_on_inode(inode);
 }
 
 static inline void lock_inode(struct inode * inode)
 {
-       cli();
-       while (inode->i_lock)
-               sleep_on(&inode->i_wait);
-       inode->i_lock=1;
-       sti();
+       wait_on_inode(inode);
+       inode->i_lock = 1;
 }
 
 static inline void unlock_inode(struct inode * inode)
 {
-       inode->i_lock=0;
+       inode->i_lock = 0;
        wake_up(&inode->i_wait);
 }
 
@@ -41,8 +87,8 @@ static void write_inode(struct inode * inode)
 {
        if (!inode->i_dirt)
                return;
-       inode->i_dirt = 0;
        lock_inode(inode);
+       inode->i_dirt = 0;
        if (inode->i_dev && inode->i_sb &&
            inode->i_sb->s_op && inode->i_sb->s_op->write_inode)
                inode->i_sb->s_op->write_inode(inode);
@@ -74,7 +120,7 @@ int bmap(struct inode * inode, int block)
        return 0;
 }
 
-void invalidate_inodes(int dev)
+void invalidate_inodes(dev_t dev)
 {
        int i;
        struct inode * inode;
@@ -92,7 +138,7 @@ void invalidate_inodes(int dev)
        }
 }
 
-void sync_inodes(void)
+void sync_inodes(dev_t dev)
 {
        int i;
        struct inode * inode;
@@ -134,11 +180,10 @@ repeat:
                inode->i_count--;
                return;
        }
-       if (!inode->i_nlink) {
-               if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
-                       inode->i_sb->s_op->put_inode(inode);
+       if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
+               inode->i_sb->s_op->put_inode(inode);
+               if (!inode->i_nlink)
                        return;
-               }
        }
        if (inode->i_dirt) {
                write_inode(inode);     /* we can sleep - so do again */
@@ -201,21 +246,21 @@ struct inode * get_pipe_inode(void)
        return inode;
 }
 
-struct inode * iget(int dev,int nr)
+struct inode * iget(struct super_block * sb,int nr)
 {
        struct inode * inode, * empty;
 
-       if (!dev)
-               panic("iget with dev==0");
+       if (!sb)
+               panic("iget with sb==NULL");
        empty = get_empty_inode();
        inode = inode_table;
        while (inode < NR_INODE+inode_table) {
-               if (inode->i_dev != dev || inode->i_ino != nr) {
+               if (inode->i_sb != sb || inode->i_ino != nr) {
                        inode++;
                        continue;
                }
                wait_on_inode(inode);
-               if (inode->i_dev != dev || inode->i_ino != nr) {
+               if (inode->i_sb != sb || inode->i_ino != nr) {
                        inode = inode_table;
                        continue;
                }
@@ -247,14 +292,10 @@ struct inode * iget(int dev,int nr)
        if (!empty)
                return (NULL);
        inode = empty;
-       if (!(inode->i_sb = get_super(dev))) {
-               printk("iget: gouldn't get super-block\n\t");
-               iput(inode);
-               return NULL;
-       }
-       inode->i_dev = dev;
+       inode->i_sb = sb;
+       inode->i_dev = sb->s_dev;
        inode->i_ino = nr;
-       inode->i_flags = inode->i_sb->s_flags;
+       inode->i_flags = sb->s_flags;
        read_inode(inode);
        return inode;
 }
index cc66d7fb3febaa6802b63e35ce2b94930c6f8421..c1cf6a1e093f5cff7cece896ec84a8b9a14a3e71 100644 (file)
@@ -73,13 +73,12 @@ static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
        return(sum);
 }
 
-void minix_free_block(int dev, int block)
+void minix_free_block(struct super_block * sb, int block)
 {
-       struct super_block * sb;
        struct buffer_head * bh;
        unsigned int bit,zone;
 
-       if (!(sb = get_super(dev))) {
+       if (!sb) {
                printk("trying to free block on nonexistent device\n");
                return;
        }
@@ -88,7 +87,7 @@ void minix_free_block(int dev, int block)
                printk("trying to free block not in datazone\n");
                return;
        }
-       bh = get_hash_table(dev,block,BLOCK_SIZE);
+       bh = get_hash_table(sb->s_dev,block,BLOCK_SIZE);
        if (bh)
                bh->b_dirt=0;
        brelse(bh);
@@ -101,18 +100,17 @@ void minix_free_block(int dev, int block)
                return;
        }
        if (clear_bit(bit,bh->b_data))
-               printk("free_block (%04x:%d): bit already cleared\n",dev,block);
+               printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
        bh->b_dirt = 1;
        return;
 }
 
-int minix_new_block(int dev)
+int minix_new_block(struct super_block * sb)
 {
        struct buffer_head * bh;
-       struct super_block * sb;
        int i,j;
 
-       if (!(sb = get_super(dev))) {
+       if (!sb) {
                printk("trying to get new block from nonexistant device\n");
                return 0;
        }
@@ -132,7 +130,7 @@ repeat:
        j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
        if (j >= sb->u.minix_sb.s_nzones)
                return 0;
-       if (!(bh=getblk(dev,j,BLOCK_SIZE))) {
+       if (!(bh = getblk(sb->s_dev,j,BLOCK_SIZE))) {
                printk("new_block: cannot get block");
                return 0;
        }
@@ -189,19 +187,15 @@ void minix_free_inode(struct inode * inode)
        memset(inode,0,sizeof(*inode));
 }
 
-struct inode * minix_new_inode(int dev)
+struct inode * minix_new_inode(struct super_block * sb)
 {
        struct inode * inode;
        struct buffer_head * bh;
        int i,j;
 
-       if (!(inode=get_empty_inode()))
+       if (!sb || !(inode = get_empty_inode()))
                return NULL;
-       if (!(inode->i_sb = get_super(dev))) {
-               printk("new_inode: unknown device\n");
-               iput(inode);
-               return NULL;
-       }
+       inode->i_sb = sb;
        inode->i_flags = inode->i_sb->s_flags;
        j = 8192;
        for (i=0 ; i<8 ; i++)
@@ -220,7 +214,7 @@ struct inode * minix_new_inode(int dev)
        bh->b_dirt = 1;
        inode->i_count = 1;
        inode->i_nlink = 1;
-       inode->i_dev = dev;
+       inode->i_dev = sb->s_dev;
        inode->i_uid = current->euid;
        inode->i_gid = current->egid;
        inode->i_dirt = 1;
index 48ca216e59902dde2c77277d941bef5bdd1fb530..57fb4d5f1685a31184018b4d424266382e1cdb6d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #define        NBUF    16
 
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
 
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
-}
-
 static int minix_file_read(struct inode *, struct file *, char *, int);
 static int minix_file_write(struct inode *, struct file *, char *, int);
 
index 7a188f1bec041d3737225d1ca66effca5f7b7bce..651f397d375c89019bc5451e2c3ccaa9a6046a89 100644 (file)
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
 
-int sync_dev(int dev);
-
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
-}
-
 void minix_put_inode(struct inode *inode)
 {
+       if (inode->i_nlink)
+               return;
        inode->i_size = 0;
        minix_truncate(inode);
        minix_free_inode(inode);
@@ -41,7 +34,7 @@ void minix_put_super(struct super_block *sb)
                brelse(sb->u.minix_sb.s_imap[i]);
        for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++)
                brelse(sb->u.minix_sb.s_zmap[i]);
-       free_super(sb);
+       unlock_super(sb);
        return;
 }
 
@@ -63,7 +56,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
        lock_super(s);
        if (!(bh = bread(dev,1,BLOCK_SIZE))) {
                s->s_dev=0;
-               free_super(s);
+               unlock_super(s);
                printk("bread failed\n");
                return NULL;
        }
@@ -80,7 +73,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
        brelse(bh);
        if (s->s_magic != MINIX_SUPER_MAGIC) {
                s->s_dev = 0;
-               free_super(s);
+               unlock_super(s);
                printk("magic match failed\n");
                return NULL;
        }
@@ -105,25 +98,26 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
                for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
                        brelse(s->u.minix_sb.s_zmap[i]);
                s->s_dev=0;
-               free_super(s);
+               unlock_super(s);
                printk("block failed\n");
                return NULL;
        }
        s->u.minix_sb.s_imap[0]->b_data[0] |= 1;
        s->u.minix_sb.s_zmap[0]->b_data[0] |= 1;
-       free_super(s);
        /* set up enough so that it can read an inode */
        s->s_dev = dev;
        s->s_op = &minix_sops;
-       if (!(s->s_mounted = iget(dev,MINIX_ROOT_INO))) {
-               s->s_dev=0;
+       s->s_mounted = iget(s,MINIX_ROOT_INO);
+       unlock_super(s);
+       if (!s->s_mounted) {
+               s->s_dev = 0;
                printk("get root inode failed\n");
                return NULL;
        }
        return s;
 }
 
-void minix_statfs (struct super_block *sb, struct statfs *buf)
+void minix_statfs(struct super_block *sb, struct statfs *buf)
 {
        long tmp;
 
@@ -200,12 +194,12 @@ repeat:
        }
        if (!create)
                return NULL;
-       tmp = minix_new_block(inode->i_dev);
+       tmp = minix_new_block(inode->i_sb);
        if (!tmp)
                return NULL;
        result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
        if (*p) {
-               minix_free_block(inode->i_dev,tmp);
+               minix_free_block(inode->i_sb,tmp);
                brelse(result);
                goto repeat;
        }
@@ -215,7 +209,8 @@ repeat:
        return result;
 }
 
-static struct buffer_head * block_getblk(struct buffer_head * bh, int nr, int create)
+static struct buffer_head * block_getblk(struct inode * inode, 
+       struct buffer_head * bh, int nr, int create)
 {
        int tmp;
        unsigned short *p;
@@ -247,14 +242,14 @@ repeat:
                brelse(bh);
                return NULL;
        }
-       tmp = minix_new_block(bh->b_dev);
+       tmp = minix_new_block(inode->i_sb);
        if (!tmp) {
                brelse(bh);
                return NULL;
        }
        result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
        if (*p) {
-               minix_free_block(bh->b_dev,tmp);
+               minix_free_block(inode->i_sb,tmp);
                brelse(result);
                goto repeat;
        }
@@ -281,12 +276,12 @@ struct buffer_head * minix_getblk(struct inode * inode, int block, int create)
        block -= 7;
        if (block < 512) {
                bh = inode_getblk(inode,7,create);
-               return block_getblk(bh,block,create);
+               return block_getblk(inode, bh, block, create);
        }
        block -= 512;
        bh = inode_getblk(inode,8,create);
-       bh = block_getblk(bh,block>>9,create);
-       return block_getblk(bh,block & 511,create);
+       bh = block_getblk(inode, bh, block>>9, create);
+       return block_getblk(inode, bh, block & 511, create);
 }
 
 struct buffer_head * minix_bread(struct inode * inode, int block, int create)
index bcc5f3f8fd1b77fb9db37de02a69064ab6591779..a5e098d18f703c706d896d00f64530575d4e9c77 100644 (file)
@@ -119,7 +119,7 @@ int minix_lookup(struct inode * dir,const char * name, int len,
        }
        ino = de->inode;
        brelse(bh);
-       if (!(*result = iget(dir->i_dev,ino))) {
+       if (!(*result = iget(dir->i_sb,ino))) {
                iput(dir);
                return -EACCES;
        }
@@ -200,7 +200,7 @@ int minix_create(struct inode * dir,const char * name, int len, int mode,
        *result = NULL;
        if (!dir)
                return -ENOENT;
-       inode = minix_new_inode(dir->i_dev);
+       inode = minix_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -238,7 +238,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
                iput(dir);
                return -EEXIST;
        }
-       inode = minix_new_inode(dir->i_dev);
+       inode = minix_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -296,7 +296,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
                iput(dir);
                return -EEXIST;
        }
-       inode = minix_new_inode(dir->i_dev);
+       inode = minix_new_inode(dir->i_sb);
        if (!inode) {
                iput(dir);
                return -ENOSPC;
@@ -396,7 +396,7 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
        if (!bh)
                goto end_rmdir;
        retval = -EPERM;
-       if (!(inode = iget(dir->i_dev, de->inode)))
+       if (!(inode = iget(dir->i_sb, de->inode)))
                goto end_rmdir;
        if ((dir->i_mode & S_ISVTX) && current->euid &&
           inode->i_uid != current->euid)
@@ -446,7 +446,7 @@ int minix_unlink(struct inode * dir, const char * name, int len)
        bh = minix_find_entry(dir,name,len,&de);
        if (!bh)
                goto end_unlink;
-       if (!(inode = iget(dir->i_dev, de->inode)))
+       if (!(inode = iget(dir->i_sb, de->inode)))
                goto end_unlink;
        retval = -EPERM;
        if ((dir->i_mode & S_ISVTX) && !suser() &&
@@ -481,7 +481,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
        int i;
        char c;
 
-       if (!(inode = minix_new_inode(dir->i_dev))) {
+       if (!(inode = minix_new_inode(dir->i_sb))) {
                iput(dir);
                return -ENOSPC;
        }
@@ -538,6 +538,11 @@ int minix_link(struct inode * oldinode, struct inode * dir, const char * name, i
                iput(dir);
                return -EPERM;
        }
+       if (oldinode->i_nlink > 126) {
+               iput(oldinode);
+               iput(dir);
+               return -EMLINK;
+       }
        bh = minix_find_entry(dir,name,len,&de);
        if (bh) {
                brelse(bh);
@@ -630,7 +635,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = iget(old_dir->i_dev, old_de->inode);
+       old_inode = iget(old_dir->i_sb, old_de->inode);
        if (!old_inode)
                goto end_rename;
        retval = -EPERM;
@@ -640,7 +645,7 @@ start_up:
                goto end_rename;
        new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
        if (new_bh) {
-               new_inode = iget(new_dir->i_dev, new_de->inode);
+               new_inode = iget(new_dir->i_sb, new_de->inode);
                if (!new_inode) {
                        brelse(new_bh);
                        new_bh = NULL;
index 276e5dfe09aa84bc8442465d9e0a621434848f71..29f4c6db2c97b0b40deae7c3c60cafdbd42d56e9 100644 (file)
@@ -50,7 +50,7 @@ repeat:
                *p = 0;
                inode->i_dirt = 1;
                brelse(bh);
-               minix_free_block(inode->i_dev,tmp);
+               minix_free_block(inode->i_sb,tmp);
        }
        return retry;
 }
@@ -99,7 +99,7 @@ repeat:
                *ind = 0;
                ind_bh->b_dirt = 1;
                brelse(bh);
-               minix_free_block(inode->i_dev,tmp);
+               minix_free_block(inode->i_sb,tmp);
        }
        ind = (unsigned short *) ind_bh->b_data;
        for (i = 0; i < 512; i++)
@@ -111,7 +111,7 @@ repeat:
                else {
                        tmp = *p;
                        *p = 0;
-                       minix_free_block(inode->i_dev,tmp);
+                       minix_free_block(inode->i_sb,tmp);
                }
        brelse(ind_bh);
        return retry;
@@ -158,7 +158,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        inode->i_dirt = 1;
-                       minix_free_block(inode->i_dev,tmp);
+                       minix_free_block(inode->i_sb,tmp);
                }
        brelse(dind_bh);
        return retry;
index 5b0ff4281ca252b5f379bb3e9a1a885d0695542a..16e4d1e56ee47628ae10cdd19d8eb8ca3cb1048e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #include <asm/segment.h>
 
@@ -18,6 +19,8 @@ void msdos_put_inode(struct inode *inode)
 {
        struct inode *depend;
 
+       if (inode->i_nlink)
+               return;
        inode->i_size = 0;
        msdos_truncate(inode);
        depend = MSDOS_I(inode)->i_depend;
@@ -40,7 +43,7 @@ void msdos_put_super(struct super_block *sb)
        cache_inval_dev(sb->s_dev);
        lock_super(sb);
        sb->s_dev = 0;
-       free_super(sb);
+       unlock_super(sb);
        return;
 }
 
@@ -55,32 +58,6 @@ static struct super_operations msdos_sops = {
 };
 
 
-static unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
-       unsigned long result = 0,value;
-
-       if (!base) {
-               base = 10;
-               if (*cp == '0') {
-                       base = 8;
-                       cp++;
-                       if ((*cp == 'x') && isxdigit(cp[1])) {
-                               cp++;
-                               base = 16;
-                       }
-               }
-       }
-       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
-           ? toupper(*cp) : *cp)-'A'+10) < base) {
-               result = result*base + value;
-               cp++;
-       }
-       if (endp)
-               *endp = (char *)cp;
-       return result;
-}
-
-
 static int parse_options(char *options,char *check,char *conversion,uid_t *uid, gid_t *gid, int *umask)
 {
        char *this,*value;
@@ -155,7 +132,7 @@ struct super_block *msdos_read_super(struct super_block *s,void *data)
        cache_init();
        lock_super(s);
        bh = bread(s->s_dev, 0, BLOCK_SIZE);
-       free_super(s);
+       unlock_super(s);
        if (bh == NULL) {
                s->s_dev = 0;
                printk("MSDOS bread failed\n");
@@ -202,7 +179,7 @@ printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,se=%d,ts=%d]\n",
        MSDOS_SB(s)->free_clusters = -1; /* don't know yet */
        MSDOS_SB(s)->fat_wait = NULL;
        MSDOS_SB(s)->fat_lock = 0;
-       if (!(s->s_mounted = iget(s->s_dev,MSDOS_ROOT_INO))) {
+       if (!(s->s_mounted = iget(s,MSDOS_ROOT_INO))) {
                s->s_dev = 0;
                printk("get root inode failed\n");
                return NULL;
index 8b4acc74376202f3408d7fd602245bb09ed39816..40d224384004c864117afd508893fa30f640aab1 100644 (file)
@@ -282,7 +282,7 @@ int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh,
                }
                else if (!de->name[0] || ((unsigned char *) (de->name))[0] ==
                            DELETED_FLAG) {
-                               if (!(inode = iget(dir->i_dev,*ino))) break;
+                               if (!(inode = iget(dir->i_sb,*ino))) break;
                                if (!MSDOS_I(inode)->i_busy) {
                                        iput(inode);
                                        break;
index 37b4aa338f2f548554d2d315682707e7c5dc3358..80d51942de2bb2e8f52c012052049eb3896b3415 100644 (file)
@@ -131,7 +131,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
                ino = msdos_parent_ino(dir,0);
                iput(dir);
                if (ino < 0) return ino;
-               if (!(*result = iget(dir->i_dev,ino))) return -EACCES;
+               if (!(*result = iget(dir->i_sb,ino))) return -EACCES;
                return 0;
        }
        if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) {
@@ -140,7 +140,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
        }
        if (bh) brelse(bh);
 /* printk("lookup: ino=%d\r\n",ino); */
-       if (!(*result = iget(dir->i_dev,ino))) {
+       if (!(*result = iget(dir->i_sb,ino))) {
                iput(dir);
                return -EACCES;
        }
@@ -152,7 +152,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
        while (MSDOS_I(*result)->i_old) {
                next = MSDOS_I(*result)->i_old;
                iput(*result);
-               if (!(*result = iget(next->i_dev,next->i_ino)))
+               if (!(*result = iget(next->i_sb,next->i_ino)))
                        panic("msdos_lookup: Can't happen");
        }
        iput(dir);
@@ -180,7 +180,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
        date_unix2dos(CURRENT_TIME,&de->time,&de->date);
        de->size = 0;
        bh->b_dirt = 1;
-       if (*result = iget(dir->i_dev,ino)) msdos_read_inode(*result);
+       if (*result = iget(dir->i_sb,ino)) msdos_read_inode(*result);
        brelse(bh);
        if (!*result) return -EIO;
        (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
@@ -308,7 +308,7 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
            get_fs_byte(name+1) == '.'))) goto rmdir_done;
        if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
        res = -ENOENT;
-       if (!(inode = iget(dir->i_dev,ino))) goto rmdir_done;
+       if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
        res = -ENOTDIR;
        if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
        res = -EBUSY;
@@ -351,7 +351,7 @@ int msdos_unlink(struct inode *dir,const char *name,int len)
        inode = NULL;
        if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
                goto unlink_done;
-       if (!(inode = iget(dir->i_dev,ino))) {
+       if (!(inode = iget(dir->i_sb,ino))) {
                res = -ENOENT;
                goto unlink_done;
        }
@@ -389,7 +389,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
                return -ENOENT;
        }
        if (exists) {
-               if (!(new_inode = iget(new_dir->i_dev,new_ino))) {
+               if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
                        brelse(new_bh);
                        return -EIO;
                }
@@ -409,7 +409,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
        memcpy(old_de->name,new_name,MSDOS_NAME);
        old_bh->b_dirt = 1;
        if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
-               if (old_inode = iget(old_dir->i_dev,old_ino)) {
+               if (old_inode = iget(old_dir->i_sb,old_ino)) {
                        msdos_read_inode(old_inode);
                        iput(old_inode);
                }
@@ -429,20 +429,20 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
 
        if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
        if (old_ino == new_dir->i_ino) return -EINVAL;
-       if (!(walk = iget(new_dir->i_dev,new_dir->i_ino))) return -EIO;
+       if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
        while (walk->i_ino != MSDOS_ROOT_INO) {
                ino = msdos_parent_ino(walk,1);
                iput(walk);
                if (ino < 0) return ino;
                if (ino == old_ino) return -EINVAL;
-               if (!(walk = iget(new_dir->i_dev,ino))) return -EIO;
+               if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
        }
        iput(walk);
        if ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) < 0)
            return error;
        exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)
            >= 0;
-       if (!(old_inode = iget(old_dir->i_dev,old_ino))) {
+       if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
                brelse(free_bh);
                if (exists) brelse(new_bh);
                return -EIO;
@@ -455,7 +455,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
        }
        new_inode = NULL; /* to make GCC happy */
        if (exists) {
-               if (!(new_inode = iget(new_dir->i_dev,new_ino))) {
+               if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
                        iput(old_inode);
                        brelse(new_bh);
                        return -EIO;
@@ -474,7 +474,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
        }
        memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
        memcpy(free_de->name,new_name,MSDOS_NAME);
-       if (!(free_inode = iget(new_dir->i_dev,free_ino))) {
+       if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
                free_de->name[0] = DELETED_FLAG;
 /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
                brelse(free_bh);
@@ -502,7 +502,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
        if (S_ISDIR(old_inode->i_mode)) {
                if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
                    &dotdot_de,&dotdot_ino)) < 0) goto rename_done;
-               if (!(dotdot_inode = iget(old_inode->i_dev,dotdot_ino))) {
+               if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
                        brelse(dotdot_bh);
                        error = -EIO;
                        goto rename_done;
index 648c3f25ee124a6c4c29c98c183e9d1a26c3acaa..17c21859fe5ef9a668555b76886ff4d0a60d010d 100644 (file)
@@ -71,6 +71,10 @@ int lookup(struct inode * dir,const char * name, int len,
        }
        if (!dir)
                return -ENOENT;
+       if (!dir->i_op || !dir->i_op->lookup) {
+               iput(dir);
+               return -ENOTDIR;
+       }
        if (!permission(dir,MAY_EXEC)) {
                iput(dir);
                return -EACCES;
@@ -79,10 +83,6 @@ int lookup(struct inode * dir,const char * name, int len,
                *result = dir;
                return 0;
        }
-       if (!dir->i_op || !dir->i_op->lookup) {
-               iput(dir);
-               return -ENOENT;
-       }
        return dir->i_op->lookup(dir,name,len,result);
 }
 
@@ -293,7 +293,7 @@ int open_namei(const char * pathname, int flag, int mode,
        return 0;
 }
 
-int do_mknod(const char * filename, int mode, int dev)
+int do_mknod(const char * filename, int mode, dev_t dev)
 {
        const char * basename;
        int namelen, error;
@@ -321,7 +321,7 @@ int do_mknod(const char * filename, int mode, int dev)
        return dir->i_op->mknod(dir,basename,namelen,mode,dev);
 }
 
-int sys_mknod(const char * filename, int mode, int dev)
+int sys_mknod(const char * filename, int mode, dev_t dev)
 {
        if (S_ISFIFO(mode) || suser())
                return do_mknod(filename,mode,dev);
@@ -373,7 +373,7 @@ int sys_rmdir(const char * name)
                iput(dir);
                return -EROFS;
        }
-       if (!permission(dir,MAY_WRITE)) {
+       if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
                iput(dir);
                return -EACCES;
        }
@@ -401,7 +401,7 @@ int sys_unlink(const char * name)
                iput(dir);
                return -EROFS;
        }
-       if (!permission(dir,MAY_WRITE)) {
+       if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
                iput(dir);
                return -EACCES;
        }
index 86f105de0ff05e93eee471c36d3b174e3ea3e46f..1193e17370311646325fc8182670836571741420 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -418,6 +418,28 @@ int sys_close(unsigned int fd)
        return (close_fp (filp));
 }
 
+/*
+ * This routine is used by vhangup.  It send's sigkill to everything
+ * waiting on a particular wait_queue.  It assumes root privledges.
+ * We don't want to destroy the wait queue here, because the caller
+ * should call wake_up immediately after calling kill_wait.
+ */
+static void kill_wait(struct wait_queue **q, int sig)
+{
+       struct wait_queue *next;
+       struct wait_queue *tmp;
+       struct task_struct *p;
+
+       if (!q || !(next = *q))
+               return;
+       do { 
+               tmp = next;
+               next = tmp->next;
+               if (p = tmp->task)
+                       send_sig (sig, p , 1);
+       } while (next && next != *q);
+}
+
 /*
  * This routine looks through all the process's and closes any
  * references to the current processes tty.  To avoid problems with
@@ -430,10 +452,11 @@ int sys_close(unsigned int fd)
  */
 int sys_vhangup(void)
 {
-       int i,j;
+       int j;
+       struct task_struct ** process;
        struct file *filep;
+       struct inode *inode;
        struct tty_struct *tty;
-       extern void kill_wait (struct wait_queue **q, int signal);
        extern int kill_pg (int pgrp, int sig, int priv);
 
        if (!suser())
@@ -444,33 +467,34 @@ int sys_vhangup(void)
        if (current->tty < 0)
                return 0;
 
-       for (i = 0; i < NR_TASKS; i++) {
-               if (task[i] == NULL)
-                       continue;
+       for (process = task + 0; process < task + NR_TASKS; process++) {
                for (j = 0; j < NR_OPEN; j++) {
-                       filep = task[i]->filp[j];
-                       if (!filep)
+                       if (!*process)
+                               break;
+                       if (!(filep = (*process)->filp[j]))
                                continue;
-                       if (!S_ISCHR(filep->f_inode->i_mode))
+                       if (!(inode = filep->f_inode))
                                continue;
-                       if ((MAJOR(filep->f_inode->i_rdev) == 5 ||
-                            MAJOR(filep->f_inode->i_rdev) == 4 ) &&
+                       if (!S_ISCHR(inode->i_mode))
+                               continue;
+                       if ((MAJOR(inode->i_rdev) == 5 ||
+                            MAJOR(inode->i_rdev) == 4 ) &&
                            (MAJOR(filep->f_rdev) == 4 &&
                             MINOR(filep->f_rdev) == MINOR (current->tty))) {
                  /* so now we have found something to close.  We
                     need to kill every process waiting on the
                     inode. */
-                               task[i]->filp[j] = NULL;
-                               kill_wait (&filep->f_inode->i_wait, SIGKILL);
+                               (*process)->filp[j] = NULL;
+                               kill_wait (&inode->i_wait, SIGKILL);
 
                  /* now make sure they are awake before we close the
                     file. */
 
-                               wake_up (&filep->f_inode->i_wait);
+                               wake_up (&inode->i_wait);
 
                  /* finally close the file. */
 
-                               current->close_on_exec &= ~(1<<j);
+                               (*process)->close_on_exec &= ~(1<<j);
                                close_fp (filep);
                        }
                }
@@ -478,15 +502,17 @@ int sys_vhangup(void)
           But we can't touch current->tty until after the
           loop is complete. */
 
-               if (task[i]->tty == current->tty && task[i] != current) {
-                       task[i]->tty = -1;
+               if (*process && (*process)->tty == current->tty && *process != current) {
+                       (*process)->tty = -1;
                }
        }
    /* need to do tty->session = 0 */
        tty = TTY_TABLE(MINOR(current->tty));
-       tty->session = 0;
-       tty->pgrp = -1;
-       current->tty = -1;
+       if (tty) {
+               tty->session = 0;
+               tty->pgrp = -1;
+               current->tty = -1;
+       }
        return 0;
 }
 
index 83a66b89ca48f2e1c2864ca27d1f2365d77ab65f..6c5dd2eaff774ba6fbf749ef42aea2a3b057f662 100644 (file)
@@ -120,7 +120,7 @@ static int proc_lookupbase(struct inode * dir,const char * name, int len,
                iput(dir);
                return -ENOENT;
        }
-       if (!(*result = iget(dir->i_dev,ino))) {
+       if (!(*result = iget(dir->i_sb,ino))) {
                iput(dir);
                return -ENOENT;
        }
index 9ddf1d7654c2fe096bca0c4a0d75a79116382768..5aa841eac4fba446c7510a626f3802a1fd3e953a 100644 (file)
@@ -53,7 +53,8 @@ static int proc_lookupfd(struct inode * dir,const char * name, int len,
 {
        unsigned int ino, pid, fd, c;
        struct task_struct * p;
-       int i, dev;
+       struct super_block * sb;
+       int i;
 
        *result = NULL;
        ino = dir->i_ino;
@@ -62,6 +63,7 @@ static int proc_lookupfd(struct inode * dir,const char * name, int len,
        ino -= 7;
        if (!dir)
                return -ENOENT;
+       sb = dir->i_sb;
        if (!pid || ino > 1 || !S_ISDIR(dir->i_mode)) {
                iput(dir);
                return -ENOENT;
@@ -72,14 +74,13 @@ static int proc_lookupfd(struct inode * dir,const char * name, int len,
                        *result = dir;
                        return 0;
                }
-               if (!(*result = iget(dir->i_dev,(pid << 16)+2))) {
+               if (!(*result = iget(sb,(pid << 16)+2))) {
                        iput(dir);
                        return -ENOENT;
                }
                iput(dir);
                return 0;
        }
-       dev = dir->i_dev;
        iput(dir);
        fd = 0;
        while (len-- > 0) {
@@ -110,7 +111,7 @@ static int proc_lookupfd(struct inode * dir,const char * name, int len,
                        return -ENOENT;
                ino = (pid << 16) + 0x200 + fd;
        }
-       if (!(*result = iget(dev,ino)))
+       if (!(*result = iget(sb,ino)))
                return -ENOENT;
        return 0;
 }
index c79d8ddf25941cad1336fe8185a9966a7f2b3d65..e4303b41fc1e45b9081bb8c8756e882284a8cf4c 100644 (file)
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
 
 void proc_put_inode(struct inode *inode)
 {
+       if (inode->i_nlink)
+               return;
        inode->i_size = 0;
 }
 
@@ -23,7 +26,7 @@ void proc_put_super(struct super_block *sb)
 {
        lock_super(sb);
        sb->s_dev = 0;
-       free_super(sb);
+       unlock_super(sb);
 }
 
 static struct super_operations proc_sops = { 
@@ -37,16 +40,13 @@ static struct super_operations proc_sops = {
 
 struct super_block *proc_read_super(struct super_block *s,void *data)
 {
-       int dev=s->s_dev;
-
        lock_super(s);
        s->s_blocksize = 1024;
        s->s_magic = PROC_SUPER_MAGIC;
-       s->s_dev = dev;
        s->s_op = &proc_sops;
-       free_super(s);
-       if (!(s->s_mounted = iget(dev,PROC_ROOT_INO))) {
-               s->s_dev=0;
+       unlock_super(s);
+       if (!(s->s_mounted = iget(s,PROC_ROOT_INO))) {
+               s->s_dev = 0;
                printk("get root inode failed\n");
                return NULL;
        }
index 848c97b26e5b539109f41c8993c4ed4356ca9893..78b536055a17e367e910fd529c8306553b63149e 100644 (file)
@@ -89,7 +89,7 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len,
                return -ENOENT;
        }
        ino = (pid << 16) + 2;
-       if (!(*result = iget(dir->i_dev,ino))) {
+       if (!(*result = iget(dir->i_sb,ino))) {
                iput(dir);
                return -ENOENT;
        }
index 7c7cd1622bee3ce43636539ebb9544e02ed32562..1062eed8d76588d295312273469e5e9e7c191a80 100644 (file)
 #include <linux/kernel.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
 
-int sync_dev(int dev);
 void wait_for_keypress(void);
 void fcntl_init_locks(void);
 
@@ -32,7 +32,7 @@ __res; })
 
 struct super_block super_block[NR_SUPER];
 /* this is initialized in init/main.c */
-int ROOT_DEV = 0;
+dev_t ROOT_DEV = 0;
 
 /* Move into include file later */
 
@@ -56,30 +56,37 @@ struct file_system_type *get_fs_type(char *name)
        return(NULL);
 }
 
-void lock_super(struct super_block * sb)
+void __wait_on_super(struct super_block * sb)
 {
-       cli();
-       while (sb->s_lock)
-               sleep_on(&(sb->s_wait));
-       sb->s_lock = 1;
-       sti();
+       add_wait_queue(&sb->s_wait,&current->wait);
+repeat:
+       current->state = TASK_UNINTERRUPTIBLE;
+       if (sb->s_lock) {
+               schedule();
+               goto repeat;
+       }
+       remove_wait_queue(&sb->s_wait,&current->wait);
+       current->state = TASK_RUNNING;
 }
 
-void free_super(struct super_block * sb)
+void sync_supers(dev_t dev)
 {
-       sb->s_lock = 0;
-       wake_up(&(sb->s_wait));
-}
+       struct super_block * sb;
 
-void wait_on_super(struct super_block * sb)
-{
-       cli();
-       while (sb->s_lock)
-               sleep_on(&(sb->s_wait));
-       sti();
+       for (sb = super_block + 0 ; sb < super_block + NR_SUPER ; sb++) {
+               if (!sb->s_dev)
+                       continue;
+               wait_on_super(sb);
+               if (!sb->s_dev || !sb->s_dirt)
+                       continue;
+               if (dev && (dev != sb->s_dev))
+                       continue;
+               if (sb->s_op && sb->s_op->write_super)
+                       sb->s_op->write_super(sb);
+       }
 }
 
-struct super_block * get_super(int dev)
+static struct super_block * get_super(dev_t dev)
 {
        struct super_block * s;
 
@@ -97,7 +104,7 @@ struct super_block * get_super(int dev)
        return NULL;
 }
 
-void put_super(int dev)
+void put_super(dev_t dev)
 {
        struct super_block * sb;
 
@@ -115,7 +122,7 @@ void put_super(int dev)
                sb->s_op->put_super(sb);
 }
 
-static struct super_block * read_super(int dev,char *name,int flags,void *data)
+static struct super_block * read_super(dev_t dev,char *name,int flags,void *data)
 {
        struct super_block * s;
        struct file_system_type *type;
@@ -148,10 +155,9 @@ static struct super_block * read_super(int dev,char *name,int flags,void *data)
        return s;
 }
 
-static int do_umount(int dev)
+static int do_umount(dev_t dev)
 {
        struct super_block * sb;
-       struct inode * inode;
 
        if (dev==ROOT_DEV)
                return -EBUSY;
@@ -159,12 +165,8 @@ static int do_umount(int dev)
                return -ENOENT;
        if (!sb->s_covered->i_mount)
                printk("Mounted inode has i_mount=0\n");
-       for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++)
-               if (inode->i_dev==dev && inode->i_count)
-                       if (inode == sb->s_mounted && inode->i_count == 1)
-                               continue;
-                       else
-                               return -EBUSY;
+       if (!fs_may_umount(dev, sb->s_mounted))
+               return -EBUSY;
        sb->s_covered->i_mount=0;
        iput(sb->s_covered);
        sb->s_covered = NULL;
@@ -172,7 +174,7 @@ static int do_umount(int dev)
        sb->s_mounted = NULL;
        if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
                sb->s_op->write_super (sb);
-        put_super(dev);
+       put_super(dev);
        return 0;
 }
 
@@ -191,13 +193,21 @@ int sys_umount(char * dev_name)
                iput(inode);
                return -ENOTBLK;
        }
+       if (IS_NODEV(inode)) {
+               iput(inode);
+               return -EACCES;
+       }
+       if (MAJOR(dev) >= MAX_BLKDEV) {
+               iput(inode);
+               return -ENODEV;
+       }
        retval = do_umount(dev);
-       if (!retval && MAJOR(dev) < MAX_BLKDEV &&
-           blkdev_fops[MAJOR(dev)]->release)
+       if (!retval && blkdev_fops[MAJOR(dev)] && blkdev_fops[MAJOR(dev)]->release)
                blkdev_fops[MAJOR(dev)]->release(inode,NULL);
        iput(inode);
-       if (retval) return retval;
-        sync_dev(dev);
+       if (retval)
+               return retval;
+       sync_dev(dev);
        return 0;
 }
 
@@ -210,9 +220,9 @@ int sys_umount(char * dev_name)
  * We also have to flush all inode-data for this device, as the new mount
  * might need new info.
  */
-static int do_mount(int dev, const char * dir, char * type, int flags, void * data)
+static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
 {
-       struct inode * inode, * dir_i;
+       struct inode * dir_i;
        struct super_block * sb;
        int error;
 
@@ -227,14 +237,9 @@ static int do_mount(int dev, const char * dir, char * type, int flags, void * da
                iput(dir_i);
                return -EPERM;
        }
-       for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
-               if (inode->i_dev != dev)
-                       continue;
-               if (inode->i_count || inode->i_dirt || inode->i_lock) {
-                       iput(dir_i);
-                       return -EBUSY;
-               }
-               inode->i_dev = 0;
+       if (!fs_may_mount(dev)) {
+               iput(dir_i);
+               return -EBUSY;
        }
        sb = read_super(dev,type,flags,data);
        if (!sb || sb->s_covered) {
@@ -263,6 +268,7 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
        unsigned long new_flags, void *data)
 {
        struct inode * inode;
+       struct file_operations * fops;
        int dev;
        int retval;
        char tmp[100],*t;
@@ -272,19 +278,27 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
 
        if (!suser())
                return -EPERM;
-       retval = namei(dev_name,&inode);
-       if (retval)
+       if (retval = namei(dev_name,&inode))
                return retval;
        dev = inode->i_rdev;
-       if (!S_ISBLK(inode->i_mode))
-               retval = -EPERM;
-       else if (IS_NODEV(inode))
-               retval = -EACCES;
-       if (!retval && blkdev_fops[MAJOR(dev)]->open)
-               retval = blkdev_fops[MAJOR(dev)]->open(inode,NULL);
-       if (retval) {
+       if (!S_ISBLK(inode->i_mode)) {
                iput(inode);
-               return retval;
+               return -ENOTBLK;
+       }
+       if (IS_NODEV(inode)) {
+               iput(inode);
+               return -EACCES;
+       }
+       if (MAJOR(dev) >= MAX_BLKDEV) {
+               iput(inode);
+               return -ENODEV;
+       }
+       fops = blkdev_fops[MAJOR(dev)];
+       if (fops && fops->open) {
+               if (retval = fops->open(inode,NULL)) {
+                       iput(inode);
+                       return retval;
+               }
        }
        if ((new_flags & 0xffff0000) == 0xC0ED0000) {
                flags = new_flags & 0xffff;
@@ -306,8 +320,8 @@ int sys_mount(char * dev_name, char * dir_name, char * type,
                t = "minix";
        retval = do_mount(dev,dir_name,t,flags,(void *) page);
        free_page(page);
-       if (retval && blkdev_fops[MAJOR(dev)]->release)
-               blkdev_fops[MAJOR(dev)]->release(inode,NULL);
+       if (retval && fops && fops->release)
+               fops->release(inode,NULL);
        iput(inode);
        return retval;
 }
diff --git a/include/asm/dma.h b/include/asm/dma.h
new file mode 100644 (file)
index 0000000..9ba767f
--- /dev/null
@@ -0,0 +1,192 @@
+/* $Header: /sys/linux-0.97/include/asm/RCS/dma.h,v 1.4 1992/09/21 03:15:46 root Exp root $
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ * Written by Hennus Bergman, 1992.
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>            /* need byte IO */
+#include <linux/kernel.h>      /* need panic() [FIXME] */
+
+
+#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#define outb   outb_p
+#endif
+
+/* FIXME: better fix this code for dma channels>3!!!!!!! */
+
+/*
+ * The routines below should in most cases (with optimizing on) result
+ * in equal or better code than similar code using macros.
+ *
+ * NOTE about DMA transfers: The DMA controller cannot handle transfers
+ * that cross a 64k boundary. When the address reaches 0xNffff, it will wrap
+ * around to 0xN0000, rather than increment to 0x(N+1)0000 !
+ * Make sure you align your buffers properly! Runtime check recommended.
+ *
+ * NOTE2: DMA1..3 can only use the lower 1MB of physical memory. DMA4..7
+ * can access the lower 16MB. There are people with >16MB, so beware!
+ */
+
+
+#define MAX_DMA_CHANNELS       8
+
+/* SOMEBODY should check the following:
+ * Channels 0..3 are on the first DMA controller, channels 4..7 are
+ * on the second. Channel 0 is for refresh, 4 is for cascading.
+ * The first DMA controller uses bytes, the second words.
+ *
+ * Where are the page regs for the second DMA controller?????
+ */
+
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE   0x00    /* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE   0xC0    /* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG           0x08    /* DMA command register */
+#define DMA1_STAT_REG          0x08    /* DMA status register */
+#define DMA1_MASK_REG          0x0A    /* mask individual channels */
+#define DMA1_MODE_REG          0x0B    /* set modes for individual channels */
+#define DMA1_CLEAR_FF_REG      0x0C    /* Write 0 for LSB, 1 for MSB */
+#define DMA1_RESET_REG         0x0D    /* Write here to reset DMA controller */
+/* don't have much info on the second DMA controller... */
+#define DMA2_MASK_REG          0xD4
+#define DMA2_MODE_REG          0xD6
+/* #define DMA2_CLEAR_FF_REG 0xD8 -- pure guessing.... */
+
+/************* #error This needs more work!!!!!!!*************/
+
+#define DMA_MODE_READ  0x44    /* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE 0x48    /* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE       0xC0    /* cascade mode (for DMA2 controller only) */
+
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+       if (dmanr<=3)
+               outb(dmanr,  DMA1_MASK_REG);
+       else
+               outb(dmanr & 3,  DMA2_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+       if (dmanr<=3)
+               outb(dmanr | 4,  DMA1_MASK_REG);
+       else
+               outb((dmanr & 3) | 4,  DMA2_MASK_REG);
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a know state.
+ * After that, keep track of it. :-) In order to do that,
+ * dma_set_addr() and dma_set_count() should only be used wile
+ * interrupts are disbled.
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+       if (dmanr<=3)
+               outb(0,  DMA1_CLEAR_FF_REG);
+       else
+#ifdef DMA2_CLEAR_FF_REG
+               outb(0,  DMA2_CLEAR_FF_REG);
+#else
+               panic("dma.h: Don't have CLEAR_FF for high dma channels!\n");
+#endif
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+       if (dmanr<=3)
+               outb(mode | dmanr,  DMA1_MODE_REG);
+       else
+               outb(DMA_MODE_CASCADE | mode | (dmanr&3),  DMA2_MODE_REG);
+}
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+       switch(dmanr) {
+               case 0:
+                       outb(pagenr, 0x80);
+                       break;
+               case 1:
+                       outb(pagenr, 0x83);
+                       break;
+               case 2:
+                       outb(pagenr, 0x81);
+                       break;
+               case 3:
+                       outb(pagenr, 0x82);
+                       break;
+               case 4:
+               case 5:
+               case 6:
+               case 7:
+                       panic("dma.h: don't know how to set DMA page regs for channels>3");
+                       break;
+       }
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+       unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
+
+       set_dma_page(dmanr, a>>16);
+       outb(a & 0xff, ((dmanr&3)<<1) + io_base);
+       outb((a>>8) & 0xff, ((dmanr&3)<<1) + io_base);
+}
+
+
+/* Set transfer size (max 64k) for a specific DMA channel.
+ * You must ensure the parameters are valid.
+ * NOTE: from a manual: "the number of transfers is one more 
+ * than the initial word count"! This is taken into account.
+ * Assumes dma flip-flop is clear.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+       unsigned int dc = count - 1;
+       unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
+
+       outb(dc & 0xff, ((dmanr&3)<<1) + 1 + io_base);
+       outb((dc>>8) & 0xff, ((dmanr&3)<<1) + 1 + io_base);
+}
+
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of bytes left to transfer,
+ * minus 1, modulo 64k.
+ * Assumes DMA flip-flop is clear.
+ */
+static __inline__ short int get_dma_residue(unsigned int dmanr)
+{
+       unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
+
+       return 1 + inb( ((dmanr&3)<<1) + 1 + io_base ) +
+               ( inb( ((dmanr&3)<<1) + 1 + io_base ) << 8 );
+}
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr);    /* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);      /* release it again */
+
+
+#endif /* _ASM_DMA_H */
index b354a8a5fc6b09657c2e3a1c333057c6c9516264..49fda909035a261b4daf811d822e682b73574c59 100644 (file)
@@ -37,7 +37,7 @@ extern inline void put_fs_long(unsigned long val,unsigned long * addr)
 __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
 }
 
-extern inline void memcpy_tofs(void * to, void * from, unsigned long n)
+extern inline void memcpy_tofs(void * to, const void * from, unsigned long n)
 {
 __asm__("cld\n\t"
        "push %%es\n\t"
@@ -56,7 +56,7 @@ __asm__("cld\n\t"
        :"cx","di","si");
 }
 
-extern inline void memcpy_fromfs(void * to, void * from, unsigned long n)
+extern inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
 __asm__("cld\n\t"
        "testb $1,%%cl\n\t"
index abfbf7e8280b364f8a9567d446ed014875917e7c..4fe72bc8cbd16fb31b976064539d7bd15dbfdfec 100644 (file)
 #define DEF_SETUPSEG   0x9020
 #define DEF_SYSSIZE    0x7000
 
+/* internal svga startup constants */
+#define NORMAL_VGA     0xffff          /* 80x25 mode */
+#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
+#define ASK_VGA                0xfffd          /* ask for it at bootup */
+
 /*
  * The root-device is no longer hard-coded. You can change the default
  * root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s
index 7e6e3aa3a8d520bc2f53910f13015babfd6f7369..9e16cba8bc0e741f3b9de9bf0035bddf1b039bb8 100644 (file)
@@ -74,11 +74,11 @@ extern int ext_link(struct inode * oldinode, struct inode * dir, const char * na
 extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
 extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
        struct inode * new_dir, const char * new_name, int new_len);
-extern struct inode * ext_new_inode(int dev);
+extern struct inode * ext_new_inode(struct super_block * sb);
 extern void ext_free_inode(struct inode * inode);
 extern unsigned long ext_count_free_inodes(struct super_block *sb);
-extern int ext_new_block(int dev);
-extern void ext_free_block(int dev, int block);
+extern int ext_new_block(struct super_block * sb);
+extern void ext_free_block(struct super_block * sb, int block);
 extern unsigned long ext_count_free_blocks(struct super_block *sb);
 
 extern int ext_bmap(struct inode *,int);
index 0aeed9baccfbda86eacb9720614bc3777642533a..87b76d704992aab18b39b01217b5661336c58326 100644 (file)
@@ -39,6 +39,7 @@
 #define WRITEA 3       /* "write-ahead" - silly, but somewhat useful */
 
 extern void buffer_init(void);
+extern void inode_init(void);
 
 #define MAJOR(a) (((unsigned)(a))>>8)
 #define MINOR(a) ((a)&0xff)
@@ -90,7 +91,7 @@ struct buffer_head {
        char * b_data;                  /* pointer to data block (1024 bytes) */
        unsigned long b_size;           /* block size */
        unsigned long b_blocknr;        /* block number */
-       unsigned short b_dev;           /* device (0 = free) */
+       dev_t b_dev;                    /* device (0 = free) */
        unsigned short b_count;         /* users using this block */
        unsigned char b_uptodate;
        unsigned char b_dirt;           /* 0-clean,1-dirty */
@@ -145,14 +146,14 @@ struct inode {
 };
 
 struct file {
-       unsigned short f_mode;
+       mode_t f_mode;
+       dev_t f_rdev;                   /* needed for /dev/tty */
+       off_t f_pos;
        unsigned short f_flags;
        unsigned short f_count;
        unsigned short f_reada;
-       unsigned short f_rdev;          /* needed for /dev/tty */
        struct inode * f_inode;
        struct file_operations * f_op;
-       off_t f_pos;
 };
 
 struct file_lock {
@@ -170,7 +171,7 @@ struct file_lock {
 #include <linux/msdos_fs_sb.h>
 
 struct super_block {
-       unsigned short s_dev;
+       dev_t s_dev;
        unsigned long s_blocksize;
        unsigned char s_lock;
        unsigned char s_rd_only;
@@ -237,7 +238,9 @@ extern struct file_operations * blkdev_fops[MAX_BLKDEV];
 
 extern struct file_system_type *get_fs_type(char *name);
 
-extern struct inode inode_table[NR_INODE];
+extern int fs_may_mount(dev_t dev);
+extern int fs_may_umount(dev_t dev, struct inode * mount_root);
+
 extern struct file file_table[NR_FILE];
 extern struct super_block super_block[NR_SUPER];
 
@@ -247,44 +250,41 @@ extern int shrink_buffers(unsigned int priority);
 extern int nr_buffers;
 extern int nr_buffer_heads;
 
-extern void check_disk_change(int dev);
-extern void invalidate_inodes(int dev);
-extern void invalidate_buffers(int dev);
+extern void check_disk_change(dev_t dev);
+extern void invalidate_inodes(dev_t dev);
+extern void invalidate_buffers(dev_t dev);
 extern int floppy_change(struct buffer_head * first_block);
 extern int ticks_to_floppy_on(unsigned int dev);
 extern void floppy_on(unsigned int dev);
 extern void floppy_off(unsigned int dev);
-extern void sync_inodes(void);
-extern void wait_on(struct inode * inode);
+extern void sync_inodes(dev_t dev);
+extern void sync_dev(dev_t dev);
+extern void sync_supers(dev_t dev);
 extern int bmap(struct inode * inode,int block);
 extern int namei(const char * pathname, struct inode ** res_inode);
 extern int lnamei(const char * pathname, struct inode ** res_inode);
 extern int permission(struct inode * inode,int mask);
 extern int open_namei(const char * pathname, int flag, int mode,
        struct inode ** res_inode, struct inode * base);
-extern int do_mknod(const char * filename, int mode, int dev);
+extern int do_mknod(const char * filename, int mode, dev_t dev);
 extern void iput(struct inode * inode);
-extern struct inode * iget(int dev,int nr);
+extern struct inode * iget(struct super_block * sb,int nr);
 extern struct inode * get_empty_inode(void);
 extern struct inode * get_pipe_inode(void);
 extern struct file * get_empty_filp(void);
-extern struct buffer_head * get_hash_table(int dev, int block, int size);
-extern struct buffer_head * getblk(int dev, int block, int size);
+extern struct buffer_head * get_hash_table(dev_t dev, int block, int size);
+extern struct buffer_head * getblk(dev_t dev, int block, int size);
 extern void ll_rw_block(int rw, struct buffer_head * bh);
 extern void ll_rw_page(int rw, int dev, int nr, char * buffer);
 extern void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buffer);
 extern void brelse(struct buffer_head * buf);
-extern struct buffer_head * bread(int dev, int block, int size);
-extern void bread_page(unsigned long addr,int dev,int b[4]);
-extern struct buffer_head * breada(int dev,int block,...);
-extern int sync_dev(int dev);
-extern struct super_block * get_super(int dev);
-extern void put_super(int dev);
-extern int ROOT_DEV;
+extern struct buffer_head * bread(dev_t dev, int block, int size);
+extern void bread_page(unsigned long addr,dev_t dev,int b[4]);
+extern struct buffer_head * breada(dev_t dev,int block,...);
+extern void put_super(dev_t dev);
+extern dev_t ROOT_DEV;
 
 extern void mount_root(void);
-extern void lock_super(struct super_block * sb);
-extern void free_super(struct super_block * sb);
 
 extern int char_read(struct inode *, struct file *, char *, int);
 extern int block_read(struct inode *, struct file *, char *, int);
index cf77d547f5bb483c20cdae42bdfc5bb6f1b4204b..a4ac54fe15b30d60a04bd94874b67145802c0ada 100644 (file)
@@ -8,6 +8,7 @@
 void verify_area(void * addr,int count);
 volatile void panic(const char * str);
 volatile void do_exit(long error_code);
+unsigned long simple_strtoul(const char *,char **,unsigned int);
 int printk(const char * fmt, ...);
 void * malloc(unsigned int size);
 void free_s(void * obj, int size);
diff --git a/include/linux/locks.h b/include/linux/locks.h
new file mode 100644 (file)
index 0000000..ac9b290
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _LINUX_LOCKS_H
+#define _LINUX_LOCKS_H
+
+/*
+ * Buffer cache locking - note that interrupts may only unlock, not
+ * lock buffers.
+ */
+extern void __wait_on_buffer(struct buffer_head *);
+
+extern inline void wait_on_buffer(struct buffer_head * bh)
+{
+       if (bh->b_lock)
+               __wait_on_buffer(bh);
+}
+
+extern inline void lock_buffer(struct buffer_head * bh)
+{
+       if (bh->b_lock)
+               __wait_on_buffer(bh);
+       bh->b_lock = 1;
+}
+
+extern inline void unlock_buffer(struct buffer_head * bh)
+{
+       bh->b_lock = 0;
+       wake_up(&bh->b_wait);
+}
+
+/*
+ * super-block locking. Again, interrupts may only unlock
+ * a super-block (although even this isn't done right now.
+ * nfs may need it).
+ */
+extern void __wait_on_super(struct super_block *);
+
+extern inline void wait_on_super(struct super_block * sb)
+{
+       if (sb->s_lock)
+               __wait_on_super(sb);
+}
+
+extern inline void lock_super(struct super_block * sb)
+{
+       if (sb->s_lock)
+               __wait_on_super(sb);
+       sb->s_lock = 1;
+}
+
+extern inline void unlock_super(struct super_block * sb)
+{
+       sb->s_lock = 0;
+       wake_up(&sb->s_wait);
+}
+
+#endif /* _LINUX_LOCKS_H */
+
index 2fef6882e235661086c3eb33c67b381f0f5688c9..d0d1607689bb3918f6e53dde0d696b5e2eb0805c 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef _LINUX_LP_H
 #define _LINUX_LP_H
 
-/*
-$Header: /usr/src/linux/include/linux/lp.h,v 1.2 1992/01/21 23:59:24 james_r_wiegand Exp james_r_wiegand $
-*/
-
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -14,15 +10,19 @@ $Header: /usr/src/linux/include/linux/lp.h,v 1.2 1992/01/21 23:59:24 james_r_wie
 
 /*
  * usr/include/linux/lp.h c.1991-1992 James Wiegand
+ * many modifications copyright (C) 1992 Michael K. Johnson
  */
 
 /*
  * caveat: my machine only has 1 printer @ lpt2 so lpt1 & lpt3 are 
  * implemented but UNTESTED
+ *
+ * My machine (Michael K. Johnson) has only lpt1...  dupla caveat...
  */
 
 /*
  * Per POSIX guidelines, this module reserves the LP and lp prefixes
+ * These are the lp_table[minor].flags flags...
  */
 #define LP_EXIST 0x0001
 #define LP_SELEC 0x0002
@@ -31,11 +31,27 @@ $Header: /usr/src/linux/include/linux/lp.h,v 1.2 1992/01/21 23:59:24 james_r_wie
 #define LP_NOPA  0x0010
 #define LP_ERR   0x0020
 
-#define LP_TIMEOUT 200000
-
-#define LP_B(minor)    lp_table[(minor)].base
-#define LP_F(minor)    lp_table[(minor)].flags
-#define LP_S(minor)    inb(LP_B((minor)) + 1)
+/* timeout for each character  (This is a good case 50 Mhz computer
+   at a poor case 10 KBS xfer rate to the printer, as best as I can
+   tell.)  This is in instruction cycles, kinda -- it is the count
+   in a busy loop.  THIS IS THE VALUE TO CHANGE if you 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.*/
+#define LP_TIME_CHAR 5000
+
+/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
+   If your printer isn't printing at least one character every five seconds,
+   you have worse problems than a slow printer driver and lp_timeout printed
+   every five seconds while trying to print. */
+#define LP_TIMEOUT 5000
+
+#define LP_B(minor)    lp_table[(minor)].base          /* IO address */
+#define LP_F(minor)    lp_table[(minor)].flags         /* flags for busy, etc. */
+#define LP_S(minor)    inb(LP_B((minor)) + 1)          /* status port */
+#define LP_C(minor)    (lp_table[(minor)].base + 2)    /* control port */
+#define LP_COUNT(minor)        lp_table[(minor)].count         /* last count */
+#define LP_TIME(minor) lp_table[(minor)].time          /* last time */
 
 /* 
 since we are dealing with a horribly slow device
@@ -44,39 +60,57 @@ I don't see the need for a queue
 struct lp_struct {
        int base;
        int flags;
+       int count;
+       int time;
 };
 
-/* 
- * the BIOS manuals say there can be up to 4 lpt devices
+/* This is the starting value for the heuristic algorithm.  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 not stricly necessary, as the algorithm should be able to
+ * adapt to your printer relatively quickly.
+ * this is in hundredths of a second, the default 50 being .5 seconds.
+ */
+
+#define LP_INIT_TIME 50
+
+/* This is our first guess at the size of the buffer on the printer,
+ * in characters.  I am assuming a 4K buffer because most newer printers
+ * have larger ones, which will be adapted to.  At this time, it really
+ * doesn't matter, as this value isn't used.
+ */
+
+#define LP_INIT_COUNT 4096
+
+/* the BIOS manuals say there can be up to 4 lpt devices
  * but I have not seen a board where the 4th address is listed
  * if you have different hardware change the table below 
  * please let me know if you have different equipment
  * if you have more than 3 printers, remember to increase LP_NO
  */
 struct lp_struct lp_table[] = {
-       { 0x3bc, 0, },
-       { 0x378, 0, },
-       { 0x278, 0, }
+       { 0x3bc, 0, LP_INIT_COUNT, LP_INIT_TIME, },
+       { 0x378, 0, LP_INIT_COUNT, LP_INIT_TIME, },
+       { 0x278, 0, LP_INIT_COUNT, LP_INIT_TIME, }
 }; 
-
 #define LP_NO 3
 
 /* 
  * bit defines for 8255 status port
  * base + 1
+ * accessed with LP_S(minor), which gets the byte...
  */
 #define LP_PBUSY       0x80 /* active low */
 #define LP_PACK                0x40 /* active low */
 #define LP_POUTPA      0x20
 #define LP_PSELECD     0x10
-#define LP_PERRORP     0x08 /*Ã¥ active low*/
-#define LP_PIRQ                0x04 /* active low */
+#define LP_PERRORP     0x08 /* active low*/
 
 /* 
  * defines for 8255 control port
  * base + 2 
+ * accessed with LP_C(minor)
  */
-#define LP_PIRQEN      0x10
 #define LP_PSELECP     0x08
 #define LP_PINITP      0x04  /* active low */
 #define LP_PAUTOLF     0x02
@@ -90,7 +124,8 @@ struct lp_struct lp_table[] = {
 #define LP_DUMMY       0x00
 
 /*
- * this is the port delay time. your mileage may vary
+ * This is the port delay time.  Your mileage may vary.
+ * It is used only in the lp_init() routine.
  */
 #define LP_DELAY       150000
 
index a4ce2e40207045a31fd556e49134b960cfec589f..c709962385aef7232e7c27b230c93824b62b79ba 100644 (file)
@@ -57,11 +57,11 @@ extern int minix_link(struct inode * oldinode, struct inode * dir, const char *
 extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
 extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
        struct inode * new_dir, const char * new_name, int new_len);
-extern struct inode * minix_new_inode(int dev);
+extern struct inode * minix_new_inode(struct super_block * sb);
 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 void minix_free_block(int dev, int block);
+extern int minix_new_block(struct super_block * sb);
+extern void minix_free_block(struct super_block * sb, int block);
 extern unsigned long minix_count_free_blocks(struct super_block *sb);
 
 extern int minix_bmap(struct inode *,int);
index a0954f16f89521257b83b9e9dcd82175268de432..5058896e71e52d7464090beae05c01527d04f0b1 100644 (file)
@@ -336,18 +336,31 @@ __asm__("movw %%dx,%0\n\t" \
 #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
 #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
 
+/*
+ * The wait-queues are circular lists, and you have to be *very* sure
+ * to keep them correct. Use only these two functions to add/remove
+ * entries in the queues.
+ */
 extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 {
        unsigned long flags;
-       struct wait_queue * tmp;
 
+#ifdef DEBUG
+       if (wait->next) {
+               unsigned long pc;
+               __asm__ __volatile__("call 1f\n"
+                       "1:\tpopl %0":"=r" (pc));
+               printk("add_wait_queue (%08x): wait->next = %08x\n",pc,wait->next);
+       }
+#endif
        __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
-       wait->next = *p;
-       tmp = wait;
-       while (tmp->next)
-               if ((tmp = tmp->next)->next == *p)
-                       break;
-       *p = tmp->next = wait;
+       if (!*p) {
+               wait->next = wait;
+               *p = wait;
+       } else {
+               wait->next = (*p)->next;
+               (*p)->next = wait;
+       }
        __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 }
 
@@ -357,14 +370,14 @@ extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue *
        struct wait_queue * tmp;
 
        __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
-       if (*p == wait)
-               if ((*p = wait->next) == wait)
-                       *p = NULL;
-       tmp = wait;
-       while (tmp && tmp->next != wait)
-               tmp = tmp->next;
-       if (tmp)
+       if ((*p == wait) && ((*p = wait->next) == wait)) {
+               *p = NULL;
+       } else {
+               tmp = wait;
+               while (tmp->next != wait)
+                       tmp = tmp->next;
                tmp->next = wait->next;
+       }
        wait->next = NULL;
        __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 }
@@ -377,6 +390,7 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table *
                return;
        entry->wait_address = wait_address;
        entry->wait.task = current;
+       entry->wait.next = NULL;
        add_wait_queue(wait_address,&entry->wait);
        p->nr++;
 }
index cdff971dcc5cf15c53bf53494f10be095d0aaee9..369fb41e4ee42ebe9aaafba5043f6c9d05e7cbd1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_STRING_H_
 #define _LINUX_STRING_H_
 
+#include <linux/types.h>       /* for size_t */
+
 #ifndef NULL
 #define NULL ((void *) 0)
 #endif
@@ -326,14 +328,22 @@ __asm__("testl %1,%1\n\t"
 return __res;
 }
 
-extern inline void * memcpy(void * dest,const void * src, size_t n)
+extern inline void * memcpy(void * to, const void * from, size_t n)
 {
 __asm__("cld\n\t"
-       "rep\n\t"
-       "movsb"
-       ::"c" (n),"S" (src),"D" (dest)
-       :"cx","si","di");
-return dest;
+       "movl %%edx, %%ecx\n\t"
+       "shrl $2,%%ecx\n\t"
+       "rep ; movsl\n\t"
+       "testb $1,%%dl\n\t"
+       "je 1f\n\t"
+       "movsb\n"
+       "1:\ttestb $2,%%dl\n\t"
+       "je 2f\n\t"
+       "movsw\n"
+       "2:\n"
+       ::"d" (n),"D" ((long) to),"S" ((long) from)
+       : "cx","di","si");
+return (to);
 }
 
 extern inline void * memmove(void * dest,const void * src, size_t n)
index 9736e8d7ae8a28871a65b88ec17bccc17f0e1e38..f3210818c60ed12a34a7d7e43d33416891732299 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/tty.h>
 #include <linux/head.h>
 #include <linux/unistd.h>
+#include <linux/string.h>
 
 extern unsigned long * prof_buffer;
 extern unsigned long prof_len;
@@ -64,22 +65,13 @@ extern void floppy_init(void);
 extern void sock_init(void);
 extern long rd_init(long mem_start, int length);
 extern long kernel_mktime(struct mktime * time);
+extern unsigned long simple_strtoul(const char *cp,char **endp,unsigned int
+    base);
 
 #ifdef CONFIG_SCSI
-extern void scsi_dev_init(void);
+extern unsigned long scsi_dev_init(unsigned long, unsigned long);
 #endif
 
-static int sprintf(char * str, const char *fmt, ...)
-{
-       va_list args;
-       int i;
-
-       va_start(args, fmt);
-       i = vsprintf(str, fmt, args);
-       va_end(args);
-       return i;
-}
-
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -89,6 +81,16 @@ static int sprintf(char * str, const char *fmt, ...)
 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
 #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
 
+/*
+ * Boot command-line arguments
+ */
+#define MAX_INIT_ARGS 8
+#define MAX_INIT_ENVS 8
+#define CL_MAGIC_ADDR (*(unsigned short *) 0x90020)
+#define CL_MAGIC 0xa33f
+#define CL_BASE_ADDR ((char *) 0x90000)
+#define CL_OFFSET (*(unsigned short *) 0x90022)
+
 /*
  * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
  * and this seems to work. I anybody has more info on the real-time
@@ -130,22 +132,71 @@ static unsigned long memory_start = 0; /* After mem_init, stores the */
 static unsigned long memory_end = 0;
 static unsigned long low_memory_start = 0;
 
-static char term[32];
-
-static char * argv_init[] = { "/bin/init", NULL };
-static char * envp_init[] = { "HOME=/", NULL, NULL };
+static char * argv_init[MAX_INIT_ARGS+2] = { "/bin/init", NULL, };
+static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=console", NULL, };
 
 static char * argv_rc[] = { "/bin/sh", NULL };
-static char * envp_rc[] = { "HOME=/", NULL ,NULL };
+static char * envp_rc[] = { "HOME=/", "TERM=console", NULL };
 
 static char * argv[] = { "-/bin/sh",NULL };
-static char * envp[] = { "HOME=/usr/root", NULL, NULL };
+static char * envp[] = { "HOME=/usr/root", "TERM=console", NULL };
 
 struct drive_info { char dummy[32]; } drive_info;
 struct screen_info screen_info;
 
 unsigned char aux_device_present;
 
+static char command_line[80] = { 0, };
+
+/*
+ * This is a simple kernel command line parsing function: it parses
+ * the command line, and fills in the arguments/environment to init
+ * as appropriate. Any cmd-line option is taken to be an environment
+ * variable if it contains the character '='.
+ *
+ *
+ * This routine also checks for options meant for the kernel - currently
+ * only the "root=XXXX" option is recognized. These options are not given
+ * to init - they are for internal kernel use only.
+ */
+static void parse_options(char *line)
+{
+       char *next;
+       int args, envs;
+
+       if (!*line)
+               return;
+       args = 0;
+       envs = 1;       /* TERM is set to 'console' by default */
+       next = line;
+       while (line = next) {
+               if (next = strchr(line,' '))
+                       *next++ = 0;
+               /*
+                * check for kernel options first..
+                */
+               if (!strncmp(line,"root=",5)) {
+                       ROOT_DEV = simple_strtoul(line+5,NULL,16);
+                       continue;
+               }
+               /*
+                * Then check if it's an environment variable or
+                * an option.
+                */     
+               if (strchr(line,'=')) {
+                       if (envs >= MAX_INIT_ENVS)
+                               break;
+                       envp_init[++envs] = line;
+               } else {
+                       if (args >= MAX_INIT_ARGS)
+                               break;
+                       argv_init[++args] = line;
+               }
+       }
+       argv_init[args+1] = NULL;
+       envp_init[envs+1] = NULL;
+}
+
 void start_kernel(void)
 {
 /*
@@ -156,10 +207,6 @@ void start_kernel(void)
        drive_info = DRIVE_INFO;
        screen_info = SCREEN_INFO;
        aux_device_present = AUX_DEVICE_INFO;
-       sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
-       envp[1] = term; 
-       envp_rc[1] = term;
-       envp_init[1] = term;
        memory_end = (1<<20) + (EXT_MEM_K<<10);
        memory_end &= 0xfffff000;
 #ifdef MAX_16M
@@ -171,9 +218,12 @@ void start_kernel(void)
        low_memory_start += 0xfff;
        low_memory_start &= 0xfffff000;
        memory_start = paging_init(memory_start,memory_end);
+       if (CL_MAGIC_ADDR == CL_MAGIC)
+               strcpy(command_line,CL_BASE_ADDR+CL_OFFSET);
        trap_init();
        init_IRQ();
        sched_init();
+       parse_options(command_line);
 #ifdef PROFILE_SHIFT
        prof_buffer = (unsigned long *) memory_start;
        prof_len = (unsigned long) &end;
@@ -182,16 +232,16 @@ void start_kernel(void)
 #endif
        memory_start = chr_dev_init(memory_start,memory_end);
        memory_start = blk_dev_init(memory_start,memory_end);
+#ifdef CONFIG_SCSI
+       memory_start = scsi_dev_init(memory_start,memory_end);
+#endif
        mem_init(low_memory_start,memory_start,memory_end);
        buffer_init();
+       inode_init();
        time_init();
        floppy_init();
        sock_init();
        sti();
-#ifdef CONFIG_SCSI
-       scsi_dev_init();
-#endif
-       sti();
        move_to_user_mode();
        if (!fork())            /* we count on this going ok */
                init();
index 5277b89ec3b790fb28a963b4f4a69078efcc0c31..d288ef798545c4782cc033809768f8afdb629419 100644 (file)
@@ -46,30 +46,6 @@ dep:
 proto:
        cproto -e -DMAKING_PROTO *.c >fpu_proto.h
 
-tar:
-       echo "List of source files for wm-FPU-emu" > MANIFEST
-       echo "---- -- ------ ----- --- ----------" >> MANIFEST
-       ls -l Makefile *.c *.S *.h >> MANIFEST
-       ( cd ../../..; \
-       pwd; \
-       tar cvf wm-FPU-emu.t \
-               linux/kernel/wm-FPU-emu/*.c \
-               linux/kernel/wm-FPU-emu/*.S \
-               linux/kernel/wm-FPU-emu/*.h \
-               linux/kernel/wm-FPU-emu/Makefile \
-               linux/kernel/wm-FPU-emu/MANIFEST \
-               linux/kernel/wm-FPU-emu/README \
-               linux/kernel/wm-FPU-emu/Checklist \
-               linux/kernel/wm-FPU-emu/Limitations \
-               linux/kernel/wm-FPU-emu/Internals \
-               linux/kernel/wm-FPU-emu/Performance \
-               linux/kernel/wm-FPU-emu/COPYING \
-               linux/include/linux/sched.h \
-               linux/include/linux/user.h \
-               ; \
-       compress wm-FPU-emu.t \
-       )
-
 dummy:
 
 ### Dependencies:
index b66aa7d72948c345ca784a79469feed506046940..078e860a47ed14f026f02e0b2af43f5f02193056 100644 (file)
@@ -267,27 +267,6 @@ void exception(int n)
 }
 
 
-/********
-int EmptyError(void)
-{
-  EXCEPTION(EX_StackUnder);
-  return 0;
-}
- **********/
-
-
-/****
-int FullError(void)
-{
-  EXCEPTION(EX_StackOver);
-  reg_move(&CONST_QNaN, st0_ptr);
-  return 0;
-}
- ****/
-
-
-
-
 /* Real operation attempted on two operands, one a NaN */
 void real_2op_NaN(REG *a, REG *b, REG *dest)
 {
index 79826cd5184f2f603bdabc934a9de2e1537f7726..48093861fee60dff5011fe91d1e3cb5bc6361685 100644 (file)
@@ -372,7 +372,7 @@ int reg_store_extended(void)
              REG tmp;
              EXCEPTION(EX_Denormal);  /* De-normal */
              reg_move(st0_ptr, &tmp);
-             tmp.exp += EXTENDED_Emin + 64;  /* largest exp to be 62 */
+             tmp.exp += -EXTENDED_Emin + 64;  /* largest exp to be 63 */
              round_to_int(&tmp);
              e = 0;
              put_fs_long(tmp.sigl, (unsigned long *) d);
@@ -516,7 +516,7 @@ int reg_store_double(void)
              REG tmp;
              EXCEPTION(EX_Denormal);
              reg_move(st0_ptr, &tmp);
-             tmp.exp += DOUBLE_Emin + 52;  /* largest exp to be 51 */
+             tmp.exp += -DOUBLE_Emin + 52;  /* largest exp to be 51 */
              round_to_int(&tmp);
              l[0] = tmp.sigl;
              l[1] = tmp.sigh;
@@ -645,7 +645,7 @@ int reg_store_single(void)
              REG tmp;
              EXCEPTION(EX_Denormal);
              reg_move(st0_ptr, &tmp);
-             tmp.exp += SINGLE_Emin + 53;  /* largest exp to be 52 */
+             tmp.exp += -SINGLE_Emin + 23;  /* largest exp to be 22 */
              round_to_int(&tmp);
              templ = tmp.sigl;
            }
@@ -1142,7 +1142,7 @@ void fsave(void)
                {
                  /* Make a de-normal */
                  reg_move(rp, &tmp);
-                 tmp.exp += EXTENDED_Emin + 64;  /* largest exp to be 62 */
+                 tmp.exp += -EXTENDED_Emin + 64;  /* largest exp to be 63 */
                  round_to_int(&tmp);
                  e = 0;
                  put_fs_long(tmp.sigl, (unsigned long *) (d+i*10+2));
index 321d9ea2014282956ac1792709a08c8dcf3312df..3d339792ac9a14cbc0d56c2ce0c7fc5ebc022e72 100644 (file)
@@ -27,12 +27,11 @@ void reg_mul(REG *a, REG *b, REG *dest)
       reg_u_mul(a, b, dest);
       dest->exp += - EXP_BIAS + 1;
       dest->sign = (a->sign ^ b->sign);
+      dest->tag = TW_Valid;
       if ( dest->exp <= EXP_UNDER )
        { arith_underflow(st0_ptr); }
       else if ( dest->exp >= EXP_OVER )
        { arith_overflow(st0_ptr); }
-      else
-       dest->tag = TW_Valid;
       return;
     }
   else if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero))
index c8d58fad1a42f8ae589043da6da6883a9e3bf20e..07e4f63d8c42ca878668bb4d6e57ee0840e2fb1a 100644 (file)
@@ -133,20 +133,21 @@ L_round_the_result:
        cmpl    $0x80000000,%edx
        jc      L_no_round_up
 
-/* Check the rounding algorithm *********/
        jne     L_do_round_up
 
+       /* Now test for round-to-even */
        testb   $1,%ebx
        jz      L_no_round_up
 
 L_do_round_up:
        addl    $1,%ebx
        adcl    $0,%eax
-       jnc     L_no_round_up
+       jnc     L_no_round_up           /* Rounding done, no overflow */
 
        /* Overflow, adjust the result */
        rcrl    $1,%eax
        rcrl    $1,%ebx
+       incl    EXP(%edi)
 
 L_no_round_up:
        /* store the result */
index 24af560ae98c5afc53c47bd1c3f2d3e63e928c93..f3615a3de7c8e0f91c4f185e0cde256141497b83 100644 (file)
@@ -208,11 +208,14 @@ L_round:
 L_round_up:
        addl    $1,%ebx
        adcl    $0,%eax
-
-#ifdef PARANOID
-       /* We can show that an overflow here is not possible */
-       jc      L_bugged_4
-#endif PARANOID
+       jnc     L_store
+
+       /* We just rounded up to (1) 00 00 */
+       /* This *is* possible, if the subtraction is of the
+          form (1. + x) - (x + y) where x is small and y is
+          very small. */
+       incl    EXP(%edi)
+       movl    $0x80000000,%eax
 
 L_store:
 /*------------------------------+
index 7b8db07799a88b77a8ffd5260b891679e4602cdd..cd492ed2184fbab062cbb17bbfa3cc8a70027201 100644 (file)
@@ -8,5 +8,5 @@
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
-#define FPU_VERSION "wm-FPU-emu version ALPHA 0.5"
+#define FPU_VERSION "wm-FPU-emu version ALPHA 0.61"
 
index 9333a4b592e36969dbce925515f67a40c0eefded..0661a0bd208a510f8c00eb7747bc694b5625efb8 100644 (file)
@@ -18,7 +18,7 @@
 
 SUBDIRS        = chr_drv blk_drv FPU-emu
 
-OBJS  = sched.o sys_call.o traps.o irq.o fork.o \
+OBJS  = sched.o sys_call.o traps.o irq.o dma.o fork.o \
        panic.o printk.o vsprintf.o sys.o exit.o \
        signal.o mktime.o ptrace.o ioport.o itimer.o
 
index 62f1227200937b8095e922a8c8d30a93fdc5b120..a4641c31bd620d874d47c7d9892e02da976a154b 100644 (file)
@@ -28,7 +28,7 @@ struct request {
        unsigned long nr_sectors;
        unsigned long current_nr_sectors;
        char * buffer;
-       struct wait_queue * waiting;
+       struct task_struct * waiting;
        struct buffer_head * bh;
        struct buffer_head * bhtail;
        struct request * next;
@@ -191,6 +191,7 @@ static void end_request(int uptodate)
 {
        struct request * req;
        struct buffer_head * bh;
+       struct task_struct * p;
 
        req = CURRENT;
        req->errors = 0;
@@ -220,7 +221,12 @@ static void end_request(int uptodate)
        }
        DEVICE_OFF(req->dev);
        CURRENT = req->next;
-       wake_up(&req->waiting);
+       if (p = req->waiting) {
+               req->waiting = NULL;
+               p->state = TASK_RUNNING;
+               if (p->counter > current->counter)
+                       need_resched = 1;
+       }
        req->dev = -1;
        wake_up(&wait_for_request);
 }
index c82c8963722a16c7f7ec6cc97afe1306e49f7bf5..512500f6c0648139f411542519f37afa1839713a 100644 (file)
@@ -42,6 +42,9 @@
  * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed 
  * FDC data overrun bug, added some preliminary stuff for vertical
  * recording support.
+ *
+ * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
+ *
  * TODO: Errors are still not counted properly.
  */
 
@@ -57,6 +60,7 @@
 
 #define REALLY_SLOW_IO
 #define FLOPPY_IRQ 6
+#define FLOPPY_DMA 2
 
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/fdreg.h>
 #include <linux/fd.h>
 #include <linux/errno.h>
-#ifdef HHB_SYSMACROS
-#include <linux/system.h>
-#endif
 
+#include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -78,6 +80,8 @@
 
 static unsigned int changed_floppies = 0, fake_change = 0;
 
+static int initial_reset_flag = 0;
+static int need_configure = 1;         /* for 82077 */
 static int recalibrate = 0;
 static int reset = 0;
 static int recover = 0; /* recalibrate immediately after resetting */
@@ -197,6 +201,7 @@ static int keep_data[4] = { 0,0,0,0 };
 /*
  * Announce successful media type detection and media information loss after
  * disk changes.
+ * Also used to enable/disable printing of overrun warnings.
  */
 static ftd_msg[4] = { 0,0,0,0 };
 
@@ -227,7 +232,7 @@ static struct format_descr format_req;
     (CURRENT->errors))
 
 /*
- * Treshold for reporting FDC errors to the console.
+ * Threshold for reporting FDC errors to the console.
  * Setting this to zero may flood your screen when using
  * ultra cheap floppies ;-)
  */
@@ -289,7 +294,8 @@ void floppy_deselect(unsigned int nr)
 void request_done(int uptodate)
 {
        timer_active &= ~(1 << FLOPPY_TIMER);
-       if (format_status != FORMAT_BUSY) end_request(uptodate);
+       if (format_status != FORMAT_BUSY)
+               end_request(uptodate);
        else {
                format_status = uptodate ? FORMAT_OKAY : FORMAT_ERROR;
                wake_up(&format_done);
@@ -373,37 +379,12 @@ static void setup_DMA(void)
                        copy_buffer(CURRENT->buffer,tmp_floppy_area);
        }
        cli();
-#ifndef HHB_SYSMACROS
-/* mask DMA 2 */
-       outb_p(4|2,10);
-/* output command byte. I don't know why, but everyone (minix, */
-/* sanches & canton) output this twice, first to 12 then to 11 */
-       outb_p(dma_code,12);
-       outb_p(dma_code,11);
-/* 8 low bits of addr */
-       outb_p(addr,4);
-       addr >>= 8;
-/* bits 8-15 of addr */
-       outb_p(addr,4);
-       addr >>= 8;
-/* bits 16-19 of addr */
-       outb_p(addr,0x81);
-/* low 8 bits of count-1 */
-       count--;
-       outb_p(count,5);
-       count >>= 8;
-/* high 8 bits of count-1 */
-       outb_p(count,5);
-/* activate DMA 2 */
-       outb_p(0|2,10);
-#else                  /* just to show off my macros -- hhb */
-       DISABLE_DMA(DMA2);
-       CLEAR_DMA_FF(DMA2);
-       SET_DMA_MODE(DMA2, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
-       SET_DMA_ADDR(DMA2, addr);
-       SET_DMA_COUNT(DMA2, count);
-       ENABLE_DMA(DMA2);
-#endif
+       disable_dma(FLOPPY_DMA);
+       clear_dma_ff(FLOPPY_DMA);
+       set_dma_mode(FLOPPY_DMA, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
+       set_dma_addr(FLOPPY_DMA, addr);
+       set_dma_count(FLOPPY_DMA, count);
+       enable_dma(FLOPPY_DMA);
        sti();
 }
 
@@ -453,18 +434,57 @@ static int result(void)
 
 static void bad_flp_intr(void)
 {
+       int errors;
+
        current_track = NO_TRACK;
-       CURRENT_ERRORS++;
-       if (CURRENT_ERRORS > MAX_ERRORS) {
+       if (format_status == FORMAT_BUSY)
+               errors = ++format_errors;
+       else if (!CURRENT) {
+               printk(DEVICE_NAME ": no current request\n");
+               reset = recalibrate = 1;
+               return;
+       } else
+               errors = ++CURRENT->errors;
+       if (errors > MAX_ERRORS) {
                floppy_deselect(current_drive);
                request_done(0);
        }
-       if (CURRENT_ERRORS > MAX_ERRORS/2)
+       if (errors > MAX_ERRORS/2)
                reset = 1;
        else
                recalibrate = 1;
 }      
 
+
+/* Set perpendicular mode as required, based on data rate, if supported.
+ * 82077 Untested! 1Mbps data rate only possible with 82077-1.
+ * TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
+ */
+static void inline perpendicular_mode(unsigned char rate)
+{
+       if (fdc_version == FDC_TYPE_82077) {
+               output_byte(FD_PERPENDICULAR);
+               if (rate & 0x40) {
+                       unsigned char r = rate & 0x03;
+                       if (r == 0)
+                               output_byte(2); /* perpendicular, 500 kbps */
+                       else if (r == 3)
+                               output_byte(3); /* perpendicular, 1Mbps */
+                       else {
+                               printk(DEVICE_NAME ": Invalid data rate for perpendicular mode!\n");
+                               reset = 1;
+                       }
+               } else
+                       output_byte(0);         /* conventional mode */
+       } else {
+               if (rate & 0x40) {
+                       printk(DEVICE_NAME ": perpendicular mode not supported by this FDC.\n");
+                       reset = 1;
+               }
+       }
+} /* perpendicular_mode */
+
+
 /*
  * This has only been tested for the case fdc_version == FDC_TYPE_STD.
  * In case you have a 82077 and want to test it, you'll have to compile
@@ -473,14 +493,26 @@ static void bad_flp_intr(void)
  */
 static void configure_fdc_mode(void)
 {
-       if (fdc_version == FDC_TYPE_82077) {
+       if (need_configure && (fdc_version == FDC_TYPE_82077)) {
                /* Enhanced version with FIFO & vertical recording. */
                output_byte(FD_CONFIGURE);
                output_byte(0);
-               output_byte(0x1A);      /* FIFO on, polling off, 10 byte treshold */
+               output_byte(0x1A);      /* FIFO on, polling off, 10 byte threshold */
                output_byte(0);         /* precompensation from track 0 upwards */
+               need_configure = 0;
                printk(DEVICE_NAME ": FIFO enabled\n");
        }
+       if (cur_spec1 != floppy->spec1) {
+               cur_spec1 = floppy->spec1;
+               output_byte(FD_SPECIFY);
+               output_byte(cur_spec1);         /* hut etc */
+               output_byte(6);                 /* Head load time =6ms, DMA */
+       }
+       if (cur_rate != floppy->rate) {
+               /* use bit 6 of floppy->rate to indicate perpendicular mode */
+               perpendicular_mode(floppy->rate);
+               outb_p((cur_rate = (floppy->rate)) & ~0x40, FD_DCR);
+       }
 } /* configure_fdc_mode */
 
 
@@ -517,7 +549,8 @@ static void rw_interrupt(void)
                                request_done(0);
                                bad = 0;
                        } else if (ST1 & ST1_OR) {
-                               printk(DEVICE_NAME ": Over/Underrun - retrying\n");
+                               if (ftd_msg[ST0 & ST0_DS])
+                                       printk(DEVICE_NAME ": Over/Underrun - retrying\n");
                                /* could continue from where we stopped, but ... */
                                bad = 0;
                        } else if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) {
@@ -646,33 +679,6 @@ static void seek_interrupt(void)
        setup_rw_floppy();
 }
 
-/* Set perpendicular mode as required, based on data rate, if supported.
- * 80277: 1Mbps data rate only possible with 82077-1.
- * Untested!! TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
- */
-static void inline perpendicular_mode(unsigned char rate)
-{
-       if (fdc_version == FDC_TYPE_82077) {
-               output_byte(FD_PERPENDICULAR);
-               if (rate & 0x40) {
-                       unsigned char r = rate & 0x03;
-                       if (r == 0)
-                               output_byte(2); /* perpendicular, 500 kbps */
-                       else if (r == 3)
-                               output_byte(3); /* perpendicular, 1Mbps */
-                       else {
-                               printk(DEVICE_NAME ": Invalid data rate for perpendicular mode!\n");
-                               reset = 1;
-                       }
-               } else
-                       output_byte(0);         /* conventional mode */
-       } else {
-               if (rate & 0x40) {
-                       printk(DEVICE_NAME ": perpendicular mode not supported by FDC.\n");
-                       reset = 1;
-               }
-       }
-} /* perpendicular_mode */
 
 /*
  * This routine is called when everything should be correctly set up
@@ -683,17 +689,9 @@ static void transfer(void)
 {
        read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) &&
            (floppy->sect <= MAX_BUFFER_SECTORS);
-       if (cur_spec1 != floppy->spec1) {
-               cur_spec1 = floppy->spec1;
-               output_byte(FD_SPECIFY);
-               output_byte(cur_spec1);         /* hut etc */
-               output_byte(6);                 /* Head load time =6ms, DMA */
-       }
-       if (cur_rate != floppy->rate) {
-               /* use bit 6 of floppy->rate to indicate perpendicular mode */
-               perpendicular_mode(floppy->rate);
-               outb_p(cur_rate = ((floppy->rate)) & ~0x40, FD_DCR);
-       }
+
+       configure_fdc_mode();
+
        if (reset) {
                redo_fd_request();
                return;
@@ -702,6 +700,7 @@ static void transfer(void)
                setup_rw_floppy();
                return;
        }
+
        do_floppy = seek_interrupt;
        output_byte(FD_SEEK);
        if (read_track)
@@ -726,8 +725,10 @@ static void recal_interrupt(void)
        if (result()!=2 || (ST0 & 0xE0) == 0x60)
                reset = 1;
 /* Recalibrate until track 0 is reached. Might help on some errors. */
-       if ((ST0 & 0x10) == 0x10) recalibrate_floppy();
-       else redo_fd_request();
+       if ((ST0 & 0x10) == 0x10)
+               recalibrate_floppy();   /* FIXME: should limit nr of recalibrates */
+       else
+               redo_fd_request();
 }
 
 static void unexpected_floppy_interrupt(void)
@@ -766,8 +767,15 @@ static void reset_interrupt(void)
        output_byte(FD_SPECIFY);
        output_byte(cur_spec1);         /* hut etc */
        output_byte(6);                 /* Head load time =6ms, DMA */
-       configure_fdc_mode();           /* reprogram if smart fdc */
-       if (!recover) redo_fd_request();
+       configure_fdc_mode();           /* reprogram fdc */
+       if (initial_reset_flag) {
+               initial_reset_flag = 0;
+               recalibrate = 1;
+               reset = 0;
+               return;
+       }
+       if (!recover)
+               redo_fd_request();
        else {
                recalibrate_floppy();
                recover = 0;
@@ -787,12 +795,14 @@ static void reset_floppy(void)
        cur_spec1 = -1;
        cur_rate = -1;
        recalibrate = 1;
-       printk("Reset-floppy called\n");
+       need_configure = 1;
+       if (!initial_reset_flag)
+               printk("Reset-floppy called\n");
        cli();
-       outb_p(current_DOR & ~0x04,FD_DOR);
+       outb_p(current_DOR & ~0x04, FD_DOR);
        for (i=0 ; i<1000 ; i++)
                __asm__("nop");
-       outb(current_DOR,FD_DOR);
+       outb(current_DOR, FD_DOR);
        sti();
 }
 
@@ -808,7 +818,8 @@ static void floppy_shutdown(void)
 static void shake_done(void)
 {
        current_track = NO_TRACK;
-       if (inb(FD_DIR) & 0x80) request_done(0);
+       if (inb(FD_DIR) & 0x80)
+               request_done(0);
        redo_fd_request();
 }
 
@@ -846,8 +857,7 @@ static void floppy_on_interrupt(void)
                                keep_data[current_drive]--;
                }
                else {
-                       if (ftd_msg[current_drive] && current_type[
-                           current_drive] != NULL)
+                       if (ftd_msg[current_drive] && current_type[current_drive] != NULL)
                                printk("Disk type is undefined after disk "
                                    "change in fd%d\n",current_drive);
                        current_type[current_drive] = NULL;
@@ -919,7 +929,7 @@ repeat:
        if (format_status != FORMAT_BUSY) {
                if (!CURRENT) {
                        if (!fdc_busy)
-                               printk("FDC access conflict");
+                               printk("FDC access conflict!");
                        fdc_busy = 0;
                        wake_up(&fdc_wait);
                        CLEAR_INTR;
@@ -1209,13 +1219,13 @@ static struct file_operations floppy_fops = {
  * my FDC does, except when booting in SVGA screen mode.
  * When it does generate an interrupt, it doesn't return any status bytes.
  * It appears to have something to do with the version command...
+ *
+ * This should never be called, because of the reset after the version check.
  */
 static void ignore_interrupt(void)
 {
-       if (result() != 0) {
-               printk(DEVICE_NAME ": weird interrupt ignored\n");
-               reset = 1;
-       }
+       printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
+       reset = 1;
        CLEAR_INTR;     /* ignore only once */
 }
 
@@ -1251,8 +1261,9 @@ void floppy_init(void)
        timer_active &= ~(1 << FLOPPY_TIMER);
        config_types();
        if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
-               printk("Unable to grab IRQ%d for the floppy driver\n",FLOPPY_IRQ);
-
+               printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
+       if (request_dma(FLOPPY_DMA))
+               printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA);
        /* Try to determine the floppy controller type */
        DEVICE_INTR = ignore_interrupt; /* don't ask ... */
        output_byte(FD_VERSION);        /* get FDC version code */
@@ -1266,5 +1277,14 @@ void floppy_init(void)
 #ifndef FDC_FIFO_UNTESTED
        fdc_version = FDC_TYPE_STD;     /* force std fdc type; can't test other. */
 #endif
-       configure_fdc_mode();
+
+       /* Not all FDCs seem to be able to handle the version command
+        * properly, so force a reset for the standard FDC clones,
+        * to avoid interrupt garbage.
+        */
+
+       if (fdc_version == FDC_TYPE_STD) {
+               initial_reset_flag = 1;
+               reset_floppy();
+       }
 }
index 5e0342020141d0baa6da8d9160ffa54d8eb9efaa..c6aef54e3ff63a12c01296941c21794d1f6c9f2b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/config.h>
+#include <linux/locks.h>
 
 #include <asm/system.h>
 
@@ -56,23 +57,6 @@ struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
  */
 int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
 
-static inline void lock_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       bh->b_lock=1;
-       sti();
-}
-
-static inline void unlock_buffer(struct buffer_head * bh)
-{
-       if (!bh->b_lock)
-               printk("ll_rw_block.c: buffer not locked\n\r");
-       bh->b_lock = 0;
-       wake_up(&bh->b_wait);
-}
-
 /* RO fail safe mechanism */
 
 static long ro_bits[NR_BLK_DEV][8];
@@ -251,7 +235,7 @@ repeat:
        req->nr_sectors = 8;
        req->current_nr_sectors = 8;
        req->buffer = buffer;
-       req->waiting = &current->wait;
+       req->waiting = current;
        req->bh = NULL;
        req->next = NULL;
        current->state = TASK_UNINTERRUPTIBLE;
@@ -284,24 +268,6 @@ void ll_rw_block(int rw, struct buffer_head * bh)
        make_request(major,rw,bh);
 }
 
-long blk_dev_init(long mem_start, long mem_end)
-{
-       int i;
-
-       for (i=0 ; i<NR_REQUEST ; i++) {
-               request[i].dev = -1;
-               request[i].next = NULL;
-       }
-       memset(ro_bits,0,sizeof(ro_bits));
-#ifdef CONFIG_BLK_DEV_HD
-       mem_start = hd_init(mem_start,mem_end);
-#endif
-#ifdef RAMDISK
-       mem_start += rd_init(mem_start, RAMDISK*1024);
-#endif
-       return mem_start;
-}
-
 void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
 {
        int i;
@@ -341,7 +307,7 @@ repeat:
                req->nr_sectors = 2;
                req->current_nr_sectors = 2;
                req->buffer = buf;
-               req->waiting = &current->wait;
+               req->waiting = current;
                req->bh = NULL;
                req->next = NULL;
                current->state = TASK_UNINTERRUPTIBLE;
@@ -349,3 +315,21 @@ repeat:
                schedule();
        }
 }
+
+long blk_dev_init(long mem_start, long mem_end)
+{
+       int i;
+
+       for (i=0 ; i<NR_REQUEST ; i++) {
+               request[i].dev = -1;
+               request[i].next = NULL;
+       }
+       memset(ro_bits,0,sizeof(ro_bits));
+#ifdef CONFIG_BLK_DEV_HD
+       mem_start = hd_init(mem_start,mem_end);
+#endif
+#ifdef RAMDISK
+       mem_start += rd_init(mem_start, RAMDISK*1024);
+#endif
+       return mem_start;
+}
index 8690a91c51a0a1491760c8ca22645f74d78f3e7d..d70ee083086227d8fb6ee1566cca66321ef7fa9f 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <asm/memory.h>
 
 #define MAJOR_NR 1
 #include "blk.h"
index 7411950f19c96350e226772d76b1e79b459767e5..daa6f1fcb96e4e762bd6da3160550748db0a6a4b 100644 (file)
@@ -133,5 +133,5 @@ int wd7000fasst_reset(void);
                wd7000fasst_queuecommand,               \
                wd7000fasst_abort,                              \
                wd7000fasst_reset,                              \
-               1, 7, 0}
+               1, 7, 0, 1}
 #endif
index 06d0bcbc5c831eed4fc4a0a8dbe8361db21ab6fd..b49e1d30367d4b469fe79889153790d00b534d9f 100644 (file)
@@ -433,11 +433,6 @@ int aha1542_detect(int hostnum)
        return 0;
     }
  
-#ifndef MAX_16M
-  printk("Adaptec 1542 disabled for kernels without memory limiting to 16MB.\n");
-  return 0;
-#endif
-
     /* Set the Bus on/off-times as not to ruin floppy performens */
     {
        static unchar oncmd[] = {CMD_BUSON_TIME, 5};
index 5d3640fb5e86c899ba8ec980df396b67eed7f2ff..aa575448bacc232dbb424b50f24393bca4d037bc 100644 (file)
@@ -135,5 +135,5 @@ int aha1542_reset(void);
                aha1542_queuecommand,                   \
                aha1542_abort,                          \
                aha1542_reset,                          \
-               1, 7, 0}
+               1, 7, 0, 1}
 #endif
index 78f2b0944f40248cd4954fc990dfcb88060aaf2e..40e4609733e554d09e8b4f0df177b85de83e023c 100644 (file)
@@ -40,6 +40,6 @@ int  fdomain_16x0_queue( unsigned char target, const void *cmnd,
                         NULL,                             \
                         fdomain_16x0_abort,               \
                         fdomain_16x0_reset,               \
-                        0, 6, 0 }
+                        0, 6, 0 ,0}
 #endif
 #endif
index f5504d605ac33db22d261a7386f550760f1ba1fe..686aae3d033fc0646ccc3bffa7c841aacd977342 100644 (file)
@@ -143,6 +143,11 @@ typedef struct
        */
 
        unsigned present:1;     
+       /*
+         true if this host adapter uses unchecked DMA onto an ISA bus.
+       */
+       unsigned unchecked_isa_dma:1;
+
        } Scsi_Host;
 
 /*
index 164813d82297b1e85cbbbfdd5d3938a93a81cb41..fd7457e8fd1a60a298cbcfb6566a40ff4cc43cc7 100644 (file)
@@ -1105,7 +1105,7 @@ static void update_timeout(void)
 */
 
 static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};                
-void scsi_dev_init (void)
+unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end)
        {
        int i;
 #ifdef FOO_ON_YOU
@@ -1129,16 +1129,17 @@ void scsi_dev_init (void)
         scan_scsis();           /* scan for scsi devices */
 
 #ifdef CONFIG_BLK_DEV_SD
-       sd_init();              /* init scsi disks */
+       memory_start = sd_init(memory_start, memory_end);              /* init scsi disks */
 #endif
 
 #ifdef CONFIG_BLK_DEV_ST
-        st_init();              /* init scsi tapes */
+        memory_start = st_init(memory_start, memory_end);              /* init scsi tapes */
 #endif
 
 #ifdef CONFIG_BLK_DEV_SR
-       sr_init();
+       memory_start = sr_init(memory_start, memory_end);
 #endif
+       return memory_start;
        }
 #endif
 
index 7bf60275b84b43f7a3b23d4a5ea38356df930b12..14b9dde350bf96fc5ecd3958095fc740da605e8b 100644 (file)
@@ -253,7 +253,7 @@ extern int scsi_abort (int host, int code);
        Initializes all SCSI devices.  This scans all scsi busses.
 */
 
-extern void scsi_dev_init (void);
+extern unsigned long scsi_dev_init (unsigned long, unsigned long);
 
 /*
        You guesed it.  This sends a command to the selected SCSI host 
index 411fa64815e47a5854b9b8baf83815310a78641d..73c3ea94f07edabeaa2950d5f65b2cd6c836e8bd 100644 (file)
@@ -70,15 +70,16 @@ static void scsi_ioctl_done (int host, int result)
        the_result[host] = result;      
 }      
 
+/* This function will operate certain scsi functions which require no
+   data transfer */
 static int ioctl_internal_command(Scsi_Device *dev, char ** command)
 {
-       char * buf;
        char * cmd;
        int temp, host;
+       char sense_buffer[256];
 
        host = dev->host_no;
        cmd = command[0];
-       buf = command[1];
 
        do {
                cli();
@@ -93,16 +94,16 @@ static int ioctl_internal_command(Scsi_Device *dev, char ** command)
                }
        } while (1);
 
-       scsi_do_cmd(host,  dev->id,  cmd,  buf,  255,
+       scsi_do_cmd(host,  dev->id,  cmd,  NULL,  0,
                        scsi_ioctl_done,  MAX_TIMEOUT,
-                       buf,  MAX_RETRIES);
+                       sense_buffer,  MAX_RETRIES);
 
        while (the_result[host] == -1)
                /* nothing */;
        temp = the_result[host];
 
        if(driver_byte(the_result[host]) != 0)
-         switch(buf[2] & 0xf) {
+         switch(sense_buffer[2] & 0xf) {
          case ILLEGAL_REQUEST:
            printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
            break;
@@ -125,9 +126,9 @@ static int ioctl_internal_command(Scsi_Device *dev, char ** command)
                   dev->lun,
                   the_result);
            printk("\tSense class %x, sense error %x, extended sense %x\n",
-                  sense_class(buf[0]),
-                  sense_error(buf[0]),
-                  buf[2] & 0xf);
+                  sense_class(sense_buffer[0]),
+                  sense_error(sense_buffer[0]),
+                  sense_buffer[2] & 0xf);
 
          };
 
@@ -226,7 +227,6 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
                        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
                        scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
                        command[0] = scsi_cmd;
-                       command[1] = (char *) arg;
                        return ioctl_internal_command((Scsi_Device *) dev, command);
                        break;
                case SCSI_IOCTL_DOORUNLOCK:
@@ -236,7 +236,6 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
                        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
                        scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
                        command[0] = scsi_cmd;
-                       command[1] = (char *) arg;
                        return ioctl_internal_command((Scsi_Device *) dev, command);
                case SCSI_IOCTL_TEST_UNIT_READY:
                        scsi_cmd[0] = TEST_UNIT_READY;
@@ -244,7 +243,6 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
                        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
                        scsi_cmd[4] = 0;
                        command[0] = scsi_cmd;
-                       command[1] = (char *) arg;
                        return ioctl_internal_command((Scsi_Device *) dev, command);
                        break;
                default :                       
index 53fa133bb450696ebe9b74ef340836978e2e8e6e..3d05bd5545f7f1d39efabb3083e9e60450c170c6 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/system.h>
 
 #include "scsi.h"
+#include "hosts.h"
 #include "sd.h"
 #include "scsi_ioctl.h"
 
@@ -37,8 +38,19 @@ static const char RCSid[] = "$Header:";
 
 #define SD_TIMEOUT 200
 
+#define ISA_DMA_THRESHOLD (0x00ffffff)
 struct hd_struct sd[MAX_SD << 4];
 
+/* For a > 16 Mb system, we may need an intermediate buffer for data */
+
+struct block_buffer
+       {
+       unsigned long int use;
+       unsigned char   buffer[4096];
+       };
+
+static struct block_buffer * bb = NULL;
+
 int NR_SD=0;
 Scsi_Disk rscsi_disks[MAX_SD];
 static int sd_sizes[MAX_SD << 4] = {0, };
@@ -61,14 +73,16 @@ static int sd_open(struct inode * inode, struct file * filp)
         int target;
        target =  DEVICE_NR(MINOR(inode->i_rdev));
 
+       if(target >= NR_SD || !rscsi_disks[target].device)
+         return -EACCES;   /* 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. */
 
        while (rscsi_disks[target].device->busy);
 
        if(rscsi_disks[target].device->removable) {
-         if (filp->f_mode)
-           check_disk_change(inode->i_rdev);
+         check_disk_change(inode->i_rdev);
 
          if(!rscsi_disks[target].device->access_count)
            sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
@@ -150,6 +164,17 @@ static void rw_intr (int host, int result)
 */
 
        if (!result) {
+         if (bb && bb[DEVICE_NR(CURRENT->dev)].use && CURRENT->cmd == READ)
+           {
+             memcpy((char *)CURRENT->buffer, 
+                    bb[DEVICE_NR(CURRENT->dev)].buffer,
+                    this_count << 9);
+#ifdef DEBUG
+             printk("R");
+#endif
+           };
+         if(bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
+
                CURRENT->nr_sectors -= this_count;
                if (slow_scsi_io == host) {
                  total_count -= this_count;
@@ -199,7 +224,7 @@ static void rw_intr (int host, int result)
                else
                        end_request(1);
                do_sd_request();
-               }
+       }
 
 /*
  *     Of course, the error handling code is a little Fubar down in scsi.c.
@@ -214,12 +239,25 @@ static void rw_intr (int host, int result)
 */
 
        else if (driver_byte(result) & DRIVER_SENSE) {
+         if (bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
                if (sugestion(result) == SUGGEST_REMAP) {
 #ifdef REMAP
 /*
        Not yet implemented.  A read will fail after being remapped,
        a write will call the strategy routine again.
 */
+                       if rscsi_disks[DEVICE_NR(CURRENT->dev)].remap
+                               {
+                               result = 0;
+                               }
+                       else
+
+#endif
+               }
+
+/* A unit attention comes up if there is a media change on a removable
+   disk drive */
+
                else if ((sense_buffer[0] & 0x7f) == 0x70) {
                        if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
                                /* detected disc change.  set a bit and quietly refuse  */
@@ -230,16 +268,8 @@ static void rw_intr (int host, int result)
                                do_sd_request();
                                return;
                        }
-               }
-
-                       if rscsi_disks[DEVICE_NR(CURRENT->dev)].remap
-                               {
-                               result = 0;
-                               }
-                       else
+                     }
 
-#endif
-               }
 /*
        If we had an ILLEGAL REQUEST returned, then we may have performed
        an unsupported command.  The only thing this should be would be a  ten
@@ -247,7 +277,6 @@ static void rw_intr (int host, int result)
        system where READ CAPACITY failed, we mave have read past the end of the
        disk.
 */
-
                else if (sense_buffer[7] == ILLEGAL_REQUEST) {
                        if (rscsi_disks[DEVICE_NR(CURRENT->dev)].ten) {
                                rscsi_disks[DEVICE_NR(CURRENT->dev)].ten = 0;
@@ -258,6 +287,7 @@ static void rw_intr (int host, int result)
                }
        }
        if (result) {
+               if (bb) bb[DEVICE_NR(CURRENT->dev)].use = 0;
                printk("SCSI disk error : host %d id %d lun %d return code = %x\n",
                       rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no,
                       rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id,
@@ -284,6 +314,7 @@ static void do_sd_request (void)
 {
        int dev, block;
        unsigned char cmd[10];
+       char * buff;
 
 repeat:
        INIT_REQUEST;
@@ -357,6 +388,24 @@ repeat:
 
        cmd[1] = (LUN << 5) & 0xe0;
 
+       buff = CURRENT->buffer;
+
+/* Curses, curses. If this is a DMA transfer, we could be screwed. */
+       if (((int) buff) + (this_count << 9) > ISA_DMA_THRESHOLD && 
+           (scsi_hosts[HOST].unchecked_isa_dma)) {
+         if (bb[DEVICE_NR(CURRENT->dev)].use) panic ("block buffer already in use");
+         bb[DEVICE_NR(CURRENT->dev)].use = 1;
+         if(this_count > 8) this_count = 8;
+         if (CURRENT->cmd == WRITE) {
+           memcpy(bb[DEVICE_NR(CURRENT->dev)].buffer,
+                  (char *)CURRENT->buffer, this_count << 9);
+#ifdef DEBUG
+           printk("W");
+#endif
+         };
+         buff = bb[DEVICE_NR(CURRENT->dev)].buffer;
+       };
+
        if (((this_count > 0xff) ||  (block > 0x1fffff)) && rscsi_disks[dev].ten)
                {
                if (this_count > 0xffff)
@@ -383,7 +432,7 @@ repeat:
                cmd[5] = 0;
                }
 
-       scsi_do_cmd (HOST, ID, (void *) cmd, CURRENT->buffer, this_count << 9,
+       scsi_do_cmd (HOST, ID, (void *) cmd, buff, this_count << 9,
                     rw_intr, SD_TIMEOUT, sense_buffer, MAX_RETRIES);
 }
 
@@ -527,7 +576,7 @@ static int sd_init_onedisk(int i)
        their size, and reads partition table entries for them.
 */
 
-void sd_init(void)
+unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
 {
        int i;
 
@@ -539,6 +588,13 @@ void sd_init(void)
        sd_gendisk.next = gendisk_head;
        gendisk_head = &sd_gendisk;
        boot_init_done++;
+/* Allocate DMA block buffer */
+       if(memory_end > ISA_DMA_THRESHOLD) {
+         bb = (struct block_buffer *) memory_start;
+         memory_start += NR_SD * sizeof(struct block_buffer);
+         for (i=0; i < NR_SD; ++i) bb[i].use = 0;
+       };
+       return memory_start;
 }
 
 #define DEVICE_BUSY rscsi_disks[target].device->busy
@@ -567,6 +623,7 @@ int revalidate_scsidisk(int dev, int maxusage){
          sti();
          if (DEVICE_BUSY || USAGE > maxusage) {
            cli();
+           printk("Device busy for revalidation (usage=%d)\n", USAGE);
            return -EBUSY;
          };
          DEVICE_BUSY = 1;
index aacb01f9e943b1c11066011c5c040963f6a603a9..e36d364f3eb3ef2f4ba8247d8d8ba948abec94ad 100644 (file)
@@ -42,7 +42,7 @@ typedef struct {
        
 extern Scsi_Disk rscsi_disks[MAX_SD];
 
-void sd_init(void);
+unsigned long sd_init(unsigned long, unsigned long);
 
 #define HOST (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no)
 #define ID (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id)
index 0eb3b30da98f4b2988f3df5f0cd9e6056438895d..744f8d57617566f43647875f7ed354a9f492115e 100644 (file)
@@ -29,7 +29,7 @@ int seagate_st0x_reset(void);
 #define SEAGATE_ST0X  {"Seagate ST-01/ST-02", seagate_st0x_detect,     \
                         seagate_st0x_info, seagate_st0x_command,       \
                         seagate_st0x_queue_command, seagate_st0x_abort, \
-                        seagate_st0x_reset, 1, 7, 0}
+                        seagate_st0x_reset, 1, 7, 0, 0}
 #endif
 
 
index c84cf218408304a83b45cde631cf6971e441e1fa..97a16bcbf3b4e937769c28126dca32235566c2ed 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
+#include <linux/errno.h>
 
 #include "scsi.h"
 #include "sr.h"
@@ -42,7 +43,7 @@ struct block_buffer
        unsigned char   buffer[2048];
        };
 
-static struct block_buffer bb[MAX_SR];
+static struct block_buffer * bb;
 
 static int sr_open(struct inode *, struct file *);
 
@@ -220,8 +221,10 @@ static void rw_intr (int host, int result)
 
 static int sr_open(struct inode * inode, struct file * filp)
 {
-       if (filp->f_mode)
-               check_disk_change(inode->i_rdev);
+       if(MINOR(inode->i_rdev) >= NR_SR ||
+          !scsi_CDs[MINOR(inode->i_rdev)].device) return -EACCES;   /* No such device */
+
+        check_disk_change(inode->i_rdev);
 
        if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++)
          sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
@@ -370,10 +373,13 @@ void do_sr_request (void)
                     rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
 }
 
-void sr_init(void)
+unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
 {
        int i;
 
+       bb = (struct block_buffer *) memory_start;
+       memory_start += NR_SR * sizeof(struct block_buffer);
+
        for (i = 0; i < NR_SR; ++i)
                {
                scsi_CDs[i].capacity = 0x1fffff;
@@ -389,6 +395,7 @@ void sr_init(void)
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
        blk_size[MAJOR_NR] = sr_sizes;  
        blkdev_fops[MAJOR_NR] = &sr_fops; 
+       return memory_start;
 }      
 #endif
 
index 6cf0ece91bb315065583d7df8ebd453e62504ecf..865d8d0c20680f2c24fd8010bcf834733fbec805 100644 (file)
@@ -32,7 +32,7 @@ typedef struct
        
 extern Scsi_CD scsi_CDs[MAX_SR];
 
-void sr_init(void);
+unsigned long sr_init(unsigned long, unsigned long);
 
 #define SR_HOST (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no)
 #define SR_ID (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id)
index 1f8121771859af354c84657c90085cd0286ae88f..01feaacbd1def895e13a2042f1c13fc76c650501 100644 (file)
@@ -24,9 +24,11 @@ void do_st_request(void)
        panic("There is no st driver.\n\r");
 }
 
-void st_init(void)
+unsigned long st_init(unsigned long memory_start, unsigned long memory_end)
 {
        blk_dev[MAJOR_NR].request_fn = do_st_request;
        blk_size[MAJOR_NR] = st_sizes;
+       return memory_start;
 }
 #endif 
+
index 9ae0795bc7ed221ff8cc70c6ca6a1f6cfe41f3c6..ca957dfa4b6988755d01730b8d7c0f8b17e23770 100644 (file)
@@ -22,5 +22,5 @@ typedef struct
 
 extern int NR_ST;
 extern Scsi_Tape scsi_tapes[MAX_ST];
-void st_init(void);
+unsigned long st_init(unsigned long, unsigned long);
 #endif
index b88141945d8ac30eaf45f64bd8a78c9c535694b1..cf8c1ac2c4f0dfb627950a4f3d68ecd6f65b0efb 100644 (file)
@@ -43,7 +43,7 @@ int ultrastor_14f_reset(void);
 #define ULTRASTOR_14F \
     { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
       ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
-      0, 0, 0 }
+      0, 0, 0, 1 }
 #endif
 
 #define UD_ABORT 0x0001
index 6d0217a46a2bac521922279122a461c503f8c423..ac24701065ff90692b0ba22b07f7ce44b7a1a34c 100644 (file)
@@ -123,15 +123,17 @@ void keyboard_interrupt(int int_pt_regs)
                        rep = scancode;
                        repke0 = ke0;
                }
-       } else if (ke0 == repke0 && (scancode & 0x7f) == rep)
+       } else if (ke0 == repke0 && (scancode & 0x7f) == rep) {
                if (scancode & 0x80)
                        rep = 0xff;
-               else if (!(krepeat && tty && (L_ECHO(tty) ||
-                                             (EMPTY(&tty->secondary) &&
-                                              EMPTY(&tty->read_q))))) {
+               else if (!(krepeat && tty &&
+                          (L_ECHO(tty) ||
+                           (EMPTY(&tty->secondary) &&
+                            EMPTY(&tty->read_q))))) {
                        ke0 = 0;
                        return;
                }
+       }
        key_table[scancode](scancode);
        do_keyboard_interrupt();
        ke0 = 0;
@@ -1351,12 +1353,11 @@ long no_idt[2] = {0, 0};
 void hard_reset_now(void)
 {
        int i;
-       unsigned long * pg_dir;
+       extern unsigned long pg0[1024];
 
        sti();
 /* rebooting needs to touch the page at absolute addr 0 */
-       pg_dir = (unsigned long *) current->tss.cr3;
-       pg_dir[768] = 7;                        /* 0xC0000000 */
+       pg0[0] = 7;
        for (;;) {
                for (i=0; i<100; i++) {
                        kb_wait();
index e0e2f2538dfc01f641a2fd5862a4028f84111da3..bfa02c76aeae18af06a90811953a8927edb4dd57 100644 (file)
@@ -1,25 +1,19 @@
 /*
- $Header: /usr/src/linux/kernel/chr_drv/lp.c,v 1.9 1992/01/06 16:11:19
-  james_r_wiegand Exp james_r_wiegand $
-*/
-
-/*
- * Edited by Linus - cleaner interface etc. Still not using interrupts, so
- * it eats more resources than necessary, but it was easy to code this way...
+ * Copyright (C) 1992 by Jim Weigand, Linus Torvalds, and Michael K. Johnson
  */
 
-#include <linux/sched.h>
 #include <linux/lp.h>
+/* sched.h is included from lp.h */
 
 static int lp_reset(int minor)
 {
        int testvalue;
 
        /* reset value */
-       outb(0, LP_B(minor)+2);
+       outb(0, LP_C(minor));
        for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
                ;
-       outb(LP_PSELECP | LP_PINITP, LP_B(minor)+2);
+       outb(LP_PSELECP | LP_PINITP, LP_C(minor));
        return LP_S(minor);
 }
 
@@ -31,18 +25,20 @@ static int lp_char(char lpchar, int minor)
        outb(lpchar, LP_B(minor));
        do {
                retval = LP_S(minor);
-               schedule(); 
                count ++;
-       } while(!(retval & LP_PBUSY) && count < LP_TIMEOUT);
-       if (count == LP_TIMEOUT) {
-               printk("lp%d timeout\n\r", minor);
+               if (need_resched)
+                       schedule();
+       } while(!(retval & LP_PBUSY) && count < LP_TIME_CHAR);
+
+       if (count == LP_TIME_CHAR) {
                return 0;
+               /* we timed out, and the character was /not/ printed */
        }
-  /* control port pr_table[0]+2 take strobe high */
-       outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_B( minor ) + 2 ));
-  /* take strobe low */
-       outb(( LP_PSELECP | LP_PINITP ), ( LP_B( minor ) + 2 ));
-  /* get something meaningful for return value */
+        /* control port takes strobe high */
+       outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
+        /* take strobe low */
+       outb(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
+       /* get something meaningful for return value */
        return LP_S(minor);
 }
 
@@ -50,31 +46,69 @@ static int lp_write(struct inode * inode, struct file * file, char * buf, int co
 {
        int  retval;
        unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int each_cnt = 0, old_cnt = 0;
        char c, *temp = buf;
 
        temp = buf;
        while (count > 0) {
-               c = get_fs_byte(temp++);
+               c = get_fs_byte(temp);
                retval = lp_char(c, minor);
-               count--;
-               if (retval & LP_POUTPA) {
-                       LP_F(minor) |= LP_NOPA;
-                       return temp-buf?temp-buf:-ENOSPC;
-               } else
-                       LP_F(minor) &= ~LP_NOPA;
-
-               if (!(retval & LP_PSELECD)) {
-                       LP_F(minor) &= ~LP_SELEC;
-                       return temp-buf?temp-buf:-EFAULT;
-               } else
-                       LP_F(minor) &= ~LP_SELEC;
-
-    /* not offline or out of paper. on fire? */
-               if (!(retval & LP_PERRORP)) {
-                       LP_F(minor) |= LP_ERR;
-                       return temp-buf?temp-buf:-EIO;
-               } else
-                       LP_F(minor) &= ~LP_SELEC;
+               /* only update counting vars if character was printed */
+               if (retval) {
+                       count--;
+                       temp++;
+               }
+
+               if (!retval) { /* if printer timed out */
+                       each_cnt = count - old_cnt;
+                       old_cnt = count;
+
+                       /* here we do calculations based on old count
+                          and change the time that we will sleep.
+                          For now this will be hard coded... */
+
+                       /* check for signals before going to sleep */
+                       if (current->signal & ~current->blocked) {
+                               return temp-buf?temp-buf:-ERESTARTSYS;
+                       }
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + LP_TIME(minor);
+                       schedule();
+                       LP_COUNT(minor) = each_cnt;
+
+                       /* the following is ugly, but should alert me if
+                          something dreadful is going on. It will disappear
+                          in the final versions of the driver. */
+                       if (!(LP_S(minor) & LP_BUSY)) {
+                               current->state = TASK_INTERRUPTIBLE;
+                               current->timeout = jiffies + LP_TIMEOUT;
+                               schedule();
+                               if (!(LP_S(minor) & LP_BUSY))
+                                       printk("lp%d timeout\n\r", minor);
+                       }
+               } else {
+                       if (retval & LP_POUTPA) {
+                               LP_F(minor) |= LP_NOPA;
+                               printk("lp%d out of paper\n\r", minor);
+                               return temp-buf?temp-buf:-ENOSPC;
+                       } else
+                               LP_F(minor) &= ~LP_NOPA;
+
+                       if (!(retval & LP_PSELECD)) {
+                               LP_F(minor) |= LP_SELEC;
+                               printk("lp%d off-line\n\r", minor);
+                               return temp-buf?temp-buf:-EFAULT;
+                       } else
+                               LP_F(minor) &= ~LP_SELEC;
+
+                       /* not offline or out of paper. on fire? */
+                       if (!(retval & LP_PERRORP)) {
+                               LP_F(minor) |= LP_ERR;
+                               printk("lp%d on fire\n\r", minor);
+                               return temp-buf?temp-buf:-EIO;
+                       } else
+                               LP_F(minor) &= ~LP_SELEC;
+               }
        }
        return temp-buf;
 }
@@ -111,13 +145,13 @@ static void lp_release(struct inode * inode, struct file * file)
 }
 
 static struct file_operations lp_fops = {
-       lp_lseek,
-       lp_read,
+       lp_lseek,       /* why not null? */
+       lp_read,        /* why not null? */
        lp_write,
        NULL,           /* lp_readdir */
        NULL,           /* lp_select */
        NULL,           /* lp_ioctl */
-       NULL,           /* lp_mmap */
+       NULL,           /* mmap */
        lp_open,
        lp_release
 };
index 301d06705116af2f3cd6a7bbf440dfad8cbf2df2..ca486b55a81c284eee3ec442b29823aa2de297d5 100644 (file)
 #include <linux/tty.h>
 #include <linux/mouse.h>
 
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/string.h>
+
 #include <asm/segment.h>
 #include <asm/io.h>
 
@@ -24,6 +28,51 @@ static int write_ram(struct inode * inode, struct file * file,char * buf, int co
        return -EIO;
 }
 
+static int read_core(struct inode * inode, struct file * file,char * buf, int count)
+{
+       unsigned long p = file->f_pos;
+       int read;
+       int count1;
+       char * pnt;
+       struct user dump;
+
+       memset(&dump, 0, sizeof(struct user));
+       dump.magic = CMAGIC;
+       dump.u_dsize = high_memory >> 12;
+
+       if (count < 0)
+               return -EINVAL;
+       if (p >= high_memory)
+               return 0;
+       if (count > high_memory - p)
+               count = high_memory - p;
+       read = 0;
+
+       if (p < sizeof(struct user) && count > 0) {
+               count1 = count;
+               if (p + count1 > sizeof(struct user))
+                       count1 = sizeof(struct user)-p;
+               pnt = (char *) &dump + p;
+               memcpy_tofs(buf,(void *) pnt, count1);
+               buf += count1;
+               p += count1;
+               count -= count1;
+               read += count1;
+       }
+
+       while (p < (4096 + 4096) && count > 0) {
+               put_fs_byte(0,buf);
+               buf++;
+               p++;
+               count--;
+               read++;
+       }
+       memcpy_tofs(buf,(void *) (p - 4096),count);
+       read += count;
+       file->f_pos += read;
+       return read;
+}
+
 static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
 {
        unsigned long p = file->f_pos;
@@ -228,6 +277,18 @@ static struct file_operations zero_fops = {
        NULL            /* no special release code */
 };
 
+static struct file_operations core_fops = {
+       memory_lseek,
+       read_core,
+       NULL,
+       NULL,           /* zero_readdir */
+       NULL,           /* zero_select */
+       NULL,           /* zero_ioctl */
+       NULL,           /* zero_mmap */
+       NULL,           /* no special open code */
+       NULL            /* no special release code */
+};
+
 static int memory_open(struct inode * inode, struct file * filp)
 {
        switch (MINOR(inode->i_rdev)) {
@@ -249,6 +310,9 @@ static int memory_open(struct inode * inode, struct file * filp)
                case 5:
                        filp->f_op = &zero_fops;
                        break;
+               case 6:
+                       filp->f_op = &core_fops;
+                       break;
                default:
                        return -ENODEV;
        }
index e867647ba87d9e207cd1fd08efdcc5fea1703219..62cf0b67c3c91dd840734f9c95bc0baf41a18fad 100644 (file)
@@ -235,7 +235,11 @@ static void UART_ISR_proc(async_ISR ISR, int line)
                        info->timer = jiffies + info->timeout;
                        if (info->timer < timer_table[RS_TIMER].expires)
                                timer_table[RS_TIMER].expires = info->timer;
+#ifdef i386
                        rs_write_active |= 1 << line;
+#else
+                       set_bit(line, &rs_write_active);
+#endif
                        timer_active |= 1 << RS_TIMER;
                }
        no_xmit:
@@ -328,6 +332,11 @@ static void rs_timer(void)
                if ((mask > rs_event) &&
                    (mask > rs_write_active))
                        break;
+               if (!info->tty) {       /* check that we haven't closed it.. */
+                       rs_event &= ~mask;
+                       rs_write_active &= ~mask;
+                       continue;
+               }
                if (mask & rs_event) {
                        if (!clear_bit(RS_EVENT_READ_PROCESS, &info->event)) {
                                TTY_READ_FLUSH(info->tty);
@@ -357,7 +366,11 @@ static void rs_timer(void)
                }
                if (mask & rs_write_active) {
                        if (info->timer <= jiffies) {
+#ifdef i386
                                rs_write_active &= ~mask;
+#else
+                               clear_bit(info->line, &rs_write_active);
+#endif
                                rs_write(info->tty);
                        }
                        if ((mask & rs_write_active) &&
@@ -405,8 +418,10 @@ static void rs_throttle(struct tty_struct * tty, int status)
        struct async_struct *info;
        unsigned char mcr;
 
+#ifdef notdef
        printk("throttle tty%d: %d (%d, %d)....\n", DEV_TO_SL(tty->line),
               status, LEFT(&tty->read_q), LEFT(&tty->secondary));
+#endif
        switch (status) {
        case TTY_THROTTLE_RQ_FULL:
                info = rs_table + DEV_TO_SL(tty->line);
@@ -460,6 +475,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        if (!info->port)
                return;
        shutdown(info);
+#ifdef i386
+       rs_write_active &= ~(1 << line);
+       rs_event &= ~(1 << line);
+#else
+       clear_bit(line, &rs_write_active);
+       clear_bit(line, &rs_event);
+#endif
+       info->event = 0;
        info->tty = 0;
        ISR = info->ISR;
        irq = ISR->irq;
@@ -556,7 +579,7 @@ void change_speed(unsigned int line)
        struct async_struct * info;
        unsigned short port;
        int     quot = 0;
-       unsigned cflag,cval;
+       unsigned cflag,cval,mcr;
        int     i;
 
        if (line >= NR_PORTS)
@@ -589,8 +612,11 @@ void change_speed(unsigned int line)
                quot = 0;
                info->timeout = 0;
        }
-       if (!quot) {
-               shutdown(info);
+       mcr = inb(UART_MCR + port);
+       if (quot) 
+               outb(mcr | UART_MCR_DTR, UART_MCR + port);
+       else {
+               outb(mcr & ~UART_MCR_DTR, UART_MCR + port);
                return;
        }
        /* byte size and parity */
@@ -844,6 +870,7 @@ int rs_open(struct tty_struct *tty, struct file * filp)
                IRQ_ISR[irq] = ISR;
        }
        startup(info);
+       change_speed(info->line);
        return 0;
 }
 
@@ -950,8 +977,6 @@ static void init(struct async_struct * info)
                }
        } else
                info->type = PORT_8250;
-       startup(info);
-       change_speed(info->line);
        shutdown(info);
 }
 
index 4117fe7af800d6578bdf38558374e3944036e73a..2b25ca4391cd519ccb44057eafd3d0f8edfdfc72 100644 (file)
@@ -50,7 +50,7 @@ struct termios *tty_termios[256]; /* We need to keep the termios state */
  */
 int fg_console = 0;
 struct tty_struct * redirect = NULL;
-struct wait_queue * keypress_wait;
+struct wait_queue * keypress_wait = NULL;
 
 int initialize_tty_struct(struct tty_struct *tty, int line);
 
@@ -545,41 +545,54 @@ static int tty_open(struct inode * inode, struct file * filp)
        if (dev < 0)
                return -ENODEV;
        filp->f_rdev = 0x0400 | dev;
-       tty = TTY_TABLE(dev);
-       if (!tty) {
-               tty = TTY_TABLE(dev) = (struct tty_struct *)
-                       get_free_page(GFP_KERNEL);
-               if (!tty)
-                       return -ENOMEM;
-               retval = initialize_tty_struct(tty, TTY_TABLE_IDX(dev));
-               if (retval) {
-                       free_page((unsigned long)tty);
-                       return retval;
-               }
-               if (IS_A_PTY(dev) && !tty_table[PTY_OTHER(dev)]) {
-                       o_tty = (struct tty_struct *) get_free_page(GFP_USER);
-                       /*
-                        * Check for race condition, since get_free_page may sleep.
-                        */
-                       if (tty_table[PTY_OTHER(dev)]) {
-                               free_page((unsigned long) o_tty);
-                               goto other_done;
-                       }
-                       tty_table[PTY_OTHER(dev)] = o_tty;
-                       if (!o_tty) {
-                               free_page((unsigned long)tty);
-                               return -ENOMEM;
-                       }
-                       retval = initialize_tty_struct(o_tty, PTY_OTHER(dev));
+/*
+ * There be race-conditions here... Lots of them. Careful now.
+ */
+       tty = o_tty = NULL;
+       if (!TTY_TABLE(dev)) {
+               tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
+               if (tty) {
+                       retval = initialize_tty_struct(tty, TTY_TABLE_IDX(dev));
                        if (retval) {
-                               free_page((unsigned long) tty);
-                               free_page((unsigned long) o_tty);
+                               free_page((unsigned long)tty);
                                return retval;
                        }
-                       tty->link = o_tty;
-                       o_tty->link = tty;
                }
-       other_done:
+       }
+       if (IS_A_PTY(dev)) {
+               if (!tty_table[PTY_OTHER(dev)]) {
+                       o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL);
+                       if (o_tty) {
+                               retval = initialize_tty_struct(o_tty, PTY_OTHER(dev));
+                               if (retval) {
+                                       free_page((unsigned long) tty);
+                                       free_page((unsigned long) o_tty);
+                                       return retval;
+                               }
+                       }
+               }
+               if (!o_tty && !tty_table[PTY_OTHER(dev)]) {
+                       free_page((unsigned long) tty);
+                       return -ENOMEM;
+               }
+       }
+       if (TTY_TABLE(dev)) {
+               free_page((unsigned long) tty);
+               tty = TTY_TABLE(dev);
+       } else if (tty)
+               TTY_TABLE(dev) = tty;
+       else {
+               free_page((unsigned long) o_tty);
+               return -ENOMEM;
+       }
+       if (IS_A_PTY(dev)) {
+               if (tty_table[PTY_OTHER(dev)]) {
+                       free_page((unsigned long) o_tty);
+                       o_tty = tty_table[PTY_OTHER(dev)];
+               } else
+                       tty_table[PTY_OTHER(dev)] = o_tty;
+               tty->link = o_tty;
+               o_tty->link = tty;
        }
        if (IS_A_PTY_MASTER(dev)) {
                if (tty->count)
@@ -791,11 +804,11 @@ int initialize_tty_struct(struct tty_struct *tty, int line)
                        tp->c_oflag = OPOST | ONLCR;
                        tp->c_cflag = B38400 | CS8 | CREAD;
                        tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE;
-               } else if IS_A_SERIAL(line) {
+               } else if (IS_A_SERIAL(line)) {
                        tp->c_cflag = B2400 | CS8 | CREAD | HUPCL;
-               } else if IS_A_PTY_MASTER(line) {
+               } else if (IS_A_PTY_MASTER(line)) {
                        tp->c_cflag = B9600 | CS8 | CREAD;
-               } else if IS_A_PTY_SLAVE(line) {
+               } else if (IS_A_PTY_SLAVE(line)) {
                        tp->c_cflag = B9600 | CS8 | CREAD;
                        tp->c_lflag = ISIG | ICANON;
                }
@@ -820,7 +833,6 @@ long tty_init(long kmem_start)
 
        chrdev_fops[4] = &tty_fops;
        chrdev_fops[5] = &tty_fops;
-       keypress_wait = 0;
        for (i=0 ; i<256 ; i++) {
                tty_table[i] =  0;
                tty_termios[i] = 0;
index 4b2996ee0e4e32ee57abbb7b128b408b5ea1ad4f..2ecf89fadaf571da2407b2bc912f8ce4f7051dbb 100644 (file)
@@ -392,6 +392,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                redirect = tty;
                        return 0;
                case FIONBIO:
+                       arg = get_fs_long((unsigned long *) arg);
                        if (arg)
                                file->f_flags |= O_NONBLOCK;
                        else
diff --git a/kernel/dma.c b/kernel/dma.c
new file mode 100644 (file)
index 0000000..e168383
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Header: /sys/linux-0.97/kernel/RCS/dma.c,v 1.4 1992/09/18 02:54:14 root Exp $
+ * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
+ * Written by Hennus Bergman, 1992. 
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/dma.h>
+
+
+/* A note on resource allocation:
+ *
+ * All drivers needing DMA channels, should allocate and release them
+ * through the public routines `request_dma()' and `free_dma()'.
+ *
+ * In order to avoid problems, all processes should allocate resources in
+ * the same sequence and release them in the reverse order.
+ * 
+ * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
+ * When releasing them, first release the DMA, then release the IRQ.
+ * If you don't, you may cause allocation requests to fail unnecessarily.
+ * This doesn't really matter now, but it will once we get real semaphores
+ * in the kernel.
+ */
+
+
+
+/* Channel n is busy iff dma_chan_busy[n] != 0.
+ * DMA0 is reserved for DRAM refresh, I think.
+ * DMA4 is reserved for cascading (?).
+ */
+static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = {
+       1, 0, 0, 0, 1, 0, 0, 0
+};
+
+
+
+/* Atomically swap memory location [32 bits] with `newval'.
+ * This avoid the cli()/sti() junk and related problems.
+ * [And it's faster too :-)]
+ * Maybe this should be in include/asm/mutex.h and be used for
+ * implementing kernel-semaphores as well.
+ */
+static unsigned int __inline__ mutex_atomic_swap(volatile unsigned int * p, unsigned int newval)
+{
+       unsigned int semval = newval;
+
+       /* If one of the operands for the XCHG instructions is a memory ref,
+        * it makes the swap an uninterruptible RMW cycle.
+        *
+        * One operand must be in memory, the other in a register, otherwise
+        * the swap may not be atomic.
+        */
+
+       asm __volatile__ ("xchgl %2, %0\n"
+                       : /* outputs: semval   */ "=r" (semval)
+                       : /* inputs: newval, p */ "0" (semval), "m" (*p)
+                       );      /* p is a var, containing an address */
+       return semval;
+} /* mutex_atomic_swap */
+
+
+
+int request_dma(unsigned int dmanr)
+{
+       if (dmanr >= MAX_DMA_CHANNELS)
+               return -EINVAL;
+
+       if (mutex_atomic_swap(&dma_chan_busy[dmanr], 1) != 0)
+               return -EBUSY;
+       else
+               /* old flag was 0, now contains 1 to indicate busy */
+               return 0;
+} /* request_dma */
+
+
+void free_dma(unsigned int dmanr)
+{
+       if (dmanr >= MAX_DMA_CHANNELS) {
+               printk("Trying to free DMA%d\n", dmanr);
+               return;
+       }
+
+       if (mutex_atomic_swap(&dma_chan_busy[dmanr], 0) == 0)
+               printk("Trying to free free DMA%d\n", dmanr);
+} /* free_dma */
+
index 6b7e65e78ca8d618c15cd6c0b76d766bc95e0009..d7a0891808cac53f26d24079b7dbc49c54697415 100644 (file)
@@ -205,30 +205,6 @@ int kill_pg(int pgrp, int sig, int priv)
        return(found ? 0 : retval);
 }
 
-/* This routine is used by vhangup.  It send's sigkill to everything
-   waiting on a particular wait_queue.  It assumes root privledges.
-   We don't want to destroy the wait queue here, because the caller
-   should call wake_up immediately after calling kill_wait. */
-
-void
-kill_wait (struct wait_queue **q, int sig)
-{
-   struct wait_queue *next;
-   struct wait_queue *tmp;
-   struct task_struct *p;
-   
-   if (!q || !(next = *q))
-     return;
-   do { 
-      tmp = next;
-      next = tmp->next;
-      if (p = tmp->task)
-       {
-          send_sig (sig, p , 1);
-       }
-   } while (next && next != *q);
-}
-
 int kill_proc(int pid, int sig, int priv)
 {
        struct task_struct **p;
index 5d68ca6dc68007fda7eed739e3ed66952f850646..dc7677d0c2c6b4884ae301cf2835242b7d216729 100644 (file)
@@ -198,20 +198,19 @@ void wake_one_task(struct task_struct * p)
 /*
  * wake_up doesn't wake up stopped processes - they have to be awakened
  * with signals or similar.
+ *
+ * Note that this doesn't need cli-sti pairs: interrupts may not change
+ * the wait-queue structures directly, but only call wake_up() to wake
+ * a process. The process itself must remove the queue once it has woken.
  */
 void wake_up(struct wait_queue **q)
 {
-       struct wait_queue *tmp, *next;
+       struct wait_queue *tmp;
        struct task_struct * p;
-       unsigned long flags;
 
-       if (!q || !(next = *q))
+       if (!q || !(tmp = *q))
                return;
-       save_flags(flags);
-       cli();
        do {
-               tmp = next;
-               next = tmp->next;
                if (p = tmp->task) {
                        if (p->state == TASK_ZOMBIE)
                                printk("wake_up: TASK_ZOMBIE\n");
@@ -221,9 +220,17 @@ void wake_up(struct wait_queue **q)
                                        need_resched = 1;
                        }
                }
-               tmp->next = NULL;
-       } while (next && next != *q);
-       restore_flags(flags);
+#ifdef DEBUG
+               if (!tmp->next) {
+                       printk("wait_queue is bad\n");
+                       printk("        q = %08x\n",q);
+                       printk("       *q = %08x\n",*q);
+                       printk("      tmp = %08x\n",tmp);
+                       break;
+               }
+#endif
+               tmp = tmp->next;
+       } while (tmp != *q);
 }
 
 static inline void __sleep_on(struct wait_queue **p, int state)
@@ -234,12 +241,9 @@ static inline void __sleep_on(struct wait_queue **p, int state)
                return;
        if (current == task[0])
                panic("task[0] trying to sleep");
-       if (current->wait.next)
-               printk("__sleep_on: wait->next exists\n");
-       save_flags(flags);
-       cli();
        current->state = state;
        add_wait_queue(p,&current->wait);
+       save_flags(flags);
        sti();
        schedule();
        remove_wait_queue(p,&current->wait);
index c5f0dfebb86eba0bc3ecf9df54e4556ff8a283b8..8343267201c795ab9607ddb8e3ed8958053cf9e2 100644 (file)
@@ -66,26 +66,6 @@ int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
     return -ERESTARTNOINTR;            /* handle the signal, and come back */
 }
 
-static inline void save_old(char * from,char * to)
-{
-       int i;
-
-       verify_area(to, sizeof(struct sigaction));
-       for (i=0 ; i< sizeof(struct sigaction) ; i++) {
-               put_fs_byte(*from,to);
-               from++;
-               to++;
-       }
-}
-
-static inline void get_new(char * from,char * to)
-{
-       int i;
-
-       for (i=0 ; i< sizeof(struct sigaction) ; i++)
-               *(to++) = get_fs_byte(from++);
-}
-
 int sys_signal(int signum, long handler, long restorer)
 {
        struct sigaction tmp;
@@ -104,19 +84,24 @@ int sys_signal(int signum, long handler, long restorer)
 int sys_sigaction(int signum, const struct sigaction * action,
        struct sigaction * oldaction)
 {
-       struct sigaction tmp;
+       struct sigaction new, *p;
 
        if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
                return -EINVAL;
-       tmp = current->sigaction[signum-1];
-       get_new((char *) action,
-               (char *) (signum-1+current->sigaction));
-       if (oldaction)
-               save_old((char *) &tmp,(char *) oldaction);
-       if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
-               current->sigaction[signum-1].sa_mask = 0;
-       else
-               current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
+       p = signum - 1 + current->sigaction;
+       if (action) {
+               memcpy_fromfs(&new, action, sizeof(struct sigaction));
+               if (new.sa_flags & SA_NOMASK)
+                       new.sa_mask = 0;
+               else
+                       new.sa_mask |= (1<<(signum-1));
+       }
+       if (oldaction) {
+               verify_area(oldaction, sizeof(struct sigaction));
+               memcpy_tofs(oldaction, p, sizeof(struct sigaction));
+       }
+       if (action)
+               *p = new;
        return 0;
 }
 
index f5cd7361a08da45994e013f489608ec225d2d473..eafed474d933a99244791ec8acfb9162291ede07 100644 (file)
@@ -564,7 +564,7 @@ int sys_sethostname(char *name, int len)
        return 0;
 }
 
-int sys_getrlimit(int resource, struct rlimit *rlim)
+int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 {
        if (resource >= RLIM_NLIMITS)
                return -EINVAL;
@@ -576,7 +576,7 @@ int sys_getrlimit(int resource, struct rlimit *rlim)
        return 0;       
 }
 
-int sys_setrlimit(int resource, struct rlimit *rlim)
+int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
        struct rlimit new, *old;
 
index 3613e3817a0e7bd5ddd4b3d52ee9b72227483c21..03b33c101002c5be69f251f6c39d2889cc3bc15a 100644 (file)
 #include <stdarg.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+       unsigned long result = 0,value;
+
+       if (!base) {
+               base = 10;
+               if (*cp == '0') {
+                       base = 8;
+                       cp++;
+                       if ((*cp == 'x') && isxdigit(cp[1])) {
+                               cp++;
+                               base = 16;
+                       }
+               }
+       }
+       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+           ? toupper(*cp) : *cp)-'A'+10) < base) {
+               result = result*base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+       return result;
+}
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)    ((c) >= '0' && (c) <= '9')
index e9c5cacc5305182f1ad22cf5f03c5437a10c4811..fe0a74ce40396450b972038ab54d19940bdb5438 100644 (file)
@@ -55,6 +55,8 @@
 
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/string.h>
+
 #include <asm/system.h>
 
 struct bucket_desc {   /* 16 bytes */
@@ -142,6 +144,7 @@ void *malloc(unsigned int len)
                printk("malloc called with impossibly large argument (%d)\n", len);
                return NULL;
        }
+       len = bdir->size;
        /*
         * Now we search for a bucket descriptor which has free space
         */
@@ -165,7 +168,7 @@ void *malloc(unsigned int len)
                bdesc = free_bucket_desc;
                free_bucket_desc = bdesc->next;
                bdesc->refcnt = 0;
-               bdesc->bucket_size = bdir->size;
+               bdesc->bucket_size = len;
                bdesc->page = bdesc->freeptr =
                  (void *) cp = get_free_page(GFP_ATOMIC);
                if (!cp) {
@@ -173,9 +176,9 @@ void *malloc(unsigned int len)
                        return NULL;
                }
                /* Set up the chain of free objects */
-               for (i=PAGE_SIZE/bdir->size; i > 1; i--) {
-                       *((char **) cp) = cp + bdir->size;
-                       cp += bdir->size;
+               for (i=PAGE_SIZE/len; i > 1; i--) {
+                       *((char **) cp) = cp + len;
+                       cp += len;
                }
                *((char **) cp) = 0;
                bdesc->next = bdir->chain; /* OK, link it in! */
@@ -185,6 +188,7 @@ void *malloc(unsigned int len)
        bdesc->freeptr = *((void **) retval);
        bdesc->refcnt++;
        sti();  /* OK, we're safe again */
+       memset(retval, 0, len);
        return retval;
 }
 
index 3c56e1611849efc723b134d962811e9e0bf9855c..6512d7fd6fdc6485b954e3d036d1cbf6e403ade2 100644 (file)
@@ -739,6 +739,10 @@ void do_no_page(unsigned long error_code, unsigned long address,
                        nr[i] = bmap(inode,block);
                bread_page(page,inode->i_dev,nr);
        }
+       if (share_page(tsk,inode,address)) {
+               free_page(page);
+               return;
+       }
        i = address + PAGE_SIZE - tsk->end_data;
        if (i > PAGE_SIZE-1)
                i = 0;
index ad3a7dc830edc730817ae443e3263c2f8d27910a..1b2578ffd9ed01acadd1fe6a5eca12f0554837a2 100644 (file)
@@ -286,10 +286,10 @@ create_arp (unsigned long paddr, unsigned char *addr, int hlen)
   apt->hlen =hlen;
   memcpy (apt->hard, addr, hlen);
   apt->last_used=timer_seq;
-  sti();
-  apt->next = arp_table[hash];
-  arp_table[hash]=apt;
   cli();
+  apt->next = arp_table[hash];
+  arp_table[hash] = apt;
+  sti();
   return (apt);
 }
 
@@ -439,7 +439,6 @@ arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
   return (1);
 }
 
-
 void
 arp_add (unsigned long addr, unsigned char *haddr, struct device *dev)
 {
@@ -461,7 +460,6 @@ arp_add_broad (unsigned long addr, struct device *dev)
   arp_add (addr,  dev->broadcast , dev);
 }
 
-
 void
 arp_queue(struct sk_buff *skb)
 {
@@ -473,13 +471,11 @@ arp_queue(struct sk_buff *skb)
        skb->prev = skb;
      }
    else
-    {
-      skb->next = arp_q;
-      skb->prev = arp_q->prev;
-      skb->next->prev = skb;
-      skb->prev->next = skb;
-    }
-  sti();
-
+     {
+       skb->next = arp_q;
+       skb->prev = arp_q->prev;
+       skb->next->prev = skb;
+       skb->prev->next = skb;
+     }
+   sti();
 }
-
index 3fd63054e46d0ac72aeaffdfc59bbbeadd8af1da..4c9607691fff6691b6c4c99a09b6c59ed1446728 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/socket.h>
 #include <netinet/in.h>
-#include <asm/memory.h>
 #include "dev.h"
 #include "eth.h"
 #include "timer.h"
index 3e6fccd6a7620845942c60d578efb779c7033ea9..cfa92204ac46364d88e1c490e38bf728a9d0c46b 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/socket.h>
 #include <netinet/in.h>
-#include <asm/memory.h>
 #include "dev.h"
 #include "eth.h"
 #include "timer.h"
index d9f8b4a927a03ac1bfc8805e3f15bcd5064434c5..163a2d81f95b2b2fb0b3576bcb46173e62808339 100644 (file)
 #include <linux/tty.h>
 #include <linux/types.h>
 #include <linux/ptrace.h>
+#include <linux/string.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
-#include <asm/memory.h>
 #include <errno.h>
 #include <linux/fcntl.h>
 #include <netinet/in.h>
index 0f4b8ca1fa92929d257e3e93b46d201977bd5a92..ad570f7c2196d1fd0cd470cc966eda8fbab97857 100644 (file)
@@ -26,8 +26,8 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/string.h>
 #include <linux/sock_ioctl.h>
-#include <asm/memory.h>
 #include "../kern_sock.h"
 #include "timer.h"
 #include "ip.h"
@@ -124,6 +124,10 @@ struct proto_ops inet_proto_ops =
 void
 print_sk (volatile struct sock *sk)
 {
+  if (!sk) {
+    PRINTK ("  print_sk(NULL)\n");
+    return;
+  }
   PRINTK ("  wmem_alloc = %d\n", sk->wmem_alloc);
   PRINTK ("  rmem_alloc = %d\n", sk->rmem_alloc);
   PRINTK ("  send_head = %X\n", sk->send_head);
@@ -149,6 +153,10 @@ print_sk (volatile struct sock *sk)
 void
 print_skb(struct sk_buff *skb)
 {
+  if (!skb) {
+    PRINTK ("  print_skb(NULL)\n");
+    return;
+  }
   PRINTK ("  prev = %X, next = %X\n", skb->prev, skb->next);
   PRINTK ("  sk = %X link3 = %X\n", skb->sk, skb->link3);
   PRINTK ("  mem_addr = %X, mem_len = %d\n", skb->mem_addr, skb->mem_len);
@@ -332,27 +340,41 @@ remove_sock(volatile struct sock *sk1)
   volatile struct sock *sk2;
   PRINTK ("remove_sock(sk1=%X)\n",sk1);
 
+  if (!sk1)
+    {
+      printk ("sock.c: remove_sock: sk1 == NULL\n");
+      return;
+    }
+
+  if (!sk1->prot)
+    {
+      printk ("sock.c: remove_sock: sk1->prot == NULL\n");
+      return;
+    }
+
   /* we can't have this changing out from under us. */
   cli();
-  sk2=sk1->prot->sock_array[sk1->num & (SOCK_ARRAY_SIZE -1)];
+  sk2 = sk1->prot->sock_array[sk1->num & (SOCK_ARRAY_SIZE -1)];
   if (sk2 == sk1)
     {
        sk1->prot->sock_array[sk1->num & (SOCK_ARRAY_SIZE -1)] = sk1->next;
        sti();
        return;
     }
-  while (sk2->next != sk1)
+
+  while (sk2 && sk2->next != sk1)
+    sk2 = sk2->next;
+
+  if (sk2)
     {
-      if (sk2 == NULL)
-       {
-         sti();
-         PRINTK ("remove_sock: sock  not found.\n");
-         return;
-       }
-      sk2=sk2->next;
+      sk2->next = sk1->next;
+      sti();
+      return;
     }
-  sk2->next = sk1->next;
   sti();
+
+  if (sk1->num != 0)
+    PRINTK ("remove_sock: sock  not found.\n");
 }
 
 void
@@ -1718,6 +1740,18 @@ volatile struct sock *get_sock (struct proto *prot, unsigned short num,
 
 void release_sock (volatile struct sock *sk)
 {
+  if (!sk)
+    {
+      printk ("sock.c: release_sock sk == NULL\n");
+      return;
+    }
+
+  if (!sk->prot)
+    {
+      printk ("sock.c: release_sock sk->prot == NULL\n");
+      return;
+    }
+
   if (sk->blog) return;
   /* see if we have any packets built up. */
 
index 65c2331b1f6723adff9c3cb7061f7234a2c1ee0b..ef310118db9eee80cbe4164f67b8c7a9676c8c45 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <asm/memory.h>
+#include <linux/string.h>
 #include <linux/socket.h>
 #include <netinet/in.h>
 #include <linux/fcntl.h>
@@ -2101,7 +2101,31 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
   struct tcp_header *th;
   volatile struct sock *sk;
 
+  if (!skb)
+    {
+      printk ("tcp.c: tcp_rcv skb = NULL\n");
+      return (0);
+    }
+#if 0 /* it's ok for protocol to be NULL */
+  if (!protocol)
+    {
+      printk ("tcp.c: tcp_rcv protocol = NULL\n");
+      return (0);
+    }
+
+  if (!opt) /* it's ok for opt to be NULL */
+    {
+      printk ("tcp.c: tcp_rcv opt = NULL\n");
+    }
+#endif
+  if (!dev)
+    {
+      printk ("tcp.c: tcp_rcv dev = NULL\n");
+      return (0);
+    }
+
   th = skb->h.th;
+
   /* find the socket. */
   sk=get_sock(&tcp_prot, net16(th->dest), saddr, th->source, daddr);
   PRINTK("<<\n");
@@ -2168,6 +2192,20 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         }
        sk->inuse = 1;
        sti();
+     }
+  else
+    {
+      if (!sk)
+       {
+         printk ("tcp.c: tcp_rcv bug sk=NULL redo = 1\n");
+         return (0);
+       }
+    }
+
+  if (!sk->prot)
+    {
+      printk ("tcp.c: tcp_rcv sk->prot = NULL \n");
+      return (0);
     }
 
   /* charge the memory to the socket. */
@@ -2214,6 +2252,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
           release_sock(sk);
           return (0);
        }
+
       if (th->rst)
        {
          sk->err = ECONNRESET;
@@ -2226,8 +2265,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
          release_sock(sk);
          return (0);
        }
-
-      if (opt->security != 0 || opt->compartment != 0 || th->syn)
+      if (opt && (opt->security != 0 || opt->compartment != 0 || th->syn))
        {
           sk->err = ECONNRESET;
           sk->state = TCP_CLOSE;
index 0dcecbacb136340174359441eb27f7248a17a6b9..99fc5d73c630c3f8d47e42ad6051f726a1454507 100644 (file)
@@ -567,13 +567,15 @@ udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        sk = get_sock (prot, net16(uh->dest), saddr, uh->source, daddr);
 
        /* if we don't know about the socket, forget about it. */
-       if (sk == NULL &&
-           (daddr & 0xff000000 != 0) && (daddr & 0xff000000 != 0xff000000))
+       if (sk == NULL)
          {
-            icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
-            skb->sk = NULL;
-            free_skb (skb, 0);
-            return (0);
+           if ((daddr & 0xff000000 != 0) && (daddr & 0xff000000 != 0xff000000))
+             {
+               icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
+             }
+           skb->sk = NULL;
+           free_skb (skb, 0);
+           return (0);
          }
 
 
index 58b820881334b5abb47e0078f264bafb236b5bcf..6e1617d32b806b5a8d500acd410e05e66944d924 100644 (file)
 #include <linux/tty.h>
 #include <linux/types.h>
 #include <linux/ptrace.h>
+#include <linux/string.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
-#include <asm/memory.h>
 #include <errno.h>
 #include <linux/fcntl.h>
 #include <netinet/in.h>