]> git.neil.brown.name Git - history.git/commitdiff
Linux-0.11 (December 8, 1991) 0.11
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:08:59 +0000 (15:08 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:08:59 +0000 (15:08 -0500)
This was created from a re-packaged 0.11 tree.

Linux-0.11 has a few rather major improvements, but perhaps most
notably, is the first kernel where some other people start making
real contributions.

 - I fixed the buffer cache code, making it a lot more stable

 - demand-loading from disk. My comment proudly states:

        Once more I can proudly say that linux stood up to being changed: it
        was less than 2 hours work to get demand-loading completely implemented.

   This is a major milestone, since it makes the kernel much more
   powerful than Minix was at the time.  I also share clean pages.

 - we still don't have an /sbin/init, but we now load /etc/rc at bootup,
   and the kernel will loop, spawning shells forever. That makes it easier
   to test things.

 - scaffolding for math emulation introduced.

 - Ted Ts'o shows up as a coder. Ted implements:
        o "#!" escape handling for executables
        o fixes for some file permission handling
        o "sticky" directory bit
        o first "malloc()/free()" implementation.
          (this one is horrible: the free needs the size for good
           performance, which will result in years of "free_s()" pains)
        o adds BSD-style setreuid/gid() handling
        o allows us to specify root device at image build time
        o cleanups of some of the uglier direct %fs-register accesses

 - Galen Hunt shows up as a coder: he's added code to handle different
   video card detection (whereas my original one just handled VGA, we
   now handle CGA, MGA, EGA and VGA)

 - The console can beep now: John T Kohl (who also does the tty KILL
   char handling)

 - we also now have German (Wolfgang Thiel) and French (Marc Corsini)
   keyboard maps.  World Domination!

Btw, if you wonder what the "Urgel" comments are - I was still fairly
Swedish-speaking, and "Urgel" is what I would these days write as "Ugh".

It's a sign of trouble or ugly code.  The floppy driver in particular is
clearly not something I'm very proud of ;).

82 files changed:
Makefile
RCS/Makefile,v [deleted file]
boot/bootsect.s
boot/bootsect.sg [deleted file]
boot/gas-convert [deleted file]
boot/head.s
boot/setup.s
boot/setup.sg [deleted file]
fs/Makefile
fs/RCS/buffer.c,v [deleted file]
fs/RCS/exec.c,v [deleted file]
fs/RCS/namei.c,v [deleted file]
fs/RCS/open.c,v [deleted file]
fs/bitmap.c
fs/buffer.c
fs/char_dev.c
fs/exec.c
fs/exec.c.orig [deleted file]
fs/exec.c~ [deleted file]
fs/inode.c
fs/ioctl.c
fs/namei.c
fs/namei.c~ [deleted file]
fs/open.c~ [deleted file]
fs/read_write.c
fs/super.c
fs/tty_ioctl.c [deleted file]
include/RCS/ctype.h,v [deleted file]
include/asm/RCS/segment.h,v [deleted file]
include/asm/segment.h
include/ctype.h
include/ctype.h~ [deleted file]
include/linux/RCS/kernel.h,v [deleted file]
include/linux/config.h
include/linux/fs.h
include/linux/kernel.h
include/linux/kernel.h.orig [deleted file]
include/linux/kernel.h~ [deleted file]
include/linux/sched.h
include/linux/sys.h
include/termios.h
include/unistd.h
init/main.c
kernel/Makefile
kernel/RCS/exit.c,v [deleted file]
kernel/RCS/sched.c,v [deleted file]
kernel/RCS/sys.c,v [deleted file]
kernel/asm.s
kernel/blk_drv/Makefile
kernel/blk_drv/blk.h
kernel/blk_drv/floppy.c
kernel/blk_drv/hd.c
kernel/blk_drv/ll_rw_blk.c
kernel/blk_drv/ramdisk.c
kernel/blk_drv/ramdisk.c~ [deleted file]
kernel/chr_drv/Makefile
kernel/chr_drv/RCS/keyboard.S,v [deleted file]
kernel/chr_drv/console.c
kernel/chr_drv/keyboard.S
kernel/chr_drv/keyboard.S.jtkohl [deleted file]
kernel/chr_drv/keyboard.S.orig.orig [deleted file]
kernel/chr_drv/keyboard.S~ [deleted file]
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c [new file with mode: 0644]
kernel/exit.c
kernel/exit.c~ [deleted file]
kernel/fork.c
kernel/malloc.c [deleted file]
kernel/math/Makefile [new file with mode: 0644]
kernel/math/math_emulate.c [new file with mode: 0644]
kernel/sched.c
kernel/sched.c~ [deleted file]
kernel/signal.c
kernel/sys.c~ [deleted file]
kernel/system_call.s
lib/Makefile
lib/malloc.c [new file with mode: 0644]
mm/Makefile
mm/memory.c
tools/RCS/build.c,v [deleted file]
tools/build.c
tools/build.c.orig [deleted file]

index 18a02a6addf786a25a27d36827a0939435a5b2cb..9de9f4f1246d812e3b6526f39d12ec81498ea248 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,30 @@
-ROOTDEV= /dev/hd3
+#
+# if you want the ram-disk device, define this to be the
+# size in blocks.
+#
+RAMDISK = #-DRAMDISK=512
 
-AS86   =as -0 -a
-CC86   =cc -0
-LD86   =ld -0
+AS86   =as86 -0 -a
+LD86   =ld86 -0
 
 AS     =gas
 LD     =gld
 LDFLAGS        =-s -x -M
-CC     =gcc
-CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs
+CC     =gcc $(RAMDISK)
+CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
+-fcombine-regs -mstring-insns
 CPP    =cpp -nostdinc -Iinclude
 
+#
+# ROOT_DEV specifies the default root-device when making the image.
+# This can be either FLOPPY, /dev/xxxx or empty, in which case the
+# default of /dev/hd6 is used by 'build'.
+#
+ROOT_DEV=/dev/hd6
+
 ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
 DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
+MATH   =kernel/math/math.a
 LIBS   =lib/lib.a
 
 .c.s:
@@ -27,24 +39,30 @@ LIBS        =lib/lib.a
 all:   Image
 
 Image: boot/bootsect boot/setup tools/system tools/build
-       tools/build boot/bootsect boot/setup tools/system $(ROOTDEV) > Image
+       tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
        sync
 
+disk: Image
+       dd bs=8192 if=Image of=/dev/PS0
+
 tools/build: tools/build.c
        $(CC) $(CFLAGS) \
        -o tools/build tools/build.c
-       chmem +65000 tools/build
 
 boot/head.o: boot/head.s
 
 tools/system:  boot/head.o init/main.o \
-               $(ARCHIVES) $(DRIVERS) $(LIBS)
+               $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)
        $(LD) $(LDFLAGS) boot/head.o init/main.o \
        $(ARCHIVES) \
        $(DRIVERS) \
+       $(MATH) \
        $(LIBS) \
        -o tools/system > System.map
 
+kernel/math/math.a:
+       (cd kernel/math; make)
+
 kernel/blk_drv/blk_drv.a:
        (cd kernel/blk_drv; make)
 
@@ -63,30 +81,29 @@ fs/fs.o:
 lib/lib.a:
        (cd lib; make)
 
-#boot/setup: boot/setup.s
-#      $(AS86) -o boot/setup.o boot/setup.s
-#      $(LD86) -s -o boot/setup boot/setup.o
+boot/setup: boot/setup.s
+       $(AS86) -o boot/setup.o boot/setup.s
+       $(LD86) -s -o boot/setup boot/setup.o
 
-#boot/bootsect:        tmp.s
-#      $(AS86) -o boot/bootsect.o tmp.s
-#      rm -f tmp.s
-#      $(LD86) -s -o boot/bootsect boot/bootsect.o
+boot/bootsect: boot/bootsect.s
+       $(AS86) -o boot/bootsect.o boot/bootsect.s
+       $(LD86) -s -o boot/bootsect boot/bootsect.o
 
-#tmp.s:        boot/bootsect.s tools/system
-#      (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
-#              | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
-#      cat boot/bootsect.s >> tmp.s
+tmp.s: boot/bootsect.s tools/system
+       (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
+               | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
+       cat boot/bootsect.s >> tmp.s
 
 clean:
-       rm -f Image System.map tmp_make core
-       rm -f init/*.o boot/*.o tools/system tools/build
+       rm -f Image System.map tmp_make core boot/bootsect boot/setup
+       rm -f init/*.o tools/system tools/build boot/*.o
        (cd mm;make clean)
        (cd fs;make clean)
        (cd kernel;make clean)
        (cd lib;make clean)
 
 backup: clean
-       (cd .. ; tar cf - linux | compress16 - > backup.Z)
+       (cd .. ; tar cf - linux | compress - > backup.Z)
        sync
 
 dep:
diff --git a/RCS/Makefile,v b/RCS/Makefile,v
deleted file mode 100644 (file)
index 7b5ab5b..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @# @;
-
-
-1.2
-date     91.11.11.15.02.48;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.11.14.43.04;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@Top level makefile for the Linux kernel
-@
-
-
-1.2
-log
-@Comment out code to build and clean out 16 bit binaries.
-
-Modify rule to specify the appropriate root device to the build program
-@
-text
-@ROOTDEV= /dev/hd3
-
-AS86   =as -0 -a
-CC86   =cc -0
-LD86   =ld -0
-
-AS     =gas
-LD     =gld
-LDFLAGS        =-s -x -M
-CC     =gcc
-CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs
-CPP    =cpp -nostdinc -Iinclude
-
-ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
-DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
-LIBS   =lib/lib.a
-
-.c.s:
-       $(CC) $(CFLAGS) \
-       -nostdinc -Iinclude -S -o $*.s $<
-.s.o:
-       $(AS) -c -o $*.o $<
-.c.o:
-       $(CC) $(CFLAGS) \
-       -nostdinc -Iinclude -c -o $*.o $<
-
-all:   Image
-
-Image: boot/bootsect boot/setup tools/system tools/build
-       tools/build boot/bootsect boot/setup tools/system $(ROOTDEV) > Image
-       sync
-
-tools/build: tools/build.c
-       $(CC) $(CFLAGS) \
-       -o tools/build tools/build.c
-       chmem +65000 tools/build
-
-boot/head.o: boot/head.s
-
-tools/system:  boot/head.o init/main.o \
-               $(ARCHIVES) $(DRIVERS) $(LIBS)
-       $(LD) $(LDFLAGS) boot/head.o init/main.o \
-       $(ARCHIVES) \
-       $(DRIVERS) \
-       $(LIBS) \
-       -o tools/system > System.map
-
-kernel/blk_drv/blk_drv.a:
-       (cd kernel/blk_drv; make)
-
-kernel/chr_drv/chr_drv.a:
-       (cd kernel/chr_drv; make)
-
-kernel/kernel.o:
-       (cd kernel; make)
-
-mm/mm.o:
-       (cd mm; make)
-
-fs/fs.o:
-       (cd fs; make)
-
-lib/lib.a:
-       (cd lib; make)
-
-#boot/setup: boot/setup.s
-#      $(AS86) -o boot/setup.o boot/setup.s
-#      $(LD86) -s -o boot/setup boot/setup.o
-
-#boot/bootsect:        tmp.s
-#      $(AS86) -o boot/bootsect.o tmp.s
-#      rm -f tmp.s
-#      $(LD86) -s -o boot/bootsect boot/bootsect.o
-
-#tmp.s:        boot/bootsect.s tools/system
-#      (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
-#              | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
-#      cat boot/bootsect.s >> tmp.s
-
-clean:
-       rm -f Image System.map tmp_make core
-       rm -f init/*.o boot/*.o tools/system tools/build
-       (cd mm;make clean)
-       (cd fs;make clean)
-       (cd kernel;make clean)
-       (cd lib;make clean)
-
-backup: clean
-       (cd .. ; tar cf - linux | compress16 - > backup.Z)
-       sync
-
-dep:
-       sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
-       (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
-       cp tmp_make Makefile
-       (cd fs; make dep)
-       (cd kernel; make dep)
-       (cd mm; make dep)
-
-### Dependencies:
-init/main.o : init/main.c include/unistd.h include/sys/stat.h \
-  include/sys/types.h include/sys/times.h include/sys/utsname.h \
-  include/utime.h include/time.h include/linux/tty.h include/termios.h \
-  include/linux/sched.h include/linux/head.h include/linux/fs.h \
-  include/linux/mm.h include/signal.h include/asm/system.h include/asm/io.h \
-  include/stddef.h include/stdarg.h include/fcntl.h 
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d1 2
-d30 1
-a30 1
-       tools/build boot/bootsect boot/setup tools/system > Image
-d66 3
-a68 3
-boot/setup: boot/setup.s
-       $(AS86) -o boot/setup.o boot/setup.s
-       $(LD86) -s -o boot/setup boot/setup.o
-d70 4
-a73 4
-boot/bootsect: tmp.s
-       $(AS86) -o boot/bootsect.o tmp.s
-       rm -f tmp.s
-       $(LD86) -s -o boot/bootsect boot/bootsect.o
-d75 4
-a78 4
-tmp.s: boot/bootsect.s tools/system
-       (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
-               | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
-       cat boot/bootsect.s >> tmp.s
-d81 2
-a82 2
-       rm -f Image System.map tmp_make boot/bootsect core
-       rm -f boot/setup init/*.o boot/*.o tools/system tools/build
-@
index 77fbb04cc513fe045d3781c0444d004d694d2254..711f103f04e0c70bf3a1bc4731d0318198954ca3 100644 (file)
@@ -1,20 +1,26 @@
-|
-|      bootsect.s              (C) 1991 Linus Torvalds
-|
-| bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
-| iself out of the way to address 0x90000, and jumps there.
-|
-| It then loads 'setup' directly after itself (0x90200), and the system
-| at 0x10000, using BIOS interrupts. 
-|
-| NOTE! currently system is at most 8*65536 bytes long. This should be no
-| problem, even in the future. I want to keep it simple. This 512 kB
-| kernel size should be enough, especially as this doesn't contain the
-| buffer cache as in minix
-|
-| The loader has been made as simple as possible, and continuos
-| read errors will result in a unbreakable loop. Reboot by hand. It
-| loads pretty fast by getting whole sectors at a time whenever possible.
+!
+! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
+! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
+! versions of linux
+!
+SYSSIZE = 0x3000
+!
+!      bootsect.s              (C) 1991 Linus Torvalds
+!
+! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
+! iself out of the way to address 0x90000, and jumps there.
+!
+! It then loads 'setup' directly after itself (0x90200), and the system
+! at 0x10000, using BIOS interrupts. 
+!
+! NOTE! currently system is at most 8*65536 bytes long. This should be no
+! problem, even in the future. I want to keep it simple. This 512 kB
+! kernel size should be enough, especially as this doesn't contain the
+! buffer cache as in minix
+!
+! The loader has been made as simple as possible, and continuos
+! read errors will result in a unbreakable loop. Reboot by hand. It
+! loads pretty fast by getting whole sectors at a time whenever possible.
 
 .globl begtext, begdata, begbss, endtext, enddata, endbss
 .text
@@ -25,16 +31,16 @@ begdata:
 begbss:
 .text
 
-SETUPLEN = 4                           | nr of setup-sectors
-BOOTSEG  = 0x07c0                      | original address of boot-sector
-INITSEG  = 0x9000                      | we move boot here - out of the way
-SETUPSEG = 0x9020                      | setup starts here
-SYSSEG   = 0x1000                      | system loaded at 0x10000 (65536).
-ENDSEG   = SYSSEG + SYSSIZE            | where to stop loading
+SETUPLEN = 4                           ! nr of setup-sectors
+BOOTSEG  = 0x07c0                      ! original address of boot-sector
+INITSEG  = 0x9000                      ! we move boot here - out of the way
+SETUPSEG = 0x9020                      ! setup starts here
+SYSSEG   = 0x1000                      ! system loaded at 0x10000 (65536).
+ENDSEG   = SYSSEG + SYSSIZE            ! where to stop loading
 
-| ROOT_DEV:    0x000 - same type of floppy as boot.
-|              0x301 - first partition on first drive etc
-ROOT_DEV = 0 | 0x306
+! ROOT_DEV:    0x000 - same type of floppy as boot.
+!              0x301 - first partition on first drive etc
+ROOT_DEV = 0x306
 
 entry start
 start:
@@ -51,31 +57,31 @@ start:
 go:    mov     ax,cs
        mov     ds,ax
        mov     es,ax
-| put stack at 0x9ff00.
+! put stack at 0x9ff00.
        mov     ss,ax
-       mov     sp,#0xFF00              | arbitrary value >>512
+       mov     sp,#0xFF00              ! arbitrary value >>512
 
-| load the setup-sectors directly after the bootblock.
-| Note that 'es' is already set up.
+! load the setup-sectors directly after the bootblock.
+! Note that 'es' is already set up.
 
 load_setup:
-       mov     dx,#0x0000              | drive 0, head 0
-       mov     cx,#0x0002              | sector 2, track 0
-       mov     bx,#0x0200              | address = 512, in INITSEG
-       mov     ax,#0x0200+SETUPLEN     | service 2, nr of sectors
-       int     0x13                    | read it
-       jnc     ok_load_setup           | ok - continue
+       mov     dx,#0x0000              ! drive 0, head 0
+       mov     cx,#0x0002              ! sector 2, track 0
+       mov     bx,#0x0200              ! address = 512, in INITSEG
+       mov     ax,#0x0200+SETUPLEN     ! service 2, nr of sectors
+       int     0x13                    ! read it
+       jnc     ok_load_setup           ! ok - continue
        mov     dx,#0x0000
-       mov     ax,#0x0000              | reset the diskette
+       mov     ax,#0x0000              ! reset the diskette
        int     0x13
        j       load_setup
 
 ok_load_setup:
 
-| Get disk drive parameters, specifically nr of sectors/track
+! Get disk drive parameters, specifically nr of sectors/track
 
        mov     dl,#0x00
-       mov     ax,#0x0800              | AH=8 is get drive parameters
+       mov     ax,#0x0800              ! AH=8 is get drive parameters
        int     0x13
        mov     ch,#0x00
        seg cs
@@ -83,30 +89,30 @@ ok_load_setup:
        mov     ax,#INITSEG
        mov     es,ax
 
-| Print some inane message
+! Print some inane message
 
-       mov     ah,#0x03                | read cursor pos
+       mov     ah,#0x03                ! read cursor pos
        xor     bh,bh
        int     0x10
        
        mov     cx,#24
-       mov     bx,#0x0007              | page 0, attribute 7 (normal)
+       mov     bx,#0x0007              ! page 0, attribute 7 (normal)
        mov     bp,#msg1
-       mov     ax,#0x1301              | write string, move cursor
+       mov     ax,#0x1301              ! write string, move cursor
        int     0x10
 
-| ok, we've written the message, now
-| we want to load the system (at 0x10000)
+! ok, we've written the message, now
+! we want to load the system (at 0x10000)
 
        mov     ax,#SYSSEG
-       mov     es,ax           | segment of 0x010000
+       mov     es,ax           ! segment of 0x010000
        call    read_it
        call    kill_motor
 
-| After that we check which root-device to use. If the device is
-| defined (!= 0), nothing is done and the given device is used.
-| Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
-| on the number of sectors that the BIOS reports currently.
+! After that we check which root-device to use. If the device is
+! defined (!= 0), nothing is done and the given device is used.
+! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
+! on the number of sectors that the BIOS reports currently.
 
        seg cs
        mov     ax,root_dev
@@ -114,10 +120,10 @@ ok_load_setup:
        jne     root_defined
        seg cs
        mov     bx,sectors
-       mov     ax,#0x0208              | /dev/ps0 - 1.2Mb
+       mov     ax,#0x0208              ! /dev/ps0 - 1.2Mb
        cmp     bx,#15
        je      root_defined
-       mov     ax,#0x021c              | /dev/PS0 - 1.44Mb
+       mov     ax,#0x021c              ! /dev/PS0 - 1.44Mb
        cmp     bx,#18
        je      root_defined
 undef_root:
@@ -126,30 +132,30 @@ root_defined:
        seg cs
        mov     root_dev,ax
 
-| after that (everyting loaded), we jump to
-| the setup-routine loaded directly after
-| the bootblock:
+! after that (everyting loaded), we jump to
+! the setup-routine loaded directly after
+! the bootblock:
 
        jmpi    0,SETUPSEG
 
-| This routine loads the system at address 0x10000, making sure
-| no 64kB boundaries are crossed. We try to load it as fast as
-| possible, loading whole tracks whenever we can.
-|
-| in:  es - starting address segment (normally 0x1000)
-|
-sread: .word 1+SETUPLEN        | sectors read of current track
-head:  .word 0                 | current head
-track: .word 0                 | current track
+! This routine loads the system at address 0x10000, making sure
+! no 64kB boundaries are crossed. We try to load it as fast as
+! possible, loading whole tracks whenever we can.
+!
+! in:  es - starting address segment (normally 0x1000)
+!
+sread: .word 1+SETUPLEN        ! sectors read of current track
+head:  .word 0                 ! current head
+track: .word 0                 ! current track
 
 read_it:
        mov ax,es
        test ax,#0x0fff
-die:   jne die                 | es must be at 64kB boundary
-       xor bx,bx               | bx is starting address within segment
+die:   jne die                 ! es must be at 64kB boundary
+       xor bx,bx               ! bx is starting address within segment
 rp_read:
        mov ax,es
-       cmp ax,#ENDSEG          | have we loaded all yet?
+       cmp ax,#ENDSEG          ! have we loaded all yet?
        jb ok1_read
        ret
 ok1_read:
diff --git a/boot/bootsect.sg b/boot/bootsect.sg
deleted file mode 100644 (file)
index 7073fd1..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/* 
- *
- *     bootsect.s              (C) 1991 Linus Torvalds
- *
- * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
- * iself out of the way to address 0x90000, and jumps there.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts. 
- *
- * NOTE! currently system is at most 8*65536 bytes long. This should be no
- * problem, even in the future. I want to keep it simple. This 512 kB
- * kernel size should be enough, especially as this doesn't contain the
- * buffer cache as in minix
- *
- * The loader has been made as simple as possible, and continuos
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole sectors at a time whenever possible.
- */
-
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-SETUPLEN = 4                           # nr of setup-sectors
-BOOTSEG  = 0x07c0                      # original address of boot-sector
-INITSEG  = 0x9000                      # we move boot here - out of the way
-SETUPSEG = 0x9020                      # setup starts here
-SYSSEG   = 0x1000                      # system loaded at 0x10000 (65536).
-ENDSEG   = SYSSEG + SYSSIZE            # where to stop loading
-
-/* 
- * ROOT_DEV:   0x000 - same type of floppy as boot.
- *             0x301 - first partition on first drive etc
- */
-ROOT_DEV = 0 # 0x306
-
-entry start
-start:
-       mov     $BOOTSEG,%ax
-       mov     %ax,%ds
-       mov     $INITSEG,%ax
-       mov     %ax,%es
-       mov     $256,%cx
-       sub     %si,%si
-       sub     %di,%di
-       rep
-       movw
-       jmpi    go,INITSEG
-go:    mov     %cs,%ax
-       mov     %ax,%ds
-       mov     %ax,%es
-/* 
- * put stack at 0x9ff00.
- */
-       mov     %ax,%ss
-       mov     $0xFF00,%sp             # arbitrary value >>512
-
-/* 
- * load the setup-sectors directly after the bootblock.
- * Note that 'es' is already set up.
- */
-
-load_setup:
-       mov     $0x0000,%dx             # drive 0, head 0
-       mov     $0x0002,%cx             # sector 2, track 0
-       mov     $0x0200,%bx             # address = 512, in INITSEG
-       mov     $0x0200,%ax+SETUPLEN    # service 2, nr of sectors
-       int     0x13                    # read it
-       jnc     ok_load_setup           # ok - continue
-       mov     $0x0000,%dx
-       mov     $0x0000,%ax             # reset the diskette
-       int     0x13
-       j       load_setup
-
-ok_load_setup:
-
-/* 
- * Get disk drive parameters, specifically nr of sectors/track
- */
-
-       mov     $0x00,%dl
-       mov     $0x0800,%ax             # AH=8 is get drive parameters
-       int     0x13
-       mov     $0x00,%ch
-       seg %cs
-       mov     %cx,sectors
-       mov     $INITSEG,%ax
-       mov     %ax,%es
-
-/* 
- * Print some inane message
- */
-
-       mov     $0x03,%ah               # read cursor pos
-       xor     %bh,%bh
-       int     0x10
-       
-       mov     $24,%cx
-       mov     $0x0007,%bx             # page 0, attribute 7 (normal)
-       mov     $msg1,%bp
-       mov     $0x1301,%ax             # write string, move cursor
-       int     0x10
-
-/* 
- * ok, we've written the message, now
- * we want to load the system (at 0x10000)
- */
-
-       mov     $SYSSEG,%ax
-       mov     %ax,%es         # segment of 0x010000
-       call    read_it
-       call    kill_motor
-
-/* 
- * After that we check which root-device to use. If the device is
- * defined (!= 0), nothing is done and the given device is used.
- * Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
- * on the number of sectors that the BIOS reports currently.
- */
-
-       seg %cs
-       mov     root,%ax_dev
-       cmp     %ax,$0
-       jne     root_defined
-       seg %cs
-       mov     sectors,%bx
-       mov     $0x0208,%ax             # /dev/ps0 - 1.2Mb
-       cmp     %bx,$15
-       je      root_defined
-       mov     $0x021c,%ax             # /dev/PS0 - 1.44Mb
-       cmp     %bx,$18
-       je      root_defined
-undef_root:
-       jmp undef_root
-root_defined:
-       seg %cs
-       mov     root_%ax,dev
-
-/* 
- * after that (everyting loaded), we jump to
- * the setup-routine loaded directly after
- * the bootblock:
- */
-
-       jmpi    0,SETUPSEG
-
-/* 
- * This routine loads the system at address 0x10000, making sure
- * no 64kB boundaries are crossed. We try to load it as fast as
- * possible, loading whole tracks whenever we can.
- *
- * in: es - starting address segment (normally 0x1000)
- *
- */
-sread: .word 1+SETUPLEN        # sectors read of current track
-head:  .word 0                 # current head
-track: .word 0                 # current track
-
-read_it:
-       mov %es,%ax
-       test %ax,$0x0fff
-die:   jne die                 # %es must be at 64kB boundary
-       xor %bx,%bx             # %bx is starting address within segment
-rp_read:
-       mov %es,%ax
-       cmp %ax,$ENDSEG         # have we loaded all yet?
-       jb ok1_read
-       ret
-ok1_read:
-       seg %cs
-       mov sectors,%ax
-       sub sread,%ax
-       mov %ax,%cx
-       shl $9,%cx
-       add %bx,%cx
-       jnc ok2_read
-       je ok2_read
-       xor %ax,%ax
-       sub %bx,%ax
-       shr $9,%ax
-ok2_read:
-       call read_track
-       mov %ax,%cx
-       add sread,%ax
-       seg %cs
-       cmp %ax,sectors
-       jne ok3_read
-       mov $1,%ax
-       sub head,%ax
-       jne ok4_read
-       inc track
-ok4_read:
-       mov %ax,head
-       xor %ax,%ax
-ok3_read:
-       mov %ax,sread
-       shl $9,%cx
-       add %cx,%bx
-       jnc rp_read
-       mov %es,%ax
-       add $0x1000,%ax
-       mov %ax,%es
-       xor %bx,%bx
-       jmp rp_read
-
-read_track:
-       push %ax
-       push %bx
-       push %cx
-       push %dx
-       mov track,%dx
-       mov sread,%cx
-       inc %cx
-       mov %dl,%ch
-       mov head,%dx
-       mov %dl,%dh
-       mov $0,%dl
-       and $0x0100,%dx
-       mov $2,%ah
-       int 0x13
-       jc bad_rt
-       pop %dx
-       pop %cx
-       pop %bx
-       pop %ax
-       ret
-bad_rt:        mov %ax,$0
-       mov $0,%dx
-       int 0x13
-       pop %dx
-       pop %cx
-       pop %bx
-       pop %ax
-       jmp read_track
-
-/*
- * This procedure turns off the floppy drive motor, so
- * that we enter the kernel in a known state, and
- * don't have to worry about it later.
- */
-kill_motor:
-       push %dx
-       mov $0x3f2,%dx
-       mov $0,%al
-       outb
-       pop %dx
-       ret
-
-sectors:
-       .word 0
-
-msg1:
-       .byte 13,10
-       .ascii "Loading system ..."
-       .byte 13,10,13,10
-
-.org 508
-root_dev:
-       .word ROOT_DEV
-boot_flag:
-       .word 0xAA55
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/boot/gas-convert b/boot/gas-convert
deleted file mode 100644 (file)
index 66c2e67..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/afs/net/tools/@sys/perl
-#
-#
-
-$in_block_comment = 0;
-
-while (<>) {
-       if (/^\|/) {
-               if (! $in_block_comment) {
-                       print "/* \n";
-                       $in_block_comment = 1;
-               }
-               s/\|/ */;
-               print;
-               next;
-       } else {
-               if ($in_block_comment) {
-                       print " */\n";
-                       $in_block_comment = 0;
-               }
-       }
-                       
-       s/#/$/;         # Convert immediate references
-       s/\|/#/;        # Convert in-line comments
-
-       s/(\b|,)([abcd][xhl])(\b|,|$)/\1%\2\3/g;
-       s/(\b|,)([cdsefg]s)(\b|,|$)/\1%\2\3/g;
-       s/(\b|,)([sd]i)(\b|,|$)/\1%\2\3/g;
-       s/(\b|,)([sb]p)(\b|,|$)/\1%\2\3/g;
-       s/(\b|,)(e[abcd]x)(\b|,|$)/\1%\2\3/g;
-
-       if (/^(([a-zA-Z]+:[ \t]+)|[ \t]+)([a-zA-Z]+)/) {
-               $op = $3;
-               if (($op eq "mov") || ($op eq "add") || ($op eq "sub") ||
-                   ($op eq "xor") || ($op eq "and") || ($op eq "shr") ||
-                   ($op eq "shl") || ($op eq "in")  || ($op eq "out")) {
-                       #
-                       # We need to swap arguments...
-                       #
-                       s/([0-9a-zA-Z%\$]+)(,)([0-9a-zA-Z%\$]+)/\3\2\1/;
-               }
-       }
-       
-       print;
-}
-
-
index 2c4970ab19f5484bb78eeea4ebcc1ccb8b9137e6..de56a74aa24f1f5623435102aea2f8baa087bf1a 100644 (file)
@@ -41,15 +41,29 @@ startup_32:
  * int 16 for math errors.
  */
        movl %cr0,%eax          # check math chip
-       andl $0x80000011,%eax   # Save PG,ET,PE
+       andl $0x80000011,%eax   # Save PG,PE,ET
 /* "orl $0x10020,%eax" here for 486 might be good */
        orl $2,%eax             # set MP
-       testl $0x10,%eax
-       jne 1f                  # ET is set - 387 is present
-       xorl $6,%eax            # else reset MP and set EM
-1:     movl %eax,%cr0
+       movl %eax,%cr0
+       call check_x87
        jmp after_page_tables
 
+/*
+ * We depend on ET to be correct. This checks for 287/387.
+ */
+check_x87:
+       fninit
+       fstsw %ax
+       cmpb $0,%al
+       je 1f                   /* no coprocessor: have to set bits */
+       movl %cr0,%eax
+       xorl $6,%eax            /* reset MP, set EM */
+       movl %eax,%cr0
+       ret
+.align 2
+1:     .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
+       ret
+
 /*
  *  setup_idt
  *
index 5034a657cc913c5d2f791e26110bb9588e03c1e0..2329d00e6087fef506c6cd540c4eec1fa7e11a1a 100644 (file)
@@ -1,22 +1,22 @@
-|
-|      setup.s         (C) 1991 Linus Torvalds
-|
-| setup.s is responsible for getting the system data from the BIOS,
-| and putting them into the appropriate places in system memory.
-| both setup.s and system has been loaded by the bootblock.
-|
-| This code asks the bios for memory/disk/other parameters, and
-| puts them in a "safe" place: 0x90000-0x901FF, ie where the
-| boot-block used to be. It is then up to the protected mode
-| system to read them from there before the area is overwritten
-| for buffer-blocks.
-|
-
-| NOTE! These had better be the same as in bootsect.s!
-
-INITSEG  = 0x9000      | we move boot here - out of the way
-SYSSEG   = 0x1000      | system loaded at 0x10000 (65536).
-SETUPSEG = 0x9020      | this is the current segment
+!
+!      setup.s         (C) 1991 Linus Torvalds
+!
+! setup.s is responsible for getting the system data from the BIOS,
+! and putting them into the appropriate places in system memory.
+! both setup.s and system has been loaded by the bootblock.
+!
+! This code asks the bios for memory/disk/other parameters, and
+! puts them in a "safe" place: 0x90000-0x901FF, ie where the
+! boot-block used to be. It is then up to the protected mode
+! system to read them from there before the area is overwritten
+! for buffer-blocks.
+!
+
+! NOTE! These had better be the same as in bootsect.s!
+
+INITSEG  = 0x9000      ! we move boot here - out of the way
+SYSSEG   = 0x1000      ! system loaded at 0x10000 (65536).
+SETUPSEG = 0x9020      ! this is the current segment
 
 .globl begtext, begdata, begbss, endtext, enddata, endbss
 .text
@@ -30,23 +30,39 @@ begbss:
 entry start
 start:
 
-| ok, the read went well so we get current cursor position and save it for
-| posterity.
+! ok, the read went well so we get current cursor position and save it for
+! posterity.
 
-       mov     ax,#INITSEG     | this is done in bootsect already, but...
+       mov     ax,#INITSEG     ! this is done in bootsect already, but...
        mov     ds,ax
-       mov     ah,#0x03        | read cursor pos
+       mov     ah,#0x03        ! read cursor pos
        xor     bh,bh
-       int     0x10            | save it in known place, con_init fetches
-       mov     [0],dx          | it from 0x90000.
+       int     0x10            ! save it in known place, con_init fetches
+       mov     [0],dx          ! it from 0x90000.
 
-| Get memory size (extended mem, kB)
+! Get memory size (extended mem, kB)
 
        mov     ah,#0x88
        int     0x15
        mov     [2],ax
 
-| Get hd0 data
+! Get video-card data:
+
+       mov     ah,#0x0f
+       int     0x10
+       mov     [4],bx          ! bh = display page
+       mov     [6],ax          ! al = video mode, ah = window width
+
+! check for EGA/VGA and some config parameters
+
+       mov     ah,#0x12
+       mov     bl,#0x10
+       int     0x10
+       mov     [8],ax
+       mov     [10],bx
+       mov     [12],cx
+
+! Get hd0 data
 
        mov     ax,#0x0000
        mov     ds,ax
@@ -58,7 +74,7 @@ start:
        rep
        movsb
 
-| Get hd1 data
+! Get hd1 data
 
        mov     ax,#0x0000
        mov     ds,ax
@@ -70,7 +86,7 @@ start:
        rep
        movsb
 
-| Check that there IS a hd1 :-)
+! Check that there IS a hd1 :-)
 
        mov     ax,#0x01500
        mov     dl,#0x81
@@ -88,20 +104,20 @@ no_disk1:
        stosb
 is_disk1:
 
-| now we want to move to protected mode ...
+! now we want to move to protected mode ...
 
-       cli                     | no interrupts allowed !
+       cli                     ! no interrupts allowed !
 
-| first we move the system to it's rightful place
+! first we move the system to it's rightful place
 
        mov     ax,#0x0000
-       cld                     | 'direction'=0, movs moves forward
+       cld                     ! 'direction'=0, movs moves forward
 do_move:
-       mov     es,ax           | destination segment
+       mov     es,ax           ! destination segment
        add     ax,#0x1000
        cmp     ax,#0x9000
        jz      end_move
-       mov     ds,ax           | source segment
+       mov     ds,ax           ! source segment
        sub     di,di
        sub     si,si
        mov     cx,#0x8000
@@ -109,103 +125,103 @@ do_move:
        movsw
        jmp     do_move
 
-| then we load the segment descriptors
+! then we load the segment descriptors
 
 end_move:
-       mov     ax,#SETUPSEG    | right, forgot this at first. didn't work :-)
+       mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
        mov     ds,ax
-       lidt    idt_48          | load idt with 0,0
-       lgdt    gdt_48          | load gdt with whatever appropriate
+       lidt    idt_48          ! load idt with 0,0
+       lgdt    gdt_48          ! load gdt with whatever appropriate
 
-| that was painless, now we enable A20
+! that was painless, now we enable A20
 
        call    empty_8042
-       mov     al,#0xD1                | command write
+       mov     al,#0xD1                ! command write
        out     #0x64,al
        call    empty_8042
-       mov     al,#0xDF                | A20 on
+       mov     al,#0xDF                ! A20 on
        out     #0x60,al
        call    empty_8042
 
-| well, that went ok, I hope. Now we have to reprogram the interrupts :-(
-| we put them right after the intel-reserved hardware interrupts, at
-| int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
-| messed this up with the original PC, and they haven't been able to
-| rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
-| which is used for the internal hardware interrupts as well. We just
-| have to reprogram the 8259's, and it isn't fun.
-
-       mov     al,#0x11                | initialization sequence
-       out     #0x20,al                | send it to 8259A-1
-       .word   0x00eb,0x00eb           | jmp $+2, jmp $+2
-       out     #0xA0,al                | and to 8259A-2
+! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+! we put them right after the intel-reserved hardware interrupts, at
+! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+! messed this up with the original PC, and they haven't been able to
+! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+! which is used for the internal hardware interrupts as well. We just
+! have to reprogram the 8259's, and it isn't fun.
+
+       mov     al,#0x11                ! initialization sequence
+       out     #0x20,al                ! send it to 8259A-1
+       .word   0x00eb,0x00eb           ! jmp $+2, jmp $+2
+       out     #0xA0,al                ! and to 8259A-2
        .word   0x00eb,0x00eb
-       mov     al,#0x20                | start of hardware int's (0x20)
+       mov     al,#0x20                ! start of hardware int's (0x20)
        out     #0x21,al
        .word   0x00eb,0x00eb
-       mov     al,#0x28                | start of hardware int's 2 (0x28)
+       mov     al,#0x28                ! start of hardware int's 2 (0x28)
        out     #0xA1,al
        .word   0x00eb,0x00eb
-       mov     al,#0x04                | 8259-1 is master
+       mov     al,#0x04                ! 8259-1 is master
        out     #0x21,al
        .word   0x00eb,0x00eb
-       mov     al,#0x02                | 8259-2 is slave
+       mov     al,#0x02                ! 8259-2 is slave
        out     #0xA1,al
        .word   0x00eb,0x00eb
-       mov     al,#0x01                | 8086 mode for both
+       mov     al,#0x01                ! 8086 mode for both
        out     #0x21,al
        .word   0x00eb,0x00eb
        out     #0xA1,al
        .word   0x00eb,0x00eb
-       mov     al,#0xFF                | mask off all interrupts for now
+       mov     al,#0xFF                ! mask off all interrupts for now
        out     #0x21,al
        .word   0x00eb,0x00eb
        out     #0xA1,al
 
-| well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-| need no steenking BIOS anyway (except for the initial loading :-).
-| The BIOS-routine wants lots of unnecessary data, and it's less
-| "interesting" anyway. This is how REAL programmers do it.
-|
-| Well, now's the time to actually move into protected mode. To make
-| things as simple as possible, we do no register set-up or anything,
-| we let the gnu-compiled 32-bit programs do that. We just jump to
-| absolute address 0x00000, in 32-bit protected mode.
-
-       mov     ax,#0x0001      | protected mode (PE) bit
-       lmsw    ax              | This is it!
-       jmpi    0,8             | jmp offset 0 of segment 8 (cs)
-
-| This routine checks that the keyboard command queue is empty
-| No timeout is used - if this hangs there is something wrong with
-| the machine, and we probably couldn't proceed anyway.
+! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
+! need no steenking BIOS anyway (except for the initial loading :-).
+! The BIOS-routine wants lots of unnecessary data, and it's less
+! "interesting" anyway. This is how REAL programmers do it.
+!
+! Well, now's the time to actually move into protected mode. To make
+! things as simple as possible, we do no register set-up or anything,
+! we let the gnu-compiled 32-bit programs do that. We just jump to
+! absolute address 0x00000, in 32-bit protected mode.
+
+       mov     ax,#0x0001      ! protected mode (PE) bit
+       lmsw    ax              ! This is it!
+       jmpi    0,8             ! jmp offset 0 of segment 8 (cs)
+
+! This routine checks that the keyboard command queue is empty
+! No timeout is used - if this hangs there is something wrong with
+! the machine, and we probably couldn't proceed anyway.
 empty_8042:
        .word   0x00eb,0x00eb
-       in      al,#0x64        | 8042 status port
-       test    al,#2           | is input buffer full?
-       jnz     empty_8042      | yes - loop
+       in      al,#0x64        ! 8042 status port
+       test    al,#2           ! is input buffer full?
+       jnz     empty_8042      ! yes - loop
        ret
 
 gdt:
-       .word   0,0,0,0         | dummy
+       .word   0,0,0,0         ! dummy
 
-       .word   0x07FF          | 8Mb - limit=2047 (2048*4096=8Mb)
-       .word   0x0000          | base address=0
-       .word   0x9A00          | code read/exec
-       .word   0x00C0          | granularity=4096, 386
+       .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
+       .word   0x0000          ! base address=0
+       .word   0x9A00          ! code read/exec
+       .word   0x00C0          ! granularity=4096, 386
 
-       .word   0x07FF          | 8Mb - limit=2047 (2048*4096=8Mb)
-       .word   0x0000          | base address=0
-       .word   0x9200          | data read/write
-       .word   0x00C0          | granularity=4096, 386
+       .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
+       .word   0x0000          ! base address=0
+       .word   0x9200          ! data read/write
+       .word   0x00C0          ! granularity=4096, 386
 
 idt_48:
-       .word   0                       | idt limit=0
-       .word   0,0                     | idt base=0L
+       .word   0                       ! idt limit=0
+       .word   0,0                     ! idt base=0L
 
 gdt_48:
-       .word   0x800           | gdt limit=2048, 256 GDT entries
-       .word   512+gdt,0x9     | gdt base = 0X9xxxx
+       .word   0x800           ! gdt limit=2048, 256 GDT entries
+       .word   512+gdt,0x9     ! gdt base = 0X9xxxx
        
 .text
 endtext:
diff --git a/boot/setup.sg b/boot/setup.sg
deleted file mode 100644 (file)
index d585003..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* 
- *
- *     setup.s         (C) 1991 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- */
-
-/* 
- * NOTE! These had better be the same as in bootsect.s!
- */
-
-INITSEG  = 0x9000      # we move boot here - out of the way
-SYSSEG   = 0x1000      # system loaded at 0x10000 (65536).
-SETUPSEG = 0x9020      # this is the current segment
-
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-entry start
-start:
-
-/* 
- * ok, the read went well so we get current cursor position and save it for
- * posterity.
- */
-
-       mov     $INITSEG,%ax    # this is done in bootsect already, but...
-       mov     %ax,%ds
-       mov     $0x03,%ah       # read cursor pos
-       xor     %bh,%bh
-       int     0x10            # save it in known place, con_init fetches
-       mov     [0],%dx         # it from 0x90000.
-
-/* 
- * Get memory size (extended mem, kB)
- */
-
-       mov     $0x88,%ah
-       int     0x15
-       mov     [2],%ax
-
-/* 
- * Get hd0 data
- */
-
-       mov     $0x0000,%ax
-       mov     %ax,%ds
-       lds     %si,[4*0x41]
-       mov     $INITSEG,%ax
-       mov     %ax,%es
-       mov     $0x0080,%di
-       mov     $0x10,%cx
-       rep
-       movsb
-
-/* 
- * Get hd1 data
- */
-
-       mov     $0x0000,%ax
-       mov     %ax,%ds
-       lds     %si,[4*0x46]
-       mov     $INITSEG,%ax
-       mov     %ax,%es
-       mov     $0x0090,%di
-       mov     $0x10,%cx
-       rep
-       movsb
-
-/* 
- * Check that there IS a hd1 :-)
- */
-
-       mov     $0x01500,%ax
-       mov     $0x81,%dl
-       int     0x13
-       jc      no_disk1
-       cmp     %ah,$3
-       je      is_disk1
-no_disk1:
-       mov     $INITSEG,%ax
-       mov     %ax,%es
-       mov     $0x0090,%di
-       mov     $0x10,%cx
-       mov     $0x00,%ax
-       rep
-       stosb
-is_disk1:
-
-/* 
- * now we want to move to protected mode ...
- */
-
-       cli                     # no interrupts allowed !
-
-/* 
- * first we move the system to it's rightful place
- */
-
-       mov     $0x0000,%ax
-       cld                     # 'direction'=0, movs moves forward
-do_move:
-       mov     %ax,%es         # destination segment
-       add     $0x1000,%ax
-       cmp     %ax,$0x9000
-       jz      end_move
-       mov     %ax,%ds         # source segment
-       sub     %di,%di
-       sub     %si,%si
-       mov     $0x8000,%cx
-       rep
-       movsw
-       jmp     do_move
-
-/* 
- * then we load the segment descriptors
- */
-
-end_move:
-       mov     $SETUPSEG,%ax   # right, forgot this at first. didn't work :-)
-       mov     %ax,%ds
-       lidt    idt_48          # load idt with 0,0
-       lgdt    gdt_48          # load gdt with whatever appropriate
-
-/* 
- * that was painless, now we enable A20
- */
-
-       call    empty_8042
-       mov     $0xD1,%al               # command write
-       out     %al,$0x64
-       call    empty_8042
-       mov     $0xDF,%al               # A20 on
-       out     %al,$0x60
-       call    empty_8042
-
-/* 
- * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
- * we put them right after the intel-reserved hardware interrupts, at
- * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
- * messed this up with the original PC, and they haven't been able to
- * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
- * which is used for the internal hardware interrupts as well. We just
- * have to reprogram the 8259's, and it isn't fun.
- */
-
-       mov     $0x11,%al               # initialization sequence
-       out     %al,$0x20               # send it to 8259A-1
-       .word   0x00eb,0x00eb           # jmp $+2, jmp $+2
-       out     %al,$0xA0               # and to 8259A-2
-       .word   0x00eb,0x00eb
-       mov     $0x20,%al               # start of hardware int's (0x20)
-       out     %al,$0x21
-       .word   0x00eb,0x00eb
-       mov     $0x28,%al               # start of hardware int's 2 (0x28)
-       out     %al,$0xA1
-       .word   0x00eb,0x00eb
-       mov     $0x04,%al               # 8259-1 is master
-       out     %al,$0x21
-       .word   0x00eb,0x00eb
-       mov     $0x02,%al               # 8259-2 is slave
-       out     %al,$0xA1
-       .word   0x00eb,0x00eb
-       mov     $0x01,%al               # 8086 mode for both
-       out     %al,$0x21
-       .word   0x00eb,0x00eb
-       out     %al,$0xA1
-       .word   0x00eb,0x00eb
-       mov     $0xFF,%al               # mask off all interrupts for now
-       out     %al,$0x21
-       .word   0x00eb,0x00eb
-       out     %al,$0xA1
-
-/* 
- * well, that certainly wasn't fun :-(. Hopefully it works, and we don't
- * need no steenking BIOS anyway (except for the initial loading :-).
- * The BIOS-routine wants lots of unnecessary data, and it's less
- * "interesting" anyway. This is how REAL programmers do it.
- *
- * Well, now's the time to actually move into protected mode. To make
- * things as simple as possible, we do no register set-up or anything,
- * we let the gnu-compiled 32-bit programs do that. We just jump to
- * absolute address 0x00000, in 32-bit protected mode.
- */
-
-       mov     $0x0001,%ax     # protected mode (PE) bit
-       lmsw    %ax             # This is it!
-       jmpi    0,8             # jmp offset 0 of segment 8 (%cs)
-
-/* 
- * This routine checks that the keyboard command queue is empty
- * No timeout is used - if this hangs there is something wrong with
- * the machine, and we probably couldn't proceed anyway.
- */
-empty_8042:
-       .word   0x00eb,0x00eb
-       in      $0x64,%al       # 8042 status port
-       test    %al,$2          # is input buffer full?
-       jnz     empty_8042      # yes - loop
-       ret
-
-gdt:
-       .word   0,0,0,0         # dummy
-
-       .word   0x07FF          # 8Mb - limit=2047 (2048*4096=8Mb)
-       .word   0x0000          # base address=0
-       .word   0x9A00          # code read/exec
-       .word   0x00C0          # granularity=4096, 386
-
-       .word   0x07FF          # 8Mb - limit=2047 (2048*4096=8Mb)
-       .word   0x0000          # base address=0
-       .word   0x9200          # data read/write
-       .word   0x00C0          # granularity=4096, 386
-
-idt_48:
-       .word   0                       # idt limit=0
-       .word   0,0                     # idt base=0L
-
-gdt_48:
-       .word   0x800           # gdt limit=2048, 256 GDT entries
-       .word   512+gdt,0x9     # gdt base = 0X9xxxx
-       
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
index 989319fe1122cc46de5a4f51d34d89d5ec001750..97a388ee9972f8437f2525a5a2f6a59c797797bb 100644 (file)
@@ -17,7 +17,7 @@ CPP   =gcc -E -nostdinc -I../include
 
 OBJS=  open.o read_write.o inode.o file_table.o buffer.o super.o \
        block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \
-       bitmap.o fcntl.o ioctl.o tty_ioctl.o truncate.o
+       bitmap.o fcntl.o ioctl.o truncate.o
 
 fs.o: $(OBJS)
        $(LD) -r -o fs.o $(OBJS)
@@ -47,10 +47,11 @@ char_dev.o : char_dev.c ../include/errno.h ../include/sys/types.h \
   ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
   ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
   ../include/asm/segment.h ../include/asm/io.h 
-exec.o : exec.c ../include/errno.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/a.out.h ../include/linux/fs.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/mm.h \
-  ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h 
+exec.o : exec.c ../include/errno.h ../include/string.h \
+  ../include/sys/stat.h ../include/sys/types.h ../include/a.out.h \
+  ../include/linux/fs.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
+  ../include/asm/segment.h 
 fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
   ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
   ../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
@@ -97,8 +98,3 @@ super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
 truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \
   ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
   ../include/signal.h ../include/sys/stat.h 
-tty_ioctl.o : tty_ioctl.c ../include/errno.h ../include/termios.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
-  ../include/linux/kernel.h ../include/linux/tty.h ../include/asm/segment.h \
-  ../include/asm/system.h 
diff --git a/fs/RCS/buffer.c,v b/fs/RCS/buffer.c,v
deleted file mode 100644 (file)
index c5916f3..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.11.20.00.10.40;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.12.15.49.42;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Used new version of buffer.c supplied from Linus.
-@
-text
-@/*
- *  linux/fs/buffer.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *  '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).
- */
-
-/*
- * NOTE! There is one discordant note here: checking floppies for
- * disk change. This is where it fits best, I think, as it should
- * invalidate changed floppy-disk-caches.
- */
-
-#include <stdarg.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-extern int end;
-struct buffer_head * start_buffer = (struct buffer_head *) &end;
-struct buffer_head * hash_table[NR_HASH];
-static struct buffer_head * free_list;
-static struct task_struct * buffer_wait = NULL;
-int NR_BUFFERS = 0;
-
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
-       cli();
-       while (bh->b_lock)
-               sleep_on(&bh->b_wait);
-       sti();
-}
-
-int sys_sync(void)
-{
-       int i;
-       struct buffer_head * bh;
-
-       sync_inodes();          /* write out inodes into buffers */
-       bh = start_buffer;
-       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
-               wait_on_buffer(bh);
-               if (bh->b_dirt)
-                       ll_rw_block(WRITE,bh);
-       }
-       return 0;
-}
-
-int sync_dev(int dev)
-{
-       int i;
-       struct buffer_head * bh;
-
-       bh = start_buffer;
-       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
-               if (bh->b_dev != dev)
-                       continue;
-               wait_on_buffer(bh);
-               if (bh->b_dev == dev && bh->b_dirt)
-                       ll_rw_block(WRITE,bh);
-       }
-       sync_inodes();
-       bh = start_buffer;
-       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
-               if (bh->b_dev != dev)
-                       continue;
-               wait_on_buffer(bh);
-               if (bh->b_dev == dev && bh->b_dirt)
-                       ll_rw_block(WRITE,bh);
-       }
-       return 0;
-}
-
-/*
- * This routine checks whether a floppy has been changed, and
- * invalidates all buffer-cache-entries in that case. This
- * is a relatively slow routine, so we have to try to minimize using
- * it. Thus it is called only upon a 'mount' or 'open'. This
- * is the best way of combining speed and utility, I think.
- * People changing diskettes in the middle of an operation deserve
- * to loose :-)
- *
- * NOTE! Although currently this is only for floppies, the idea is
- * that any additional removable block-device will use this routine,
- * and that mount/open needn't know that floppies/whatever are
- * special.
- */
-void check_disk_change(int dev)
-{
-       int i;
-       struct buffer_head * bh;
-
-       if (MAJOR(dev) != 2)
-               return;
-       dev=MINOR(dev) & 0x03;  /* which floppy is it? */
-       if (!floppy_change(dev))
-               return;
-       dev |= 0x200;
-       for (i=0 ; i<NR_SUPER ; i++)
-               if ((super_block[i].s_dev & 0xff03)==dev)
-                       put_super(super_block[i].s_dev);
-       bh = start_buffer;
-       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
-               if ((bh->b_dev & 0xff03) != dev)
-                       continue;
-               wait_on_buffer(bh);
-               if ((bh->b_dev & 0xff03) == dev)
-                       bh->b_uptodate = bh->b_dirt = 0;
-       }
-}
-
-#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
-#define hash(dev,block) hash_table[_hashfn(dev,block)]
-
-static inline void remove_from_queues(struct buffer_head * bh)
-{
-/* remove from hash-queue */
-       if (bh->b_next)
-               bh->b_next->b_prev = bh->b_prev;
-       if (bh->b_prev)
-               bh->b_prev->b_next = bh->b_next;
-       if (hash(bh->b_dev,bh->b_blocknr) == bh)
-               hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
-/* remove from free list */
-       if (!(bh->b_prev_free) || !(bh->b_next_free))
-               panic("Free block list corrupted");
-       bh->b_prev_free->b_next_free = bh->b_next_free;
-       bh->b_next_free->b_prev_free = bh->b_prev_free;
-       if (free_list == bh)
-               free_list = bh->b_next_free;
-}
-
-static inline void insert_into_queues(struct buffer_head * bh)
-{
-/* put at end of free list */
-       bh->b_next_free = free_list;
-       bh->b_prev_free = free_list->b_prev_free;
-       free_list->b_prev_free->b_next_free = bh;
-       free_list->b_prev_free = bh;
-/* put the buffer in new hash-queue if it has a device */
-       bh->b_prev = NULL;
-       bh->b_next = NULL;
-       if (!bh->b_dev)
-               return;
-       bh->b_next = hash(bh->b_dev,bh->b_blocknr);
-       hash(bh->b_dev,bh->b_blocknr) = bh;
-       bh->b_next->b_prev = bh;
-}
-
-static struct buffer_head * find_buffer(int dev, int block)
-{              
-       struct buffer_head * tmp;
-
-       for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
-               if (tmp->b_dev==dev && tmp->b_blocknr==block)
-                       return tmp;
-       return NULL;
-}
-
-/*
- * Why like this, I hear you say... The reason is race-conditions.
- * As we don't lock buffers (unless we are readint them, that is),
- * something might happen to it while we sleep (ie a read-error
- * 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)
-{
-       struct buffer_head * bh;
-
-       for (;;) {
-               if (!(bh=find_buffer(dev,block)))
-                       return NULL;
-               bh->b_count++;
-               wait_on_buffer(bh);
-               if (bh->b_dev == dev && bh->b_blocknr == block)
-                       return bh;
-               bh->b_count--;
-       }
-}
-
-/*
- * Ok, this is getblk, and it isn't very clear, again to hinder
- * race-conditions. Most of the code is seldom used, (ie repeating),
- * so it should be much more efficient than it looks.
- *
- * The algoritm is changed: better, and an elusive bug removed.
- *             LBT 11.11.91
- */
-#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
-struct buffer_head * getblk(int dev,int block)
-{
-       struct buffer_head * tmp, * bh;
-
-repeat:
-       if (bh = get_hash_table(dev,block))
-               return bh;
-       tmp = free_list;
-       do {
-               if (tmp->b_count)
-                       continue;
-               if (!bh || BADNESS(tmp)<BADNESS(bh)) {
-                       bh = tmp;
-                       if (!BADNESS(tmp))
-                               break;
-               }
-       } while ((tmp = tmp->b_next_free) != free_list);
-       if (!bh) {
-               sleep_on(&buffer_wait);
-               goto repeat;
-       }
-       wait_on_buffer(bh);
-       if (bh->b_count)
-               goto repeat;
-       while (bh->b_dirt) {
-               sync_dev(bh->b_dev);
-               wait_on_buffer(bh);
-               if (bh->b_count)
-                       goto repeat;
-       }
-/* NOTE!! While we slept waiting for this block, somebody else might */
-/* already have added "this" block to the cache. check it */
-       if (find_buffer(dev,block))
-               goto repeat;
-/* OK, FINALLY we know that this buffer is the only one of it's kind, */
-/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
-       bh->b_count=1;
-       bh->b_dirt=0;
-       bh->b_uptodate=0;
-       remove_from_queues(bh);
-       bh->b_dev=dev;
-       bh->b_blocknr=block;
-       insert_into_queues(bh);
-       return bh;
-}
-
-void brelse(struct buffer_head * buf)
-{
-       if (!buf)
-               return;
-       wait_on_buffer(buf);
-       if (!(buf->b_count--))
-               panic("Trying to free free buffer");
-       wake_up(&buffer_wait);
-}
-
-/*
- * 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)
-{
-       struct buffer_head * bh;
-
-       if (!(bh=getblk(dev,block)))
-               panic("bread: getblk returned NULL\n");
-       if (bh->b_uptodate)
-               return bh;
-       ll_rw_block(READ,bh);
-       wait_on_buffer(bh);
-       if (bh->b_uptodate)
-               return bh;
-       brelse(bh);
-       return NULL;
-}
-
-/*
- * Ok, breada can be used as bread, but additionally to mark other
- * blocks for reading as well. End the argument list with a negative
- * number.
- */
-struct buffer_head * breada(int dev,int first, ...)
-{
-       va_list args;
-       struct buffer_head * bh, *tmp;
-
-       va_start(args,first);
-       if (!(bh=getblk(dev,first)))
-               panic("bread: getblk returned NULL\n");
-       if (!bh->b_uptodate)
-               ll_rw_block(READ,bh);
-       while ((first=va_arg(args,int))>=0) {
-               tmp=getblk(dev,first);
-               if (tmp) {
-                       if (!tmp->b_uptodate)
-                               ll_rw_block(READA,bh);
-                       tmp->b_count--;
-               }
-       }
-       va_end(args);
-       wait_on_buffer(bh);
-       if (bh->b_uptodate)
-               return bh;
-       brelse(bh);
-       return (NULL);
-}
-
-void buffer_init(long buffer_end)
-{
-       struct buffer_head * h = start_buffer;
-       void * b;
-       int i;
-
-       if (buffer_end == 1<<20)
-               b = (void *) (640*1024);
-       else
-               b = (void *) buffer_end;
-       while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
-               h->b_dev = 0;
-               h->b_dirt = 0;
-               h->b_count = 0;
-               h->b_lock = 0;
-               h->b_uptodate = 0;
-               h->b_wait = NULL;
-               h->b_next = NULL;
-               h->b_prev = NULL;
-               h->b_data = (char *) b;
-               h->b_prev_free = h-1;
-               h->b_next_free = h+1;
-               h++;
-               NR_BUFFERS++;
-               if (b == (void *) 0x100000)
-                       b = (void *) 0xA0000;
-       }
-       h--;
-       free_list = start_buffer;
-       free_list->b_prev_free = h;
-       h->b_next_free = free_list;
-       for (i=0;i<NR_HASH;i++)
-               hash_table[i]=NULL;
-}      
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d72 9
-d196 3
-d200 1
-d203 1
-a203 1
-       struct buffer_head * tmp;
-d206 2
-a207 2
-       if (tmp=get_hash_table(dev,block))
-               return tmp;
-d209 6
-a214 4
-       for (;;) {
-               if (!tmp->b_count) {
-                       wait_on_buffer(tmp);    /* we still have to wait */
-                       if (!tmp->b_count)      /* on it, it might be dirty */
-d217 12
-a228 3
-               tmp = tmp->b_next_free;
-               if (tmp == free_list) {
-                       sleep_on(&buffer_wait);
-a229 1
-               }
-d231 3
-a233 23
-       tmp->b_count++;
-       remove_from_queues(tmp);
-/*
- * Now, when we know nobody can get to this node (as it's removed from the
- * free list), we write it out. We can sleep here without fear of race-
- * conditions.
- */
-       while (tmp->b_dirt) {
-               sync_dev(tmp->b_dev);
-               wait_on_buffer(tmp);
-       }
-/* update buffer contents */
-       tmp->b_dev=dev;
-       tmp->b_blocknr=block;
-       tmp->b_dirt=0;
-       tmp->b_uptodate=0;
-/* NOTE!! While we possibly slept in sync_dev(), somebody else might have */
-/* added "this" block already, so check for that. Thank God for goto's. */
-       if (find_buffer(dev,block)) {
-               tmp->b_dev=0;           /* ok, someone else has beaten us */
-               tmp->b_blocknr=0;       /* to it - free this block and */
-               tmp->b_count=0;         /* try again */
-               insert_into_queues(tmp);
-d235 10
-a244 4
-       }
-/* and then insert into correct position */
-       insert_into_queues(tmp);
-       return tmp;
-@
diff --git a/fs/RCS/exec.c,v b/fs/RCS/exec.c,v
deleted file mode 100644 (file)
index 5e0ea5b..0000000
+++ /dev/null
@@ -1,547 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    tytso:1.2; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.22.01;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.23.19.36;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to Linus
-@
-text
-@/*
- *  linux/fs/exec.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <a.out.h>
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/segment.h>
-
-extern int sys_exit(int exit_code);
-extern int sys_close(int fd);
-
-/*
- * MAX_ARG_PAGES defines the number of pages allocated for arguments
- * and envelope for the new program. 32 should suffice, this gives
- * a maximum env+arg of 128kB !
- */
-#define MAX_ARG_PAGES 32
-
-#define cp_block(from,to) \
-__asm__("pushl $0x10\n\t" \
-       "pushl $0x17\n\t" \
-       "pop %%es\n\t" \
-       "cld\n\t" \
-       "rep\n\t" \
-       "movsl\n\t" \
-       "pop %%es" \
-       ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
-       :"cx","di","si")
-
-/*
- * read_head() reads blocks 1-6 (not 0). Block 0 has already been
- * read for header information.
- */
-int read_head(struct m_inode * inode,int blocks)
-{
-       struct buffer_head * bh;
-       int count;
-
-       if (blocks>6)
-               blocks=6;
-       for(count = 0 ; count<blocks ; count++) {
-               if (!inode->i_zone[count+1])
-                       continue;
-               if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
-                       return -1;
-               cp_block(bh->b_data,count*BLOCK_SIZE);
-               brelse(bh);
-       }
-       return 0;
-}
-
-int read_ind(int dev,int ind,long size,unsigned long offset)
-{
-       struct buffer_head * ih, * bh;
-       unsigned short * table,block;
-
-       if (size<=0)
-               panic("size<=0 in read_ind");
-       if (size>512*BLOCK_SIZE)
-               size=512*BLOCK_SIZE;
-       if (!ind)
-               return 0;
-       if (!(ih=bread(dev,ind)))
-               return -1;
-       table = (unsigned short *) ih->b_data;
-       while (size>0) {
-               if (block=*(table++))
-                       if (!(bh=bread(dev,block))) {
-                               brelse(ih);
-                               return -1;
-                       } else {
-                               cp_block(bh->b_data,offset);
-                               brelse(bh);
-                       }
-               size -= BLOCK_SIZE;
-               offset += BLOCK_SIZE;
-       }
-       brelse(ih);
-       return 0;
-}
-
-/*
- * read_area() reads an area into %fs:mem.
- */
-int read_area(struct m_inode * inode,long size)
-{
-       struct buffer_head * dind;
-       unsigned short * table;
-       int i,count;
-
-       if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
-           (size -= BLOCK_SIZE*6)<=0)
-               return i;
-       if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
-           (size -= BLOCK_SIZE*512)<=0)
-               return i;
-       if (!(i=inode->i_zone[8]))
-               return 0;
-       if (!(dind = bread(inode->i_dev,i)))
-               return -1;
-       table = (unsigned short *) dind->b_data;
-       for(count=0 ; count<512 ; count++)
-               if ((i=read_ind(inode->i_dev,*(table++),size,
-                   BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
-                       return i;
-       panic("Impossibly long executable");
-}
-
-/*
- * create_tables() parses the env- and arg-strings in new user
- * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
- */
-static unsigned long * create_tables(char * p,int argc,int envc)
-{
-       unsigned long *argv,*envp;
-       unsigned long * sp;
-
-       sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
-       sp -= envc+1;
-       envp = sp;
-       sp -= argc+1;
-       argv = sp;
-       put_fs_long((unsigned long)envp,--sp);
-       put_fs_long((unsigned long)argv,--sp);
-       put_fs_long((unsigned long)argc,--sp);
-       while (argc-->0) {
-               put_fs_long((unsigned long) p,argv++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,argv);
-       while (envc-->0) {
-               put_fs_long((unsigned long) p,envp++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,envp);
-       return sp;
-}
-
-/*
- * count() counts the number of arguments/envelopes
- */
-static int count(char ** argv)
-{
-       int i=0;
-       char ** tmp;
-
-       if (tmp = argv)
-               while (get_fs_long((unsigned long *) (tmp++)))
-                       i++;
-
-       return i;
-}
-
-/*
- * 'copy_string()' copies argument/envelope strings from user
- * memory to free pages in kernel mem. These are in a format ready
- * to be put directly into the top of new user memory.
- *
- * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
- * whether the string and the string array are from user or kernel segments:
- * 
- * from_kmem     argv *        argv **
- *    0          user space    user space
- *    1          kernel space  user space
- *    2          kernel space  kernel space
- * 
- * We do this by playing games with the fs segment register.  Since it
- * it is expensive to load a segment register, we try to avoid calling
- * set_fs() unless we absolutely have to.
- */
-static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
-               unsigned long p, int from_kmem)
-{
-       char *tmp, *pag;
-       int len, offset = 0;
-       unsigned long old_fs, new_fs;
-
-       if (!p)
-               return 0;       /* bullet-proofing */
-       new_fs = get_ds();
-       old_fs = get_fs();
-       if (from_kmem==2)
-               set_fs(new_fs);
-       while (argc-- > 0) {
-               if (from_kmem == 1)
-                       set_fs(new_fs);
-               if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
-                       panic("argc is wrong");
-               if (from_kmem == 1)
-                       set_fs(old_fs);
-               len=0;          /* remember zero-padding */
-               do {
-                       len++;
-               } while (get_fs_byte(tmp++));
-               if (p-len < 0) {        /* this shouldn't happen - 128kB */
-                       set_fs(old_fs);
-                       return 0;
-               }
-               while (len) {
-                       --p; --tmp; --len;
-                       if (--offset < 0) {
-                               offset = p % PAGE_SIZE;
-                               if (from_kmem==2)
-                                       set_fs(old_fs);
-                               if (!(pag = (char *) page[p/PAGE_SIZE]) &&
-                                   !(pag = (char *) page[p/PAGE_SIZE] =
-                                     (unsigned long *) get_free_page())) 
-                                       return 0;
-                               if (from_kmem==2)
-                                       set_fs(new_fs);
-
-                       }
-                       *(pag + offset) = get_fs_byte(tmp);
-               }
-       }
-       if (from_kmem==2)
-               set_fs(old_fs);
-       return p;
-}
-
-static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
-{
-       unsigned long code_limit,data_limit,code_base,data_base;
-       int i;
-
-       code_limit = text_size+PAGE_SIZE -1;
-       code_limit &= 0xFFFFF000;
-       data_limit = 0x4000000;
-       code_base = get_base(current->ldt[1]);
-       data_base = code_base;
-       set_base(current->ldt[1],code_base);
-       set_limit(current->ldt[1],code_limit);
-       set_base(current->ldt[2],data_base);
-       set_limit(current->ldt[2],data_limit);
-/* make sure fs points to the NEW data segment */
-       __asm__("pushl $0x17\n\tpop %%fs"::);
-       data_base += data_limit;
-       for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
-               data_base -= PAGE_SIZE;
-               if (page[i])
-                       put_page(page[i],data_base);
-       }
-       return data_limit;
-}
-
-/*
- * 'do_execve()' executes a new program.
- */
-int do_execve(unsigned long * eip,long tmp,char * filename,
-       char ** argv, char ** envp)
-{
-       struct m_inode * inode;
-       struct buffer_head * bh;
-       struct exec ex;
-       unsigned long page[MAX_ARG_PAGES];
-       int i,argc,envc;
-       int e_uid, e_gid;
-       int retval;
-       int sh_bang = 0;
-       unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
-
-       if ((0xffff & eip[1]) != 0x000f)
-               panic("execve called from supervisor mode");
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-               page[i]=0;
-       if (!(inode=namei(filename)))           /* get executables inode */
-               return -ENOENT;
-       argc = count(argv);
-       envc = count(envp);
-       
-restart_interp:
-       if (!S_ISREG(inode->i_mode)) {  /* must be regular file */
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       i = inode->i_mode;
-       e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
-       e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
-       if (current->euid == inode->i_uid)
-               i >>= 6;
-       else if (current->egid == inode->i_gid)
-               i >>= 3;
-       if (!(i & 1) &&
-           !((inode->i_mode & 0111) && suser())) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       ex = *((struct exec *) bh->b_data);     /* read exec-header */
-       if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
-               /*
-                * This section does the #! interpretation.
-                * Sorta complicated, but hopefully it will work.  -TYT
-                */
-
-               char buf[1023], *cp, *interp, *i_name, *i_arg;
-               unsigned long old_fs;
-
-               strncpy(buf, bh->b_data+2, 1022);
-               brelse(bh);
-               iput(inode);
-               buf[1022] = '\0';
-               if (cp = strchr(buf, '\n')) {
-                       *cp = '\0';
-                       for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
-               }
-               if (!cp || *cp == '\0') {
-                       retval = -ENOEXEC; /* No interpreter name found */
-                       goto exec_error1;
-               }
-               interp = i_name = cp;
-               i_arg = 0;
-               for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
-                       if (*cp == '/')
-                               i_name = cp+1;
-               }
-               if (*cp) {
-                       *cp++ = '\0';
-                       i_arg = cp;
-               }
-               /*
-                * OK, we've parsed out the interpreter name and
-                * (optional) argument.
-                */
-               if (sh_bang++ == 0) {
-                       p = copy_strings(envc, envp, page, p, 0);
-                       p = copy_strings(--argc, argv+1, page, p, 0);
-               }
-               /*
-                * Splice in (1) the interpreter's name for argv[0]
-                *           (2) (optional) argument to interpreter
-                *           (3) filename of shell script
-                *
-                * This is done in reverse order, because of how the
-                * user environment and arguments are stored.
-                */
-               p = copy_strings(1, &filename, page, p, 1);
-               argc++;
-               if (i_arg) {
-                       p = copy_strings(1, &i_arg, page, p, 2);
-                       argc++;
-               }
-               p = copy_strings(1, &i_name, page, p, 2);
-               argc++;
-               if (!p) {
-                       retval = -ENOMEM;
-                       goto exec_error1;
-               }
-               /*
-                * OK, now restart the process with the interpreter's inode.
-                */
-               old_fs = get_fs();
-               set_fs(get_ds());
-               if (!(inode=namei(interp))) { /* get executables inode */
-                       set_fs(old_fs);
-                       retval = -ENOENT;
-                       goto exec_error1;
-               }
-               set_fs(old_fs);
-               goto restart_interp;
-       }
-       brelse(bh);
-       if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
-               ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
-               inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (N_TXTOFF(ex) != BLOCK_SIZE) {
-               printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!sh_bang) {
-               p = copy_strings(envc,envp,page,p,0);
-               p = copy_strings(argc,argv,page,p,0);
-               if (!p) {
-                       retval = -ENOMEM;
-                       goto exec_error2;
-               }
-       }
-/* OK, This is the point of no return */
-       for (i=0 ; i<32 ; i++)
-               current->sigaction[i].sa_handler = NULL;
-       for (i=0 ; i<NR_OPEN ; i++)
-               if ((current->close_on_exec>>i)&1)
-                       sys_close(i);
-       current->close_on_exec = 0;
-       free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
-       free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
-       current->used_math = 0;
-       p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
-       p = (unsigned long) create_tables((char *)p,argc,envc);
-       current->brk = ex.a_bss +
-               (current->end_data = ex.a_data +
-               (current->end_code = ex.a_text));
-       current->start_stack = p & 0xfffff000;
-       current->euid = e_uid;
-       current->egid = e_gid;
-       i = read_area(inode,ex.a_text+ex.a_data);
-       iput(inode);
-       if (i<0)
-               sys_exit(-1);
-       i = ex.a_text+ex.a_data;
-       while (i&0xfff)
-               put_fs_byte(0,(char *) (i++));
-       eip[0] = ex.a_entry;            /* eip, magic happens :-) */
-       eip[3] = p;                     /* stack pointer */
-       return 0;
-exec_error2:
-       iput(inode);
-exec_error1:
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)
-               free_page(page[i]);
-       return(retval);
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d8 1
-d168 12
-d182 1
-a182 1
-               unsigned long p)
-d184 3
-a186 2
-       int len,i;
-       char *tmp;
-d188 6
-d195 3
-a197 1
-               if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
-d199 2
-d205 2
-a206 1
-               if (p-len < 0)          /* this shouldn't happen - 128kB */
-a207 5
-               i = ((unsigned) (p-len)) >> 12;
-               while (i<MAX_ARG_PAGES && !page[i]) {
-                       if (!(page[i]=get_free_page()))
-                               return 0;
-                       i++;
-d209 16
-a224 7
-               do {
-                       --p;
-                       if (!page[p/PAGE_SIZE])
-                               panic("nonexistent page in exec.c");
-                       ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
-                               get_fs_byte(--tmp);
-               } while (--len);
-d226 2
-d267 4
-a270 1
-       unsigned long p;
-d278 4
-d283 2
-a284 2
-               iput(inode);
-               return -EACCES;
-d287 10
-a296 10
-       if (current->uid && current->euid) {
-               if (current->euid == inode->i_uid)
-                       i >>= 6;
-               else if (current->egid == inode->i_gid)
-                       i >>= 3;
-       } else if (i & 0111)
-               i=1;
-       if (!(i & 1)) {
-               iput(inode);
-               return -ENOEXEC;
-d299 15
-d315 59
-a373 1
-               return -EACCES;
-a374 1
-       ex = *((struct exec *) bh->b_data);     /* read exec-header */
-d379 2
-a380 2
-               iput(inode);
-               return -ENOEXEC;
-d382 4
-a385 11
-       if (N_TXTOFF(ex) != BLOCK_SIZE)
-               panic("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
-       argc = count(argv);
-       envc = count(envp);
-       p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES-4);
-       p = copy_strings(argc,argv,page,p);
-       if (!p) {
-               for (i=0 ; i<MAX_ARG_PAGES ; i++)
-                       free_page(page[i]);
-               iput(inode);
-               return -1;
-d387 8
-d413 2
-d425 6
-@
diff --git a/fs/RCS/namei.c,v b/fs/RCS/namei.c,v
deleted file mode 100644 (file)
index 8a33451..0000000
+++ /dev/null
@@ -1,831 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.22.07;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.09.55.14;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to Linus
-@
-text
-@/*
- *  linux/fs/namei.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <const.h>
-#include <sys/stat.h>
-
-#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
-
-/*
- * comment out this line if you want names > NAME_LEN chars to be
- * truncated. Else they will be disallowed.
- */
-/* #define NO_TRUNCATE */
-
-#define MAY_EXEC 1
-#define MAY_WRITE 2
-#define MAY_READ 4
-
-/*
- *     permission()
- *
- * is used to check for read/write/execute permissions on a file.
- * I don't know if we should look at just the euid or both euid and
- * uid, but that should be easily changed.
- */
-static int permission(struct m_inode * inode,int mask)
-{
-       int mode = inode->i_mode;
-
-/* special case: not even root can read/write a deleted file */
-       if (inode->i_dev && !inode->i_nlinks)
-               return 0;
-       else if (current->euid==inode->i_uid)
-               mode >>= 6;
-       else if (current->egid==inode->i_gid)
-               mode >>= 3;
-       if (((mode & mask & 0007) == mask) || suser())
-               return 1;
-       return 0;
-}
-
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
- */
-static int match(int len,const char * name,struct dir_entry * de)
-{
-       register int same __asm__("ax");
-
-       if (!de || !de->inode || len > NAME_LEN)
-               return 0;
-       if (len < NAME_LEN && de->name[len])
-               return 0;
-       __asm__("cld\n\t"
-               "fs ; repe ; cmpsb\n\t"
-               "setz %%al"
-               :"=a" (same)
-               :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
-               :"cx","di","si");
-       return same;
-}
-
-/*
- *     find_entry()
- *
- * finds and entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- *
- * This also takes care of the few special cases due to '..'-traversal
- * over a pseudo-root and a mount point.
- */
-static struct buffer_head * find_entry(struct m_inode ** dir,
-       const char * name, int namelen, struct dir_entry ** res_dir)
-{
-       int entries;
-       int block,i;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-       struct super_block * sb;
-
-#ifdef NO_TRUNCATE
-       if (namelen > NAME_LEN)
-               return NULL;
-#else
-       if (namelen > NAME_LEN)
-               namelen = NAME_LEN;
-#endif
-       entries = (*dir)->i_size / (sizeof (struct dir_entry));
-       *res_dir = NULL;
-       if (!namelen)
-               return NULL;
-/* check for '..', as we might have to do some "magic" for it */
-       if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
-/* '..' in a pseudo-root results in a faked '.' (just change namelen) */
-               if ((*dir) == current->root)
-                       namelen=1;
-               else if ((*dir)->i_num == ROOT_INO) {
-/* '..' over a mount-point results in 'dir' being exchanged for the mounted
-   directory-inode. NOTE! We set mounted, so that we can iput the new dir */
-                       sb=get_super((*dir)->i_dev);
-                       if (sb->s_imount) {
-                               iput(*dir);
-                               (*dir)=sb->s_imount;
-                               (*dir)->i_count++;
-                       }
-               }
-       }
-       if (!(block = (*dir)->i_zone[0]))
-               return NULL;
-       if (!(bh = bread((*dir)->i_dev,block)))
-               return NULL;
-       i = 0;
-       de = (struct dir_entry *) bh->b_data;
-       while (i < entries) {
-               if ((char *)de >= BLOCK_SIZE+bh->b_data) {
-                       brelse(bh);
-                       bh = NULL;
-                       if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
-                           !(bh = bread((*dir)->i_dev,block))) {
-                               i += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (match(namelen,name,de)) {
-                       *res_dir = de;
-                       return bh;
-               }
-               de++;
-               i++;
-       }
-       brelse(bh);
-       return NULL;
-}
-
-/*
- *     add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * add_entry(struct m_inode * dir,
-       const char * name, int namelen, struct dir_entry ** res_dir)
-{
-       int block,i;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       *res_dir = NULL;
-#ifdef NO_TRUNCATE
-       if (namelen > NAME_LEN)
-               return NULL;
-#else
-       if (namelen > NAME_LEN)
-               namelen = NAME_LEN;
-#endif
-       if (!namelen)
-               return NULL;
-       if (!(block = dir->i_zone[0]))
-               return NULL;
-       if (!(bh = bread(dir->i_dev,block)))
-               return NULL;
-       i = 0;
-       de = (struct dir_entry *) bh->b_data;
-       while (1) {
-               if ((char *)de >= BLOCK_SIZE+bh->b_data) {
-                       brelse(bh);
-                       bh = NULL;
-                       block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
-                       if (!block)
-                               return NULL;
-                       if (!(bh = bread(dir->i_dev,block))) {
-                               i += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (i*sizeof(struct dir_entry) >= dir->i_size) {
-                       de->inode=0;
-                       dir->i_size = (i+1)*sizeof(struct dir_entry);
-                       dir->i_dirt = 1;
-                       dir->i_ctime = CURRENT_TIME;
-               }
-               if (!de->inode) {
-                       dir->i_mtime = CURRENT_TIME;
-                       for (i=0; i < NAME_LEN ; i++)
-                               de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
-                       bh->b_dirt = 1;
-                       *res_dir = de;
-                       return bh;
-               }
-               de++;
-               i++;
-       }
-       brelse(bh);
-       return NULL;
-}
-
-/*
- *     get_dir()
- *
- * Getdir traverses the pathname until it hits the topmost directory.
- * It returns NULL on failure.
- */
-static struct m_inode * get_dir(const char * pathname)
-{
-       char c;
-       const char * thisname;
-       struct m_inode * inode;
-       struct buffer_head * bh;
-       int namelen,inr,idev;
-       struct dir_entry * de;
-
-       if (!current->root || !current->root->i_count)
-               panic("No root inode");
-       if (!current->pwd || !current->pwd->i_count)
-               panic("No cwd inode");
-       if ((c=get_fs_byte(pathname))=='/') {
-               inode = current->root;
-               pathname++;
-       } else if (c)
-               inode = current->pwd;
-       else
-               return NULL;    /* empty name is bad */
-       inode->i_count++;
-       while (1) {
-               thisname = pathname;
-               if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
-                       iput(inode);
-                       return NULL;
-               }
-               for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
-                       /* nothing */ ;
-               if (!c)
-                       return inode;
-               if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
-                       iput(inode);
-                       return NULL;
-               }
-               inr = de->inode;
-               idev = inode->i_dev;
-               brelse(bh);
-               iput(inode);
-               if (!(inode = iget(idev,inr)))
-                       return NULL;
-       }
-}
-
-/*
- *     dir_namei()
- *
- * dir_namei() returns the inode of the directory of the
- * specified name, and the name within that directory.
- */
-static struct m_inode * dir_namei(const char * pathname,
-       int * namelen, const char ** name)
-{
-       char c;
-       const char * basename;
-       struct m_inode * dir;
-
-       if (!(dir = get_dir(pathname)))
-               return NULL;
-       basename = pathname;
-       while (c=get_fs_byte(pathname++))
-               if (c=='/')
-                       basename=pathname;
-       *namelen = pathname-basename-1;
-       *name = basename;
-       return dir;
-}
-
-/*
- *     namei()
- *
- * is used by most simple commands to get the inode of a specified name.
- * Open, link etc use their own routines, but this is enough for things
- * like 'chmod' etc.
- */
-struct m_inode * namei(const char * pathname)
-{
-       const char * basename;
-       int inr,dev,namelen;
-       struct m_inode * dir;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return NULL;
-       if (!namelen)                   /* special case: '/usr/' etc */
-               return dir;
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return NULL;
-       }
-       inr = de->inode;
-       dev = dir->i_dev;
-       brelse(bh);
-       iput(dir);
-       dir=iget(dev,inr);
-       if (dir) {
-               dir->i_atime=CURRENT_TIME;
-               dir->i_dirt=1;
-       }
-       return dir;
-}
-
-/*
- *     open_namei()
- *
- * namei for open - this is in fact almost the whole open-routine.
- */
-int open_namei(const char * pathname, int flag, int mode,
-       struct m_inode ** res_inode)
-{
-       const char * basename;
-       int inr,dev,namelen;
-       struct m_inode * dir, *inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
-               flag |= O_WRONLY;
-       mode &= 0777 & ~current->umask;
-       mode |= I_REGULAR;
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {                 /* special case: '/usr/' etc */
-               if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
-                       *res_inode=dir;
-                       return 0;
-               }
-               iput(dir);
-               return -EISDIR;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               if (!(flag & O_CREAT)) {
-                       iput(dir);
-                       return -ENOENT;
-               }
-               if (!permission(dir,MAY_WRITE)) {
-                       iput(dir);
-                       return -EACCES;
-               }
-               inode = new_inode(dir->i_dev);
-               if (!inode) {
-                       iput(dir);
-                       return -ENOSPC;
-               }
-               inode->i_uid = current->euid;
-               inode->i_mode = mode;
-               inode->i_dirt = 1;
-               bh = add_entry(dir,basename,namelen,&de);
-               if (!bh) {
-                       inode->i_nlinks--;
-                       iput(inode);
-                       iput(dir);
-                       return -ENOSPC;
-               }
-               de->inode = inode->i_num;
-               bh->b_dirt = 1;
-               brelse(bh);
-               iput(dir);
-               *res_inode = inode;
-               return 0;
-       }
-       inr = de->inode;
-       dev = dir->i_dev;
-       brelse(bh);
-       iput(dir);
-       if (flag & O_EXCL)
-               return -EEXIST;
-       if (!(inode=iget(dev,inr)))
-               return -EACCES;
-       if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
-           !permission(inode,ACC_MODE(flag))) {
-               iput(inode);
-               return -EPERM;
-       }
-       inode->i_atime = CURRENT_TIME;
-       if (flag & O_TRUNC)
-               truncate(inode);
-       *res_inode = inode;
-       return 0;
-}
-
-int sys_mknod(const char * filename, int mode, int dev)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-       
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(filename,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!permission(dir,MAY_WRITE)) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               return -EEXIST;
-       }
-       inode = new_inode(dir->i_dev);
-       if (!inode) {
-               iput(dir);
-               return -ENOSPC;
-       }
-       inode->i_mode = mode;
-       if (S_ISBLK(mode) || S_ISCHR(mode))
-               inode->i_zone[0] = dev;
-       inode->i_mtime = inode->i_atime = CURRENT_TIME;
-       inode->i_dirt = 1;
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               inode->i_nlinks=0;
-               iput(inode);
-               return -ENOSPC;
-       }
-       de->inode = inode->i_num;
-       bh->b_dirt = 1;
-       iput(dir);
-       iput(inode);
-       brelse(bh);
-       return 0;
-}
-
-int sys_mkdir(const char * pathname, int mode)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh, *dir_block;
-       struct dir_entry * de;
-
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!permission(dir,MAY_WRITE)) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               return -EEXIST;
-       }
-       inode = new_inode(dir->i_dev);
-       if (!inode) {
-               iput(dir);
-               return -ENOSPC;
-       }
-       inode->i_size = 32;
-       inode->i_dirt = 1;
-       inode->i_mtime = inode->i_atime = CURRENT_TIME;
-       if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
-               iput(dir);
-               inode->i_nlinks--;
-               iput(inode);
-               return -ENOSPC;
-       }
-       inode->i_dirt = 1;
-       if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
-               iput(dir);
-               free_block(inode->i_dev,inode->i_zone[0]);
-               inode->i_nlinks--;
-               iput(inode);
-               return -ERROR;
-       }
-       de = (struct dir_entry *) dir_block->b_data;
-       de->inode=inode->i_num;
-       strcpy(de->name,".");
-       de++;
-       de->inode = dir->i_num;
-       strcpy(de->name,"..");
-       inode->i_nlinks = 2;
-       dir_block->b_dirt = 1;
-       brelse(dir_block);
-       inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
-       inode->i_dirt = 1;
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               free_block(inode->i_dev,inode->i_zone[0]);
-               inode->i_nlinks=0;
-               iput(inode);
-               return -ENOSPC;
-       }
-       de->inode = inode->i_num;
-       bh->b_dirt = 1;
-       dir->i_nlinks++;
-       dir->i_dirt = 1;
-       iput(dir);
-       iput(inode);
-       brelse(bh);
-       return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct m_inode * inode)
-{
-       int nr,block;
-       int len;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       len = inode->i_size / sizeof (struct dir_entry);
-       if (len<2 || !inode->i_zone[0] ||
-           !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
-               printk("warning - bad directory on dev %04x\n",inode->i_dev);
-               return 0;
-       }
-       de = (struct dir_entry *) bh->b_data;
-       if (de[0].inode != inode->i_num || !de[1].inode || 
-           strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
-               printk("warning - bad directory on dev %04x\n",inode->i_dev);
-               return 0;
-       }
-       nr = 2;
-       de += 2;
-       while (nr<len) {
-               if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
-                       brelse(bh);
-                       block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
-                       if (!block) {
-                               nr += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       if (!(bh=bread(inode->i_dev,block)))
-                               return 0;
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (de->inode) {
-                       brelse(bh);
-                       return 0;
-               }
-               de++;
-               nr++;
-       }
-       brelse(bh);
-       return 1;
-}
-
-int sys_rmdir(const char * name)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(name,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!permission(dir,MAY_WRITE)) {
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (!(inode = iget(dir->i_dev, de->inode))) {
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (inode == dir) {     /* we may not delete ".", but "../dir" is ok */
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOTDIR;
-       }
-       if (!empty_dir(inode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOTEMPTY;
-       }
-       if (inode->i_nlinks != 2)
-               printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
-       de->inode = 0;
-       bh->b_dirt = 1;
-       brelse(bh);
-       inode->i_nlinks=0;
-       inode->i_dirt=1;
-       dir->i_nlinks--;
-       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       dir->i_dirt=1;
-       iput(dir);
-       iput(inode);
-       return 0;
-}
-
-int sys_unlink(const char * name)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!(dir = dir_namei(name,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!permission(dir,MAY_WRITE)) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return -ENOENT;
-       }
-       inode = iget(dir->i_dev, de->inode);
-       if (!inode) {
-               printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOENT;
-       }
-       if (S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       /*
-        * If the directory has the sticky bit, the user must either
-        * own the file or own the directory or be the superuser to 
-        * delete a file in that directory.  This is typically used 
-        * for /tmp and /usr/tmp.
-        */
-       if ((dir->i_mode & S_ISVTX) && (current->euid != inode->i_uid) &&
-           (current->euid != dir->i_uid) && !suser()) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }               
-       if (!inode->i_nlinks) {
-               printk("Deleting nonexistent file (%04x:%d), %d\n",
-                       inode->i_dev,inode->i_num,inode->i_nlinks);
-               inode->i_nlinks=1;
-       }
-       de->inode = 0;
-       bh->b_dirt = 1;
-       brelse(bh);
-       inode->i_nlinks--;
-       inode->i_dirt = 1;
-       inode->i_ctime = CURRENT_TIME;
-       iput(inode);
-       iput(dir);
-       return 0;
-}
-
-int sys_link(const char * oldname, const char * newname)
-{
-       struct dir_entry * de;
-       struct m_inode * oldinode, * dir;
-       struct buffer_head * bh;
-       const char * basename;
-       int namelen;
-
-       oldinode=namei(oldname);
-       if (!oldinode)
-               return -ENOENT;
-       if (S_ISDIR(oldinode->i_mode)) {
-               iput(oldinode);
-               return -EPERM;
-       }
-       dir = dir_namei(newname,&namelen,&basename);
-       if (!dir) {
-               iput(oldinode);
-               return -EACCES;
-       }
-       if (!namelen) {
-               iput(oldinode);
-               iput(dir);
-               return -EPERM;
-       }
-       if (dir->i_dev != oldinode->i_dev) {
-               iput(dir);
-               iput(oldinode);
-               return -EXDEV;
-       }
-       if (!permission(dir,MAY_WRITE)) {
-               iput(dir);
-               iput(oldinode);
-               return -EACCES;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               iput(oldinode);
-               return -EEXIST;
-       }
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               iput(oldinode);
-               return -ENOSPC;
-       }
-       de->inode = oldinode->i_num;
-       bh->b_dirt = 1;
-       brelse(bh);
-       iput(dir);
-       oldinode->i_nlinks++;
-       oldinode->i_ctime = CURRENT_TIME;
-       oldinode->i_dirt = 1;
-       iput(oldinode);
-       return 0;
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d43 1
-a43 3
-       if (!(current->uid && current->euid))
-               mode=0777;
-       else if (current->uid==inode->i_uid || current->euid==inode->i_uid)
-d45 1
-a45 1
-       else if (current->gid==inode->i_gid || current->egid==inode->i_gid)
-d47 3
-a49 1
-       return mode & mask & 0007;
-d371 1
-d397 1
-a397 1
-           permission(inode,ACC_MODE(flag))!=ACC_MODE(flag)) {
-d416 1
-a416 1
-       if (current->euid && current->uid)
-d467 1
-a467 1
-       if (current->euid && current->uid)
-d591 1
-a591 1
-       if (current->euid && current->uid)
-d683 13
-@
diff --git a/fs/RCS/open.c,v b/fs/RCS/open.c,v
deleted file mode 100644 (file)
index 18f4c73..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.22.10;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.09.38.53;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to Linus
-@
-text
-@/*
- *  linux/fs/open.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <utime.h>
-#include <sys/stat.h>
-
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-
-int sys_ustat(int dev, struct ustat * ubuf)
-{
-       return -ENOSYS;
-}
-
-int sys_utime(char * filename, struct utimbuf * times)
-{
-       struct m_inode * inode;
-       long actime,modtime;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (times) {
-               actime = get_fs_long((unsigned long *) &times->actime);
-               modtime = get_fs_long((unsigned long *) &times->modtime);
-       } else
-               actime = modtime = CURRENT_TIME;
-       inode->i_atime = actime;
-       inode->i_mtime = modtime;
-       inode->i_dirt = 1;
-       iput(inode);
-       return 0;
-}
-
-/*
- * XXX should we use the real or effective uid?  BSD uses the real uid,
- * so as to make this call useful to setuid programs.
- */
-int sys_access(const char * filename,int mode)
-{
-       struct m_inode * inode;
-       int res, i_mode;
-
-       mode &= 0007;
-       if (!(inode=namei(filename)))
-               return -EACCES;
-       i_mode = res = inode->i_mode & 0777;
-       iput(inode);
-       if (current->uid == inode->i_uid)
-               res >>= 6;
-       else if (current->gid == inode->i_gid)
-               res >>= 6;
-       if ((res & 0007 & mode) == mode)
-               return 0;
-       /*
-        * XXX we are doing this test last because we really should be
-        * swapping the effective with the real user id (temporarily),
-        * and then calling suser() routine.  If we do call the
-        * suser() routine, it needs to be called last. 
-        */
-       if ((!current->uid) &&
-           (!(mode & 1) || (i_mode & 0111)))
-               return 0;
-       return -EACCES;
-}
-
-int sys_chdir(const char * filename)
-{
-       struct m_inode * inode;
-
-       if (!(inode = namei(filename)))
-               return -ENOENT;
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               return -ENOTDIR;
-       }
-       iput(current->pwd);
-       current->pwd = inode;
-       return (0);
-}
-
-int sys_chroot(const char * filename)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               return -ENOTDIR;
-       }
-       iput(current->root);
-       current->root = inode;
-       return (0);
-}
-
-int sys_chmod(const char * filename,int mode)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if ((current->euid != inode->i_uid) && !suser()) {
-               iput(inode);
-               return -EACCES;
-       }
-       inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
-       inode->i_dirt = 1;
-       iput(inode);
-       return 0;
-}
-
-int sys_chown(const char * filename,int uid,int gid)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (!suser()) {
-               iput(inode);
-               return -EACCES;
-       }
-       inode->i_uid=uid;
-       inode->i_gid=gid;
-       inode->i_dirt=1;
-       iput(inode);
-       return 0;
-}
-
-int sys_open(const char * filename,int flag,int mode)
-{
-       struct m_inode * inode;
-       struct file * f;
-       int i,fd;
-
-       mode &= 0777 & ~current->umask;
-       for(fd=0 ; fd<NR_OPEN ; fd++)
-               if (!current->filp[fd])
-                       break;
-       if (fd>=NR_OPEN)
-               return -EINVAL;
-       current->close_on_exec &= ~(1<<fd);
-       f=0+file_table;
-       for (i=0 ; i<NR_FILE ; i++,f++)
-               if (!f->f_count) break;
-       if (i>=NR_FILE)
-               return -EINVAL;
-       (current->filp[fd]=f)->f_count++;
-       if ((i=open_namei(filename,flag,mode,&inode))<0) {
-               current->filp[fd]=NULL;
-               f->f_count=0;
-               return i;
-       }
-/* ttys are somewhat special (ttyxx major==4, tty major==5) */
-       if (S_ISCHR(inode->i_mode))
-               if (MAJOR(inode->i_zone[0])==4) {
-                       if (current->leader && current->tty<0) {
-                               current->tty = MINOR(inode->i_zone[0]);
-                               tty_table[current->tty].pgrp = current->pgrp;
-                       }
-               } else if (MAJOR(inode->i_zone[0])==5)
-                       if (current->tty<0) {
-                               iput(inode);
-                               current->filp[fd]=NULL;
-                               f->f_count=0;
-                               return -EPERM;
-                       }
-/* Likewise with block-devices: check for floppy_change */
-       if (S_ISBLK(inode->i_mode))
-               check_disk_change(inode->i_zone[0]);
-       f->f_mode = inode->i_mode;
-       f->f_flags = flag;
-       f->f_count = 1;
-       f->f_inode = inode;
-       f->f_pos = 0;
-       return (fd);
-}
-
-int sys_creat(const char * pathname, int mode)
-{
-       return sys_open(pathname, O_CREAT | O_TRUNC, mode);
-}
-
-int sys_close(unsigned int fd)
-{      
-       struct file * filp;
-
-       if (fd >= NR_OPEN)
-               return -EINVAL;
-       current->close_on_exec &= ~(1<<fd);
-       if (!(filp = current->filp[fd]))
-               return -EINVAL;
-       current->filp[fd] = NULL;
-       if (filp->f_count == 0)
-               panic("Close: file count is 0");
-       if (--filp->f_count)
-               return (0);
-       iput(filp->f_inode);
-       return (0);
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d43 4
-d50 1
-a50 1
-       int res;
-d55 1
-a55 1
-       res = inode->i_mode & 0777;
-d57 1
-a57 6
-       if (!(current->euid && current->uid))
-               if (res & 0111)
-                       res = 0777;
-               else
-                       res = 0666;
-       if (current->euid == inode->i_uid)
-d59 1
-a59 1
-       else if (current->egid == inode->i_gid)
-d63 9
-d111 4
-a114 6
-       if (current->uid && current->euid)
-               if (current->uid!=inode->i_uid && current->euid!=inode->i_uid) {
-                       iput(inode);
-                       return -EACCES;
-               } else 
-                       mode = (mode & 0777) | (inode->i_mode & 07000);
-d127 1
-a127 1
-       if (current->uid && current->euid) {
-@
index 843c9ee02765eb35eac24dd4a009b7c4ea0975d2..a3fc362ad8c2dee8498a1d4349a226c576ba57f0 100644 (file)
@@ -18,12 +18,14 @@ __asm__("cld\n\t" \
 
 #define set_bit(nr,addr) ({\
 register int res __asm__("ax"); \
-__asm__("btsl %2,%3\n\tsetb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
+__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
+"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
 res;})
 
 #define clear_bit(nr,addr) ({\
 register int res __asm__("ax"); \
-__asm__("btrl %2,%3\n\tsetnb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
+__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
+"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
 res;})
 
 #define find_first_zero(addr) ({ \
@@ -126,7 +128,7 @@ void free_inode(struct m_inode * inode)
        if (!(bh=sb->s_imap[inode->i_num>>13]))
                panic("nonexistent imap in superblock");
        if (clear_bit(inode->i_num&8191,bh->b_data))
-               panic("free_inode: bit already cleared");
+               printk("free_inode: bit already cleared.\n\r");
        bh->b_dirt = 1;
        memset(inode,0,sizeof(*inode));
 }
@@ -157,6 +159,8 @@ struct m_inode * new_inode(int dev)
        inode->i_count=1;
        inode->i_nlinks=1;
        inode->i_dev=dev;
+       inode->i_uid=current->euid;
+       inode->i_gid=current->egid;
        inode->i_dirt=1;
        inode->i_num = j + i*8192;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
index c8276316a149941dc43b9aa6f747bc56ee44bbbe..f0f3fb30bbc1b92d75fd0848ddad503a443d5fc4 100644 (file)
@@ -81,6 +81,21 @@ int sync_dev(int dev)
        return 0;
 }
 
+void inline invalidate_buffers(int dev)
+{
+       int i;
+       struct buffer_head * bh;
+
+       bh = start_buffer;
+       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
+               if (bh->b_dev != dev)
+                       continue;
+               wait_on_buffer(bh);
+               if (bh->b_dev == dev)
+                       bh->b_uptodate = bh->b_dirt = 0;
+       }
+}
+
 /*
  * This routine checks whether a floppy has been changed, and
  * invalidates all buffer-cache-entries in that case. This
@@ -98,25 +113,16 @@ int sync_dev(int dev)
 void check_disk_change(int dev)
 {
        int i;
-       struct buffer_head * bh;
 
        if (MAJOR(dev) != 2)
                return;
-       dev=MINOR(dev) & 0x03;  /* which floppy is it? */
-       if (!floppy_change(dev))
+       if (!floppy_change(dev & 0x03))
                return;
-       dev |= 0x200;
        for (i=0 ; i<NR_SUPER ; i++)
-               if ((super_block[i].s_dev & 0xff03)==dev)
+               if (super_block[i].s_dev == dev)
                        put_super(super_block[i].s_dev);
-       bh = start_buffer;
-       for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
-               if ((bh->b_dev & 0xff03) != dev)
-                       continue;
-               wait_on_buffer(bh);
-               if ((bh->b_dev & 0xff03) == dev)
-                       bh->b_uptodate = bh->b_dirt = 0;
-       }
+       invalidate_inodes(dev);
+       invalidate_buffers(dev);
 }
 
 #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
@@ -194,8 +200,7 @@ struct buffer_head * get_hash_table(int dev, int block)
  * race-conditions. Most of the code is seldom used, (ie repeating),
  * so it should be much more efficient than it looks.
  *
- * The algoritm is changed: better, and an elusive bug removed.
- *             LBT 11.11.91
+ * The algoritm is changed: hopefully better, and an elusive bug removed.
  */
 #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
 struct buffer_head * getblk(int dev,int block)
@@ -214,6 +219,7 @@ repeat:
                        if (!BADNESS(tmp))
                                break;
                }
+/* and repeat until we find something good */
        } while ((tmp = tmp->b_next_free) != free_list);
        if (!bh) {
                sleep_on(&buffer_wait);
@@ -274,6 +280,40 @@ struct buffer_head * bread(int dev,int block)
        return NULL;
 }
 
+#define COPYBLK(from,to) \
+__asm__("cld\n\t" \
+       "rep\n\t" \
+       "movsl\n\t" \
+       ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
+       :"cx","di","si")
+
+/*
+ * bread_page reads four buffers into memory at the desired address. It's
+ * a function of its own, as there is some speed to be got by reading them
+ * 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])
+{
+       struct buffer_head * bh[4];
+       int i;
+
+       for (i=0 ; i<4 ; i++)
+               if (b[i]) {
+                       if (bh[i] = getblk(dev,b[i]))
+                               if (!bh[i]->b_uptodate)
+                                       ll_rw_block(READ,bh[i]);
+               } else
+                       bh[i] = NULL;
+       for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
+               if (bh[i]) {
+                       wait_on_buffer(bh[i]);
+                       if (bh[i]->b_uptodate)
+                               COPYBLK((unsigned long) bh[i]->b_data,address);
+                       brelse(bh[i]);
+               }
+}
+
 /*
  * Ok, breada can be used as bread, but additionally to mark other
  * blocks for reading as well. End the argument list with a negative
index 8052a3ef2fb8faf8519974f21ae63d17cc9f6177..7b07cc9243dcb9b6b47a3ebb29029a7b5704eeb8 100644 (file)
@@ -97,10 +97,8 @@ int rw_char(int rw,int dev, char * buf, int count, off_t * pos)
        crw_ptr call_addr;
 
        if (MAJOR(dev)>=NRDEVS)
-               panic("rw_char: dev>NRDEV");
-       if (!(call_addr=crw_table[MAJOR(dev)])) {
-               printk("dev: %04x\n",dev);
-               panic("Trying to r/w from/to nonexistent character device");
-       }
+               return -ENODEV;
+       if (!(call_addr=crw_table[MAJOR(dev)]))
+               return -ENODEV;
        return call_addr(rw,MINOR(dev),buf,count,pos);
 }
index 5fd004921987036a9a4b0f82d97daa469814b11d..419f248797c3b6d4ba8ac01a3a6e2f69cf633627 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -4,6 +4,19 @@
  *  (C) 1991  Linus Torvalds
  */
 
+/*
+ * #!-checking implemented by tytso.
+ */
+
+/*
+ * Demand-loading implemented 01.12.91 - no need to read anything but
+ * the header into memory. The inode of the executable is put into
+ * "current->executable", and page faults do the actual loading. Clean.
+ *
+ * Once more I can proudly say that linux stood up to being changed: it
+ * was less than 2 hours work to get demand-loading completely implemented.
+ */
+
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -25,96 +38,6 @@ extern int sys_close(int fd);
  */
 #define MAX_ARG_PAGES 32
 
-#define cp_block(from,to) \
-__asm__("pushl $0x10\n\t" \
-       "pushl $0x17\n\t" \
-       "pop %%es\n\t" \
-       "cld\n\t" \
-       "rep\n\t" \
-       "movsl\n\t" \
-       "pop %%es" \
-       ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
-       :"cx","di","si")
-
-/*
- * read_head() reads blocks 1-6 (not 0). Block 0 has already been
- * read for header information.
- */
-int read_head(struct m_inode * inode,int blocks)
-{
-       struct buffer_head * bh;
-       int count;
-
-       if (blocks>6)
-               blocks=6;
-       for(count = 0 ; count<blocks ; count++) {
-               if (!inode->i_zone[count+1])
-                       continue;
-               if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
-                       return -1;
-               cp_block(bh->b_data,count*BLOCK_SIZE);
-               brelse(bh);
-       }
-       return 0;
-}
-
-int read_ind(int dev,int ind,long size,unsigned long offset)
-{
-       struct buffer_head * ih, * bh;
-       unsigned short * table,block;
-
-       if (size<=0)
-               panic("size<=0 in read_ind");
-       if (size>512*BLOCK_SIZE)
-               size=512*BLOCK_SIZE;
-       if (!ind)
-               return 0;
-       if (!(ih=bread(dev,ind)))
-               return -1;
-       table = (unsigned short *) ih->b_data;
-       while (size>0) {
-               if (block=*(table++))
-                       if (!(bh=bread(dev,block))) {
-                               brelse(ih);
-                               return -1;
-                       } else {
-                               cp_block(bh->b_data,offset);
-                               brelse(bh);
-                       }
-               size -= BLOCK_SIZE;
-               offset += BLOCK_SIZE;
-       }
-       brelse(ih);
-       return 0;
-}
-
-/*
- * read_area() reads an area into %fs:mem.
- */
-int read_area(struct m_inode * inode,long size)
-{
-       struct buffer_head * dind;
-       unsigned short * table;
-       int i,count;
-
-       if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
-           (size -= BLOCK_SIZE*6)<=0)
-               return i;
-       if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
-           (size -= BLOCK_SIZE*512)<=0)
-               return i;
-       if (!(i=inode->i_zone[8]))
-               return 0;
-       if (!(dind = bread(inode->i_dev,i)))
-               return -1;
-       table = (unsigned short *) dind->b_data;
-       for(count=0 ; count<512 ; count++)
-               if ((i=read_ind(inode->i_dev,*(table++),size,
-                   BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
-                       return i;
-       panic("Impossibly long executable");
-}
-
 /*
  * create_tables() parses the env- and arg-strings in new user
  * memory and creates the pointer tables from them, and puts their
@@ -267,7 +190,6 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
        int e_uid, e_gid;
        int retval;
        int sh_bang = 0;
-       char    *buf = 0;
        unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
 
        if ((0xffff & eip[1]) != 0x000f)
@@ -307,11 +229,9 @@ restart_interp:
                 * Sorta complicated, but hopefully it will work.  -TYT
                 */
 
-               char *cp, *interp, *i_name, *i_arg;
+               char buf[1023], *cp, *interp, *i_name, *i_arg;
                unsigned long old_fs;
 
-               if (!buf)
-                       buf = malloc(1024);
                strncpy(buf, bh->b_data+2, 1022);
                brelse(bh);
                iput(inode);
@@ -396,8 +316,9 @@ restart_interp:
                }
        }
 /* OK, This is the point of no return */
-       if (buf)
-               free_s(buf, 1024);
+       if (current->executable)
+               iput(current->executable);
+       current->executable = inode;
        for (i=0 ; i<32 ; i++)
                current->sigaction[i].sa_handler = NULL;
        for (i=0 ; i<NR_OPEN ; i++)
@@ -417,10 +338,6 @@ restart_interp:
        current->start_stack = p & 0xfffff000;
        current->euid = e_uid;
        current->egid = e_gid;
-       i = read_area(inode,ex.a_text+ex.a_data);
-       iput(inode);
-       if (i<0)
-               sys_exit(-1);
        i = ex.a_text+ex.a_data;
        while (i&0xfff)
                put_fs_byte(0,(char *) (i++));
@@ -430,8 +347,6 @@ restart_interp:
 exec_error2:
        iput(inode);
 exec_error1:
-       if (buf)
-               free(buf);
        for (i=0 ; i<MAX_ARG_PAGES ; i++)
                free_page(page[i]);
        return(retval);
diff --git a/fs/exec.c.orig b/fs/exec.c.orig
deleted file mode 100644 (file)
index 5fe481e..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- *  linux/fs/exec.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <a.out.h>
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/segment.h>
-
-extern int sys_exit(int exit_code);
-extern int sys_close(int fd);
-
-/*
- * MAX_ARG_PAGES defines the number of pages allocated for arguments
- * and envelope for the new program. 32 should suffice, this gives
- * a maximum env+arg of 128kB !
- */
-#define MAX_ARG_PAGES 32
-
-#define cp_block(from,to) \
-__asm__("pushl $0x10\n\t" \
-       "pushl $0x17\n\t" \
-       "pop %%es\n\t" \
-       "cld\n\t" \
-       "rep\n\t" \
-       "movsl\n\t" \
-       "pop %%es" \
-       ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
-       :"cx","di","si")
-
-/*
- * read_head() reads blocks 1-6 (not 0). Block 0 has already been
- * read for header information.
- */
-int read_head(struct m_inode * inode,int blocks)
-{
-       struct buffer_head * bh;
-       int count;
-
-       if (blocks>6)
-               blocks=6;
-       for(count = 0 ; count<blocks ; count++) {
-               if (!inode->i_zone[count+1])
-                       continue;
-               if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
-                       return -1;
-               cp_block(bh->b_data,count*BLOCK_SIZE);
-               brelse(bh);
-       }
-       return 0;
-}
-
-int read_ind(int dev,int ind,long size,unsigned long offset)
-{
-       struct buffer_head * ih, * bh;
-       unsigned short * table,block;
-
-       if (size<=0)
-               panic("size<=0 in read_ind");
-       if (size>512*BLOCK_SIZE)
-               size=512*BLOCK_SIZE;
-       if (!ind)
-               return 0;
-       if (!(ih=bread(dev,ind)))
-               return -1;
-       table = (unsigned short *) ih->b_data;
-       while (size>0) {
-               if (block=*(table++))
-                       if (!(bh=bread(dev,block))) {
-                               brelse(ih);
-                               return -1;
-                       } else {
-                               cp_block(bh->b_data,offset);
-                               brelse(bh);
-                       }
-               size -= BLOCK_SIZE;
-               offset += BLOCK_SIZE;
-       }
-       brelse(ih);
-       return 0;
-}
-
-/*
- * read_area() reads an area into %fs:mem.
- */
-int read_area(struct m_inode * inode,long size)
-{
-       struct buffer_head * dind;
-       unsigned short * table;
-       int i,count;
-
-       if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
-           (size -= BLOCK_SIZE*6)<=0)
-               return i;
-       if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
-           (size -= BLOCK_SIZE*512)<=0)
-               return i;
-       if (!(i=inode->i_zone[8]))
-               return 0;
-       if (!(dind = bread(inode->i_dev,i)))
-               return -1;
-       table = (unsigned short *) dind->b_data;
-       for(count=0 ; count<512 ; count++)
-               if ((i=read_ind(inode->i_dev,*(table++),size,
-                   BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
-                       return i;
-       panic("Impossibly long executable");
-}
-
-/*
- * create_tables() parses the env- and arg-strings in new user
- * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
- */
-static unsigned long * create_tables(char * p,int argc,int envc)
-{
-       unsigned long *argv,*envp;
-       unsigned long * sp;
-
-       sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
-       sp -= envc+1;
-       envp = sp;
-       sp -= argc+1;
-       argv = sp;
-       put_fs_long((unsigned long)envp,--sp);
-       put_fs_long((unsigned long)argv,--sp);
-       put_fs_long((unsigned long)argc,--sp);
-       while (argc-->0) {
-               put_fs_long((unsigned long) p,argv++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,argv);
-       while (envc-->0) {
-               put_fs_long((unsigned long) p,envp++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,envp);
-       return sp;
-}
-
-/*
- * count() counts the number of arguments/envelopes
- */
-static int count(char ** argv)
-{
-       int i=0;
-       char ** tmp;
-
-       if (tmp = argv)
-               while (get_fs_long((unsigned long *) (tmp++)))
-                       i++;
-
-       return i;
-}
-
-/*
- * 'copy_string()' copies argument/envelope strings from user
- * memory to free pages in kernel mem. These are in a format ready
- * to be put directly into the top of new user memory.
- *
- * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
- * whether the string and the string array are from user or kernel segments:
- * 
- * from_kmem     argv *        argv **
- *    0          user space    user space
- *    1          kernel space  user space
- *    2          kernel space  kernel space
- * 
- * We do this by playing games with the fs segment register.  Since it
- * it is expensive to load a segment register, we try to avoid calling
- * set_fs() unless we absolutely have to.
- */
-static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
-               unsigned long p, int from_kmem)
-{
-       char *tmp, *pag;
-       int len, offset = 0;
-       unsigned long old_fs, new_fs;
-
-       if (!p)
-               return 0;       /* bullet-proofing */
-       new_fs = get_ds();
-       old_fs = get_fs();
-       if (from_kmem==2)
-               set_fs(new_fs);
-       while (argc-- > 0) {
-               if (from_kmem == 1)
-                       set_fs(new_fs);
-               if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
-                       panic("argc is wrong");
-               if (from_kmem == 1)
-                       set_fs(old_fs);
-               len=0;          /* remember zero-padding */
-               do {
-                       len++;
-               } while (get_fs_byte(tmp++));
-               if (p-len < 0) {        /* this shouldn't happen - 128kB */
-                       set_fs(old_fs);
-                       return 0;
-               }
-               while (len) {
-                       --p; --tmp; --len;
-                       if (--offset < 0) {
-                               offset = p % PAGE_SIZE;
-                               if (from_kmem==2)
-                                       set_fs(old_fs);
-                               if (!(pag = (char *) page[p/PAGE_SIZE]) &&
-                                   !(pag = (char *) page[p/PAGE_SIZE] =
-                                     (unsigned long *) get_free_page())) 
-                                       return 0;
-                               if (from_kmem==2)
-                                       set_fs(new_fs);
-
-                       }
-                       *(pag + offset) = get_fs_byte(tmp);
-               }
-       }
-       if (from_kmem==2)
-               set_fs(old_fs);
-       return p;
-}
-
-static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
-{
-       unsigned long code_limit,data_limit,code_base,data_base;
-       int i;
-
-       code_limit = text_size+PAGE_SIZE -1;
-       code_limit &= 0xFFFFF000;
-       data_limit = 0x4000000;
-       code_base = get_base(current->ldt[1]);
-       data_base = code_base;
-       set_base(current->ldt[1],code_base);
-       set_limit(current->ldt[1],code_limit);
-       set_base(current->ldt[2],data_base);
-       set_limit(current->ldt[2],data_limit);
-/* make sure fs points to the NEW data segment */
-       __asm__("pushl $0x17\n\tpop %%fs"::);
-       data_base += data_limit;
-       for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
-               data_base -= PAGE_SIZE;
-               if (page[i])
-                       put_page(page[i],data_base);
-       }
-       return data_limit;
-}
-
-/*
- * 'do_execve()' executes a new program.
- */
-int do_execve(unsigned long * eip,long tmp,char * filename,
-       char ** argv, char ** envp)
-{
-       struct m_inode * inode;
-       struct buffer_head * bh;
-       struct exec ex;
-       unsigned long page[MAX_ARG_PAGES];
-       int i,argc,envc;
-       int e_uid, e_gid;
-       int retval;
-       int sh_bang = 0;
-       unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
-
-       if ((0xffff & eip[1]) != 0x000f)
-               panic("execve called from supervisor mode");
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-               page[i]=0;
-       if (!(inode=namei(filename)))           /* get executables inode */
-               return -ENOENT;
-       argc = count(argv);
-       envc = count(envp);
-       
-restart_interp:
-       if (!S_ISREG(inode->i_mode)) {  /* must be regular file */
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       i = inode->i_mode;
-       e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
-       e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
-       if (current->euid == inode->i_uid)
-               i >>= 6;
-       else if (current->egid == inode->i_gid)
-               i >>= 3;
-       if (!(i & 1) &&
-           !((inode->i_mode & 0111) && suser())) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       ex = *((struct exec *) bh->b_data);     /* read exec-header */
-       if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
-               /*
-                * This section does the #! interpretation.
-                * Sorta complicated, but hopefully it will work.  -TYT
-                */
-
-               char buf[1023], *cp, *interp, *i_name, *i_arg;
-               unsigned long old_fs;
-
-               strncpy(buf, bh->b_data+2, 1022);
-               brelse(bh);
-               iput(inode);
-               buf[1022] = '\0';
-               if (cp = strchr(buf, '\n')) {
-                       *cp = '\0';
-                       for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
-               }
-               if (!cp || *cp == '\0') {
-                       retval = -ENOEXEC; /* No interpreter name found */
-                       goto exec_error1;
-               }
-               interp = i_name = cp;
-               i_arg = 0;
-               for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
-                       if (*cp == '/')
-                               i_name = cp+1;
-               }
-               if (*cp) {
-                       *cp++ = '\0';
-                       i_arg = cp;
-               }
-               /*
-                * OK, we've parsed out the interpreter name and
-                * (optional) argument.
-                */
-               if (sh_bang++ == 0) {
-                       p = copy_strings(envc, envp, page, p, 0);
-                       p = copy_strings(--argc, argv+1, page, p, 0);
-               }
-               /*
-                * Splice in (1) the interpreter's name for argv[0]
-                *           (2) (optional) argument to interpreter
-                *           (3) filename of shell script
-                *
-                * This is done in reverse order, because of how the
-                * user environment and arguments are stored.
-                */
-               p = copy_strings(1, &filename, page, p, 1);
-               argc++;
-               if (i_arg) {
-                       p = copy_strings(1, &i_arg, page, p, 2);
-                       argc++;
-               }
-               p = copy_strings(1, &i_name, page, p, 2);
-               argc++;
-               if (!p) {
-                       retval = -ENOMEM;
-                       goto exec_error1;
-               }
-               /*
-                * OK, now restart the process with the interpreter's inode.
-                */
-               old_fs = get_fs();
-               set_fs(get_ds());
-               if (!(inode=namei(interp))) { /* get executables inode */
-                       set_fs(old_fs);
-                       retval = -ENOENT;
-                       goto exec_error1;
-               }
-               set_fs(old_fs);
-               goto restart_interp;
-       }
-       brelse(bh);
-       if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
-               ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
-               inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (N_TXTOFF(ex) != BLOCK_SIZE) {
-               printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!sh_bang) {
-               p = copy_strings(envc,envp,page,p,0);
-               p = copy_strings(argc,argv,page,p,0);
-               if (!p) {
-                       retval = -ENOMEM;
-                       goto exec_error2;
-               }
-       }
-/* OK, This is the point of no return */
-       for (i=0 ; i<32 ; i++)
-               current->sigaction[i].sa_handler = NULL;
-       for (i=0 ; i<NR_OPEN ; i++)
-               if ((current->close_on_exec>>i)&1)
-                       sys_close(i);
-       current->close_on_exec = 0;
-       free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
-       free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
-       current->used_math = 0;
-       p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
-       p = (unsigned long) create_tables((char *)p,argc,envc);
-       current->brk = ex.a_bss +
-               (current->end_data = ex.a_data +
-               (current->end_code = ex.a_text));
-       current->start_stack = p & 0xfffff000;
-       current->euid = e_uid;
-       current->egid = e_gid;
-       i = read_area(inode,ex.a_text+ex.a_data);
-       iput(inode);
-       if (i<0)
-               sys_exit(-1);
-       i = ex.a_text+ex.a_data;
-       while (i&0xfff)
-               put_fs_byte(0,(char *) (i++));
-       eip[0] = ex.a_entry;            /* eip, magic happens :-) */
-       eip[3] = p;                     /* stack pointer */
-       return 0;
-exec_error2:
-       iput(inode);
-exec_error1:
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)
-               free_page(page[i]);
-       return(retval);
-}
diff --git a/fs/exec.c~ b/fs/exec.c~
deleted file mode 100644 (file)
index e4b1228..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- *  linux/fs/exec.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <a.out.h>
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/segment.h>
-
-extern int sys_exit(int exit_code);
-extern int sys_close(int fd);
-
-/*
- * MAX_ARG_PAGES defines the number of pages allocated for arguments
- * and envelope for the new program. 32 should suffice, this gives
- * a maximum env+arg of 128kB !
- */
-#define MAX_ARG_PAGES 32
-
-#define cp_block(from,to) \
-__asm__("pushl $0x10\n\t" \
-       "pushl $0x17\n\t" \
-       "pop %%es\n\t" \
-       "cld\n\t" \
-       "rep\n\t" \
-       "movsl\n\t" \
-       "pop %%es" \
-       ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
-       :"cx","di","si")
-
-/*
- * read_head() reads blocks 1-6 (not 0). Block 0 has already been
- * read for header information.
- */
-int read_head(struct m_inode * inode,int blocks)
-{
-       struct buffer_head * bh;
-       int count;
-
-       if (blocks>6)
-               blocks=6;
-       for(count = 0 ; count<blocks ; count++) {
-               if (!inode->i_zone[count+1])
-                       continue;
-               if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
-                       return -1;
-               cp_block(bh->b_data,count*BLOCK_SIZE);
-               brelse(bh);
-       }
-       return 0;
-}
-
-int read_ind(int dev,int ind,long size,unsigned long offset)
-{
-       struct buffer_head * ih, * bh;
-       unsigned short * table,block;
-
-       if (size<=0)
-               panic("size<=0 in read_ind");
-       if (size>512*BLOCK_SIZE)
-               size=512*BLOCK_SIZE;
-       if (!ind)
-               return 0;
-       if (!(ih=bread(dev,ind)))
-               return -1;
-       table = (unsigned short *) ih->b_data;
-       while (size>0) {
-               if (block=*(table++))
-                       if (!(bh=bread(dev,block))) {
-                               brelse(ih);
-                               return -1;
-                       } else {
-                               cp_block(bh->b_data,offset);
-                               brelse(bh);
-                       }
-               size -= BLOCK_SIZE;
-               offset += BLOCK_SIZE;
-       }
-       brelse(ih);
-       return 0;
-}
-
-/*
- * read_area() reads an area into %fs:mem.
- */
-int read_area(struct m_inode * inode,long size)
-{
-       struct buffer_head * dind;
-       unsigned short * table;
-       int i,count;
-
-       if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
-           (size -= BLOCK_SIZE*6)<=0)
-               return i;
-       if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
-           (size -= BLOCK_SIZE*512)<=0)
-               return i;
-       if (!(i=inode->i_zone[8]))
-               return 0;
-       if (!(dind = bread(inode->i_dev,i)))
-               return -1;
-       table = (unsigned short *) dind->b_data;
-       for(count=0 ; count<512 ; count++)
-               if ((i=read_ind(inode->i_dev,*(table++),size,
-                   BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
-                       return i;
-       panic("Impossibly long executable");
-}
-
-/*
- * create_tables() parses the env- and arg-strings in new user
- * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
- */
-static unsigned long * create_tables(char * p,int argc,int envc)
-{
-       unsigned long *argv,*envp;
-       unsigned long * sp;
-
-       sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
-       sp -= envc+1;
-       envp = sp;
-       sp -= argc+1;
-       argv = sp;
-       put_fs_long((unsigned long)envp,--sp);
-       put_fs_long((unsigned long)argv,--sp);
-       put_fs_long((unsigned long)argc,--sp);
-       while (argc-->0) {
-               put_fs_long((unsigned long) p,argv++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,argv);
-       while (envc-->0) {
-               put_fs_long((unsigned long) p,envp++);
-               while (get_fs_byte(p++)) /* nothing */ ;
-       }
-       put_fs_long(0,envp);
-       return sp;
-}
-
-/*
- * count() counts the number of arguments/envelopes
- */
-static int count(char ** argv)
-{
-       int i=0;
-       char ** tmp;
-
-       if (tmp = argv)
-               while (get_fs_long((unsigned long *) (tmp++)))
-                       i++;
-
-       return i;
-}
-
-/*
- * 'copy_string()' copies argument/envelope strings from user
- * memory to free pages in kernel mem. These are in a format ready
- * to be put directly into the top of new user memory.
- */
-static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
-               unsigned long p)
-{
-       int len,i;
-       char *tmp;
-
-       while (argc-- > 0) {
-               if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
-                       panic("argc is wrong");
-               len=0;          /* remember zero-padding */
-               do {
-                       len++;
-               } while (get_fs_byte(tmp++));
-               if (p-len < 0)          /* this shouldn't happen - 128kB */
-                       return 0;
-               i = ((unsigned) (p-len)) >> 12;
-               while (i<MAX_ARG_PAGES && !page[i]) {
-                       if (!(page[i]=get_free_page()))
-                               return 0;
-                       i++;
-               }
-               do {
-                       --p;
-                       if (!page[p/PAGE_SIZE])
-                               panic("nonexistent page in exec.c");
-                       ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
-                               get_fs_byte(--tmp);
-               } while (--len);
-       }
-       return p;
-}
-
-static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
-{
-       unsigned long code_limit,data_limit,code_base,data_base;
-       int i;
-
-       code_limit = text_size+PAGE_SIZE -1;
-       code_limit &= 0xFFFFF000;
-       data_limit = 0x4000000;
-       code_base = get_base(current->ldt[1]);
-       data_base = code_base;
-       set_base(current->ldt[1],code_base);
-       set_limit(current->ldt[1],code_limit);
-       set_base(current->ldt[2],data_base);
-       set_limit(current->ldt[2],data_limit);
-/* make sure fs points to the NEW data segment */
-       __asm__("pushl $0x17\n\tpop %%fs"::);
-       data_base += data_limit;
-       for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
-               data_base -= PAGE_SIZE;
-               if (page[i])
-                       put_page(page[i],data_base);
-       }
-       return data_limit;
-}
-
-/*
- * 'do_execve()' executes a new program.
- */
-int do_execve(unsigned long * eip,long tmp,char * filename,
-       char ** argv, char ** envp)
-{
-       struct m_inode * inode;
-       struct buffer_head * bh;
-       struct exec ex;
-       unsigned long page[MAX_ARG_PAGES];
-       int i,argc,envc;
-       int e_uid, e_gid;
-       unsigned long p;
-       int retval;
-       int interp = 0;
-
-       if ((0xffff & eip[1]) != 0x000f)
-               panic("execve called from supervisor mode");
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-               page[i]=0;
-       if (!(inode=namei(filename))) {         /* get executables inode */
-               retval = -ENOENT;
-               goto exec_error1;
-       }
-       argc = count(argv);
-       envc = count(envp);
-       
-restart_interp:
-       e_uid = current->euid;  /* Note this means no setuid */
-       e_gid = current->egid;  /* shell scripts! */
-       if (!S_ISREG(inode->i_mode)) {  /* must be regular file */
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       i = inode->i_mode;
-       if (i & S_ISUID)
-               e_uid = inode->i_uid;
-       if (i & S_ISGID)
-               e_gid = inode->i_gid;
-       if (current->euid == inode->i_uid)
-               i >>= 6;
-       else if (current->egid == inode->i_gid)
-               i >>= 3;
-       if (!(i & 1) &&
-           !((inode->i_mode & 111) && suser())) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
-               retval = -EACCES;
-               goto exec_error2;
-       }
-       ex = *((struct exec *) bh->b_data);     /* read exec-header */
-       if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (interp > 3)) {
-               /*
-                * This section does the #! interpretation.
-                * Gee, I hope the C compiler is intelligent about this,
-                * and only activates this sub-frame when necessary.
-                */
-               char buf[1023], *cp, *interp, *i_name, *i_arg;
-               int len;
-
-               strncpy(buf, bh->b_data+2, 1022);
-               brelse(bh);
-               iput(inode);
-               buf[1022] = '\0';
-               if (!(cp = strchr(buf, '\n'))) {
-                       retval = -ENOEXEC;
-                       goto exec_error1;
-               }
-               *cp = '\0';
-               for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++) ;
-               if (*cp == '\0') {
-                       retval = -ENOEXEC; /* No interpreter name found */
-                       goto exec_error1;
-               }
-               interp = i_name = cp;
-               for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
-                       if (*cp == '/')
-                               i_name = cp;
-               }
-               if (*cp) {
-                       *cp++ = '\0';
-                       i_arg = cp;
-               } else
-                       i_arg = 0;
-               /*
-                * OK, we've parsed out the interpreter name and
-                * (optional) argument.
-                */
-               if (interp++ == 0) {
-                       p = copy_strings(envc,envp,page,
-                                        PAGE_SIZE*MAX_ARG_PAGES-4);
-                       p = copy_strings(--argc,argv+1,page,p);
-               }
-               /*
-                * Copy in interpreter name
-                */
-               len = strlen(i_name) + 1;
-               i = ((unsigned) (p-len)) >> 12;
-               while (i<MAX_ARG_PAGES && !page[i]) {
-                       if (!(page[i]=get_free_page())) {
-                               retval = -ENOMEM;
-                               goto exec_error1;
-                       }
-                       i++;
-               }
-               do {
-                       --p;
-                       if (!page[p/PAGE_SIZE])
-                               panic("nonexistent page in exec.c");
-                       ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
-                               i_name[--len];
-               } while (len);
-               /*
-                * OK, now restart the process with the interpreter's inode.
-                */
-               if (!(inode=namei(interpreter))) { /* get executables inode */
-                       retval = -ENOENT;
-                       goto exec_error1;
-               }
-               goto restart_interp;
-       } else
-               brelse(bh);
-       if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
-               ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
-               inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (N_TXTOFF(ex) != BLOCK_SIZE) {
-               printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
-               retval = -ENOEXEC;
-               goto exec_error2;
-       }
-       if (!interp) {
-               p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES-4);
-               p = copy_strings(argc,argv,page,p);
-       }
-       if (!p) {
-               for (i=0 ; i<MAX_ARG_PAGES ; i++)
-                       free_page(page[i]);
-               retval = -ENOMEM;
-               goto exec_error2;
-       }
-/* OK, This is the point of no return */
-       for (i=0 ; i<32 ; i++)
-               current->sigaction[i].sa_handler = NULL;
-       for (i=0 ; i<NR_OPEN ; i++)
-               if ((current->close_on_exec>>i)&1)
-                       sys_close(i);
-       current->close_on_exec = 0;
-       free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
-       free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
-       current->used_math = 0;
-       p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
-       p = (unsigned long) create_tables((char *)p,argc,envc);
-       current->brk = ex.a_bss +
-               (current->end_data = ex.a_data +
-               (current->end_code = ex.a_text));
-       current->start_stack = p & 0xfffff000;
-       current->euid = e_uid;
-       current->egid = e_gid;
-       i = read_area(inode,ex.a_text+ex.a_data);
-       iput(inode);
-       if (i<0)
-               sys_exit(-1);
-       i = ex.a_text+ex.a_data;
-       while (i&0xfff)
-               put_fs_byte(0,(char *) (i++));
-       eip[0] = ex.a_entry;            /* eip, magic happens :-) */
-       eip[3] = p;                     /* stack pointer */
-       return 0;
-exec_error2:
-       iput(inode);
-exec_error1:
-       for (i=0 ; i<MAX_ARG_PAGES ; i++)
-               free_page(page[i]);
-       return(retval);
-}
index 803347f2cd9c30158386b9257af624fb2ccecd11..85c4107107c6c8cb60b5806fbfb9816ecbef25ea 100644 (file)
@@ -40,6 +40,22 @@ static inline void unlock_inode(struct m_inode * inode)
        wake_up(&inode->i_wait);
 }
 
+void invalidate_inodes(int dev)
+{
+       int i;
+       struct m_inode * inode;
+
+       inode = 0+inode_table;
+       for(i=0 ; i<NR_INODE ; i++,inode++) {
+               wait_on_inode(inode);
+               if (inode->i_dev == dev) {
+                       if (inode->i_count)
+                               printk("inode in use on removed disk\n\r");
+                       inode->i_dev = inode->i_dirt = 0;
+               }
+       }
+}
+
 void sync_inodes(void)
 {
        int i;
@@ -148,15 +164,19 @@ void iput(struct m_inode * inode)
                inode->i_pipe=0;
                return;
        }
-       if (!inode->i_dev || inode->i_count>1) {
+       if (!inode->i_dev) {
                inode->i_count--;
                return;
        }
-repeat:
        if (S_ISBLK(inode->i_mode)) {
                sync_dev(inode->i_zone[0]);
                wait_on_inode(inode);
        }
+repeat:
+       if (inode->i_count>1) {
+               inode->i_count--;
+               return;
+       }
        if (!inode->i_nlinks) {
                truncate(inode);
                free_inode(inode);
@@ -171,40 +191,35 @@ repeat:
        return;
 }
 
-static volatile int last_allocated_inode = 0;
-
 struct m_inode * get_empty_inode(void)
 {
        struct m_inode * inode;
-       int inr;
+       static struct m_inode * last_inode = inode_table;
+       int i;
 
-       while (1) {
+       do {
                inode = NULL;
-               inr = last_allocated_inode;
-               do {
-                       if (!inode_table[inr].i_count) {
-                               inode = inr + inode_table;
-                               break;
+               for (i = NR_INODE; i ; i--) {
+                       if (++last_inode >= inode_table + NR_INODE)
+                               last_inode = inode_table;
+                       if (!last_inode->i_count) {
+                               inode = last_inode;
+                               if (!inode->i_dirt && !inode->i_lock)
+                                       break;
                        }
-                       inr++;
-                       if (inr>=NR_INODE)
-                               inr=0;
-               } while (inr != last_allocated_inode);
+               }
                if (!inode) {
-                       for (inr=0 ; inr<NR_INODE ; inr++)
-                               printk("%04x: %6d\t",inode_table[inr].i_dev,
-                                       inode_table[inr].i_num);
+                       for (i=0 ; i<NR_INODE ; i++)
+                               printk("%04x: %6d\t",inode_table[i].i_dev,
+                                       inode_table[i].i_num);
                        panic("No free inodes in mem");
                }
-               last_allocated_inode = inr;
                wait_on_inode(inode);
                while (inode->i_dirt) {
                        write_inode(inode);
                        wait_on_inode(inode);
                }
-               if (!inode->i_count)
-                       break;
-       }
+       } while (inode->i_count);
        memset(inode,0,sizeof(*inode));
        inode->i_count = 1;
        return inode;
@@ -283,7 +298,8 @@ static void read_inode(struct m_inode * inode)
        int block;
 
        lock_inode(inode);
-       sb=get_super(inode->i_dev);
+       if (!(sb=get_super(inode->i_dev)))
+               panic("trying to read inode without dev");
        block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
                (inode->i_num-1)/INODES_PER_BLOCK;
        if (!(bh=bread(inode->i_dev,block)))
@@ -302,7 +318,12 @@ static void write_inode(struct m_inode * inode)
        int block;
 
        lock_inode(inode);
-       sb=get_super(inode->i_dev);
+       if (!inode->i_dirt || !inode->i_dev) {
+               unlock_inode(inode);
+               return;
+       }
+       if (!(sb=get_super(inode->i_dev)))
+               panic("trying to write inode without device");
        block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
                (inode->i_num-1)/INODES_PER_BLOCK;
        if (!(bh=bread(inode->i_dev,block)))
index cb514a9d97df0aa5d42f7f2d778464028bbb8e26..36fc976d0bcb173f7e9e686a4a16efefbcfeed5d 100644 (file)
@@ -39,7 +39,7 @@ int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                return -EINVAL;
        dev = filp->f_inode->i_zone[0];
        if (MAJOR(dev) >= NRDEVS)
-               panic("unknown device for ioctl");
+               return -ENODEV;
        if (!ioctl_table[MAJOR(dev)])
                return -ENOTTY;
        return ioctl_table[MAJOR(dev)](dev,cmd,arg);
index cad3203744b6139d456068099cbeb7a6458f1ea0..fe2425cf7d87200e4404b9805a32b615bd2c5084 100644 (file)
@@ -4,6 +4,10 @@
  *  (C) 1991  Linus Torvalds
  */
 
+/*
+ * Some corrections by tytso.
+ */
+
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
@@ -76,7 +80,7 @@ static int match(int len,const char * name,struct dir_entry * de)
 /*
  *     find_entry()
  *
- * finds and entry in the specified directory with the wanted name. It
+ * finds an entry in the specified directory with the wanted name. It
  * returns the cache buffer in which the entry was found, and the entry
  * itself (as a parameter - res_dir). It does NOT read the inode of the
  * entry - you'll have to do that yourself if you want to.
@@ -596,18 +600,30 @@ int sys_rmdir(const char * name)
                iput(dir);
                return -ENOENT;
        }
+       if (!permission(dir,MAY_WRITE)) {
+               iput(dir);
+               return -EPERM;
+       }
        bh = find_entry(&dir,basename,namelen,&de);
        if (!bh) {
                iput(dir);
                return -ENOENT;
        }
-       if (!permission(dir,MAY_WRITE)) {
+       if (!(inode = iget(dir->i_dev, de->inode))) {
                iput(dir);
                brelse(bh);
                return -EPERM;
        }
-       if (!(inode = iget(dir->i_dev, de->inode))) {
+       if ((dir->i_mode & S_ISVTX) && current->euid &&
+           inode->i_uid != current->euid) {
                iput(dir);
+               iput(inode);
+               brelse(bh);
+               return -EPERM;
+       }
+       if (inode->i_dev != dir->i_dev || inode->i_count>1) {
+               iput(dir);
+               iput(inode);
                brelse(bh);
                return -EPERM;
        }
@@ -667,32 +683,25 @@ int sys_unlink(const char * name)
                iput(dir);
                return -ENOENT;
        }
-       inode = iget(dir->i_dev, de->inode);
-       if (!inode) {
-               printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
+       if (!(inode = iget(dir->i_dev, de->inode))) {
                iput(dir);
                brelse(bh);
                return -ENOENT;
        }
-       if (S_ISDIR(inode->i_mode)) {
-               iput(inode);
+       if ((dir->i_mode & S_ISVTX) && !suser() &&
+           current->euid != inode->i_uid &&
+           current->euid != dir->i_uid) {
                iput(dir);
+               iput(inode);
                brelse(bh);
                return -EPERM;
        }
-       /*
-        * If the directory has the sticky bit, the user must either
-        * own the file or own the directory or be the superuser to 
-        * delete a file in that directory.  This is typically used 
-        * for /tmp and /usr/tmp.
-        */
-       if ((dir->i_mode & S_ISVTX) && (current->euid != inode->i_uid) &&
-           (current->euid != dir->i_uid) && !suser()) {
+       if (S_ISDIR(inode->i_mode)) {
                iput(inode);
                iput(dir);
                brelse(bh);
                return -EPERM;
-       }               
+       }
        if (!inode->i_nlinks) {
                printk("Deleting nonexistent file (%04x:%d), %d\n",
                        inode->i_dev,inode->i_num,inode->i_nlinks);
diff --git a/fs/namei.c~ b/fs/namei.c~
deleted file mode 100644 (file)
index 11a1216..0000000
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- *  linux/fs/namei.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <const.h>
-#include <sys/stat.h>
-
-#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
-
-/*
- * comment out this line if you want names > NAME_LEN chars to be
- * truncated. Else they will be disallowed.
- */
-/* #define NO_TRUNCATE */
-
-#define MAY_EXEC 1
-#define MAY_WRITE 2
-#define MAY_READ 4
-
-/*
- *     permission()
- *
- * is used to check for read/write/execute permissions on a file.
- * I don't know if we should look at just the euid or both euid and
- * uid, but that should be easily changed.
- */
-static int permission(struct m_inode * inode,int mask)
-{
-       int mode = inode->i_mode;
-
-/* special case: not even root can read/write a deleted file */
-       if (inode->i_dev && !inode->i_nlinks)
-               return 0;
-       else if (current->euid==inode->i_uid)
-               mode >>= 6;
-       else if (current->egid==inode->i_gid)
-               mode >>= 3;
-       return mode & mask & 0007;
-}
-
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
- */
-static int match(int len,const char * name,struct dir_entry * de)
-{
-       register int same __asm__("ax");
-
-       if (!de || !de->inode || len > NAME_LEN)
-               return 0;
-       if (len < NAME_LEN && de->name[len])
-               return 0;
-       __asm__("cld\n\t"
-               "fs ; repe ; cmpsb\n\t"
-               "setz %%al"
-               :"=a" (same)
-               :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
-               :"cx","di","si");
-       return same;
-}
-
-/*
- *     find_entry()
- *
- * finds and entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- *
- * This also takes care of the few special cases due to '..'-traversal
- * over a pseudo-root and a mount point.
- */
-static struct buffer_head * find_entry(struct m_inode ** dir,
-       const char * name, int namelen, struct dir_entry ** res_dir)
-{
-       int entries;
-       int block,i;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-       struct super_block * sb;
-
-#ifdef NO_TRUNCATE
-       if (namelen > NAME_LEN)
-               return NULL;
-#else
-       if (namelen > NAME_LEN)
-               namelen = NAME_LEN;
-#endif
-       entries = (*dir)->i_size / (sizeof (struct dir_entry));
-       *res_dir = NULL;
-       if (!namelen)
-               return NULL;
-/* check for '..', as we might have to do some "magic" for it */
-       if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
-/* '..' in a pseudo-root results in a faked '.' (just change namelen) */
-               if ((*dir) == current->root)
-                       namelen=1;
-               else if ((*dir)->i_num == ROOT_INO) {
-/* '..' over a mount-point results in 'dir' being exchanged for the mounted
-   directory-inode. NOTE! We set mounted, so that we can iput the new dir */
-                       sb=get_super((*dir)->i_dev);
-                       if (sb->s_imount) {
-                               iput(*dir);
-                               (*dir)=sb->s_imount;
-                               (*dir)->i_count++;
-                       }
-               }
-       }
-       if (!(block = (*dir)->i_zone[0]))
-               return NULL;
-       if (!(bh = bread((*dir)->i_dev,block)))
-               return NULL;
-       i = 0;
-       de = (struct dir_entry *) bh->b_data;
-       while (i < entries) {
-               if ((char *)de >= BLOCK_SIZE+bh->b_data) {
-                       brelse(bh);
-                       bh = NULL;
-                       if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
-                           !(bh = bread((*dir)->i_dev,block))) {
-                               i += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (match(namelen,name,de)) {
-                       *res_dir = de;
-                       return bh;
-               }
-               de++;
-               i++;
-       }
-       brelse(bh);
-       return NULL;
-}
-
-/*
- *     add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * add_entry(struct m_inode * dir,
-       const char * name, int namelen, struct dir_entry ** res_dir)
-{
-       int block,i;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       *res_dir = NULL;
-#ifdef NO_TRUNCATE
-       if (namelen > NAME_LEN)
-               return NULL;
-#else
-       if (namelen > NAME_LEN)
-               namelen = NAME_LEN;
-#endif
-       if (!namelen)
-               return NULL;
-       if (!(block = dir->i_zone[0]))
-               return NULL;
-       if (!(bh = bread(dir->i_dev,block)))
-               return NULL;
-       i = 0;
-       de = (struct dir_entry *) bh->b_data;
-       while (1) {
-               if ((char *)de >= BLOCK_SIZE+bh->b_data) {
-                       brelse(bh);
-                       bh = NULL;
-                       block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
-                       if (!block)
-                               return NULL;
-                       if (!(bh = bread(dir->i_dev,block))) {
-                               i += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (i*sizeof(struct dir_entry) >= dir->i_size) {
-                       de->inode=0;
-                       dir->i_size = (i+1)*sizeof(struct dir_entry);
-                       dir->i_dirt = 1;
-                       dir->i_ctime = CURRENT_TIME;
-               }
-               if (!de->inode) {
-                       dir->i_mtime = CURRENT_TIME;
-                       for (i=0; i < NAME_LEN ; i++)
-                               de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
-                       bh->b_dirt = 1;
-                       *res_dir = de;
-                       return bh;
-               }
-               de++;
-               i++;
-       }
-       brelse(bh);
-       return NULL;
-}
-
-/*
- *     get_dir()
- *
- * Getdir traverses the pathname until it hits the topmost directory.
- * It returns NULL on failure.
- */
-static struct m_inode * get_dir(const char * pathname)
-{
-       char c;
-       const char * thisname;
-       struct m_inode * inode;
-       struct buffer_head * bh;
-       int namelen,inr,idev;
-       struct dir_entry * de;
-
-       if (!current->root || !current->root->i_count)
-               panic("No root inode");
-       if (!current->pwd || !current->pwd->i_count)
-               panic("No cwd inode");
-       if ((c=get_fs_byte(pathname))=='/') {
-               inode = current->root;
-               pathname++;
-       } else if (c)
-               inode = current->pwd;
-       else
-               return NULL;    /* empty name is bad */
-       inode->i_count++;
-       while (1) {
-               thisname = pathname;
-               if (!S_ISDIR(inode->i_mode) ||
-                   !(permission(inode,MAY_EXEC) || suser())) {
-                       iput(inode);
-                       return NULL;
-               }
-               for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
-                       /* nothing */ ;
-               if (!c)
-                       return inode;
-               if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
-                       iput(inode);
-                       return NULL;
-               }
-               inr = de->inode;
-               idev = inode->i_dev;
-               brelse(bh);
-               iput(inode);
-               if (!(inode = iget(idev,inr)))
-                       return NULL;
-       }
-}
-
-/*
- *     dir_namei()
- *
- * dir_namei() returns the inode of the directory of the
- * specified name, and the name within that directory.
- */
-static struct m_inode * dir_namei(const char * pathname,
-       int * namelen, const char ** name)
-{
-       char c;
-       const char * basename;
-       struct m_inode * dir;
-
-       if (!(dir = get_dir(pathname)))
-               return NULL;
-       basename = pathname;
-       while (c=get_fs_byte(pathname++))
-               if (c=='/')
-                       basename=pathname;
-       *namelen = pathname-basename-1;
-       *name = basename;
-       return dir;
-}
-
-/*
- *     namei()
- *
- * is used by most simple commands to get the inode of a specified name.
- * Open, link etc use their own routines, but this is enough for things
- * like 'chmod' etc.
- */
-struct m_inode * namei(const char * pathname)
-{
-       const char * basename;
-       int inr,dev,namelen;
-       struct m_inode * dir;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return NULL;
-       if (!namelen)                   /* special case: '/usr/' etc */
-               return dir;
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return NULL;
-       }
-       inr = de->inode;
-       dev = dir->i_dev;
-       brelse(bh);
-       iput(dir);
-       dir=iget(dev,inr);
-       if (dir) {
-               dir->i_atime=CURRENT_TIME;
-               dir->i_dirt=1;
-       }
-       return dir;
-}
-
-/*
- *     open_namei()
- *
- * namei for open - this is in fact almost the whole open-routine.
- */
-int open_namei(const char * pathname, int flag, int mode,
-       struct m_inode ** res_inode)
-{
-       const char * basename;
-       int inr,dev,namelen;
-       struct m_inode * dir, *inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
-               flag |= O_WRONLY;
-       mode &= 0777 & ~current->umask;
-       mode |= I_REGULAR;
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {                 /* special case: '/usr/' etc */
-               if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
-                       *res_inode=dir;
-                       return 0;
-               }
-               iput(dir);
-               return -EISDIR;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               if (!(flag & O_CREAT)) {
-                       iput(dir);
-                       return -ENOENT;
-               }
-               if (!(permission(dir,MAY_WRITE) || suser())) {
-                       iput(dir);
-                       return -EACCES;
-               }
-               inode = new_inode(dir->i_dev);
-               if (!inode) {
-                       iput(dir);
-                       return -ENOSPC;
-               }
-               inode->i_mode = mode;
-               inode->i_dirt = 1;
-               bh = add_entry(dir,basename,namelen,&de);
-               if (!bh) {
-                       inode->i_nlinks--;
-                       iput(inode);
-                       iput(dir);
-                       return -ENOSPC;
-               }
-               de->inode = inode->i_num;
-               bh->b_dirt = 1;
-               brelse(bh);
-               iput(dir);
-               *res_inode = inode;
-               return 0;
-       }
-       inr = de->inode;
-       dev = dir->i_dev;
-       brelse(bh);
-       iput(dir);
-       if (flag & O_EXCL)
-               return -EEXIST;
-       if (!(inode=iget(dev,inr)))
-               return -EACCES;
-       if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
-           (!(permission(inode,ACC_MODE(flag))==ACC_MODE(flag)) ||
-            suser())) {
-               iput(inode);
-               return -EPERM;
-       }
-       inode->i_atime = CURRENT_TIME;
-       if (flag & O_TRUNC)
-               truncate(inode);
-       *res_inode = inode;
-       return 0;
-}
-
-int sys_mknod(const char * filename, int mode, int dev)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-       
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(filename,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!(permission(dir,MAY_WRITE) || suser())) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               return -EEXIST;
-       }
-       inode = new_inode(dir->i_dev);
-       if (!inode) {
-               iput(dir);
-               return -ENOSPC;
-       }
-       inode->i_mode = mode;
-       if (S_ISBLK(mode) || S_ISCHR(mode))
-               inode->i_zone[0] = dev;
-       inode->i_mtime = inode->i_atime = CURRENT_TIME;
-       inode->i_dirt = 1;
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               inode->i_nlinks=0;
-               iput(inode);
-               return -ENOSPC;
-       }
-       de->inode = inode->i_num;
-       bh->b_dirt = 1;
-       iput(dir);
-       iput(inode);
-       brelse(bh);
-       return 0;
-}
-
-int sys_mkdir(const char * pathname, int mode)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh, *dir_block;
-       struct dir_entry * de;
-
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(pathname,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!(permission(dir,MAY_WRITE) || suser())) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               return -EEXIST;
-       }
-       inode = new_inode(dir->i_dev);
-       if (!inode) {
-               iput(dir);
-               return -ENOSPC;
-       }
-       inode->i_size = 32;
-       inode->i_dirt = 1;
-       inode->i_mtime = inode->i_atime = CURRENT_TIME;
-       if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
-               iput(dir);
-               inode->i_nlinks--;
-               iput(inode);
-               return -ENOSPC;
-       }
-       inode->i_dirt = 1;
-       if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
-               iput(dir);
-               free_block(inode->i_dev,inode->i_zone[0]);
-               inode->i_nlinks--;
-               iput(inode);
-               return -ERROR;
-       }
-       de = (struct dir_entry *) dir_block->b_data;
-       de->inode=inode->i_num;
-       strcpy(de->name,".");
-       de++;
-       de->inode = dir->i_num;
-       strcpy(de->name,"..");
-       inode->i_nlinks = 2;
-       dir_block->b_dirt = 1;
-       brelse(dir_block);
-       inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
-       inode->i_dirt = 1;
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               free_block(inode->i_dev,inode->i_zone[0]);
-               inode->i_nlinks=0;
-               iput(inode);
-               return -ENOSPC;
-       }
-       de->inode = inode->i_num;
-       bh->b_dirt = 1;
-       dir->i_nlinks++;
-       dir->i_dirt = 1;
-       iput(dir);
-       iput(inode);
-       brelse(bh);
-       return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct m_inode * inode)
-{
-       int nr,block;
-       int len;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       len = inode->i_size / sizeof (struct dir_entry);
-       if (len<2 || !inode->i_zone[0] ||
-           !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
-               printk("warning - bad directory on dev %04x\n",inode->i_dev);
-               return 0;
-       }
-       de = (struct dir_entry *) bh->b_data;
-       if (de[0].inode != inode->i_num || !de[1].inode || 
-           strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
-               printk("warning - bad directory on dev %04x\n",inode->i_dev);
-               return 0;
-       }
-       nr = 2;
-       de += 2;
-       while (nr<len) {
-               if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
-                       brelse(bh);
-                       block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
-                       if (!block) {
-                               nr += DIR_ENTRIES_PER_BLOCK;
-                               continue;
-                       }
-                       if (!(bh=bread(inode->i_dev,block)))
-                               return 0;
-                       de = (struct dir_entry *) bh->b_data;
-               }
-               if (de->inode) {
-                       brelse(bh);
-                       return 0;
-               }
-               de++;
-               nr++;
-       }
-       brelse(bh);
-       return 1;
-}
-
-int sys_rmdir(const char * name)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!suser())
-               return -EPERM;
-       if (!(dir = dir_namei(name,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!(permission(dir,MAY_WRITE) || suser())) {
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (!(inode = iget(dir->i_dev, de->inode))) {
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (inode == dir) {     /* we may not delete ".", but "../dir" is ok */
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOTDIR;
-       }
-       if (!empty_dir(inode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOTEMPTY;
-       }
-       if (inode->i_nlinks != 2)
-               printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
-       de->inode = 0;
-       bh->b_dirt = 1;
-       brelse(bh);
-       inode->i_nlinks=0;
-       inode->i_dirt=1;
-       dir->i_nlinks--;
-       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       dir->i_dirt=1;
-       iput(dir);
-       iput(inode);
-       return 0;
-}
-
-int sys_unlink(const char * name)
-{
-       const char * basename;
-       int namelen;
-       struct m_inode * dir, * inode;
-       struct buffer_head * bh;
-       struct dir_entry * de;
-
-       if (!(dir = dir_namei(name,&namelen,&basename)))
-               return -ENOENT;
-       if (!namelen) {
-               iput(dir);
-               return -ENOENT;
-       }
-       if (!(permission(dir,MAY_WRITE) || suser())) {
-               iput(dir);
-               return -EPERM;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               return -ENOENT;
-       }
-       inode = iget(dir->i_dev, de->inode);
-       if (!inode) {
-               printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
-               iput(dir);
-               brelse(bh);
-               return -ENOENT;
-       }
-       if (S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               iput(dir);
-               brelse(bh);
-               return -EPERM;
-       }
-       if (!inode->i_nlinks) {
-               printk("Deleting nonexistent file (%04x:%d), %d\n",
-                       inode->i_dev,inode->i_num,inode->i_nlinks);
-               inode->i_nlinks=1;
-       }
-       de->inode = 0;
-       bh->b_dirt = 1;
-       brelse(bh);
-       inode->i_nlinks--;
-       inode->i_dirt = 1;
-       inode->i_ctime = CURRENT_TIME;
-       iput(inode);
-       iput(dir);
-       return 0;
-}
-
-int sys_link(const char * oldname, const char * newname)
-{
-       struct dir_entry * de;
-       struct m_inode * oldinode, * dir;
-       struct buffer_head * bh;
-       const char * basename;
-       int namelen;
-
-       oldinode=namei(oldname);
-       if (!oldinode)
-               return -ENOENT;
-       if (S_ISDIR(oldinode->i_mode)) {
-               iput(oldinode);
-               return -EPERM;
-       }
-       dir = dir_namei(newname,&namelen,&basename);
-       if (!dir) {
-               iput(oldinode);
-               return -EACCES;
-       }
-       if (!namelen) {
-               iput(oldinode);
-               iput(dir);
-               return -EPERM;
-       }
-       if (dir->i_dev != oldinode->i_dev) {
-               iput(dir);
-               iput(oldinode);
-               return -EXDEV;
-       }
-       if (!(permission(dir,MAY_WRITE) || suser())) {
-               iput(dir);
-               iput(oldinode);
-               return -EACCES;
-       }
-       bh = find_entry(&dir,basename,namelen,&de);
-       if (bh) {
-               brelse(bh);
-               iput(dir);
-               iput(oldinode);
-               return -EEXIST;
-       }
-       bh = add_entry(dir,basename,namelen,&de);
-       if (!bh) {
-               iput(dir);
-               iput(oldinode);
-               return -ENOSPC;
-       }
-       de->inode = oldinode->i_num;
-       bh->b_dirt = 1;
-       brelse(bh);
-       iput(dir);
-       oldinode->i_nlinks++;
-       oldinode->i_ctime = CURRENT_TIME;
-       oldinode->i_dirt = 1;
-       iput(oldinode);
-       return 0;
-}
diff --git a/fs/open.c~ b/fs/open.c~
deleted file mode 100644 (file)
index afef756..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *  linux/fs/open.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <utime.h>
-#include <sys/stat.h>
-
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-
-int sys_ustat(int dev, struct ustat * ubuf)
-{
-       return -ENOSYS;
-}
-
-int sys_utime(char * filename, struct utimbuf * times)
-{
-       struct m_inode * inode;
-       long actime,modtime;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (times) {
-               actime = get_fs_long((unsigned long *) &times->actime);
-               modtime = get_fs_long((unsigned long *) &times->modtime);
-       } else
-               actime = modtime = CURRENT_TIME;
-       inode->i_atime = actime;
-       inode->i_mtime = modtime;
-       inode->i_dirt = 1;
-       iput(inode);
-       return 0;
-}
-
-int sys_access(const char * filename,int mode)
-{
-       struct m_inode * inode;
-       int res;
-
-       mode &= 0007;
-       if (!(inode=namei(filename)))
-               return -EACCES;
-       res = inode->i_mode & 0777;
-       iput(inode);
-       if (!(current->euid && current->uid))
-               if (res & 0111)
-                       res = 0777;
-               else
-                       res = 0666;
-       if (current->euid == inode->i_uid)
-               res >>= 6;
-       else if (current->egid == inode->i_gid)
-               res >>= 6;
-       if ((res & 0007 & mode) == mode)
-               return 0;
-       return -EACCES;
-}
-
-int sys_chdir(const char * filename)
-{
-       struct m_inode * inode;
-
-       if (!(inode = namei(filename)))
-               return -ENOENT;
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               return -ENOTDIR;
-       }
-       iput(current->pwd);
-       current->pwd = inode;
-       return (0);
-}
-
-int sys_chroot(const char * filename)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (!S_ISDIR(inode->i_mode)) {
-               iput(inode);
-               return -ENOTDIR;
-       }
-       iput(current->root);
-       current->root = inode;
-       return (0);
-}
-
-int sys_chmod(const char * filename,int mode)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (current->uid && current->euid)
-               if (current->uid!=inode->i_uid && current->euid!=inode->i_uid) {
-                       iput(inode);
-                       return -EACCES;
-               } else 
-                       mode = (mode & 0777) | (inode->i_mode & 07000);
-       inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
-       inode->i_dirt = 1;
-       iput(inode);
-       return 0;
-}
-
-int sys_chown(const char * filename,int uid,int gid)
-{
-       struct m_inode * inode;
-
-       if (!(inode=namei(filename)))
-               return -ENOENT;
-       if (current->uid && current->euid) {
-               iput(inode);
-               return -EACCES;
-       }
-       inode->i_uid=uid;
-       inode->i_gid=gid;
-       inode->i_dirt=1;
-       iput(inode);
-       return 0;
-}
-
-int sys_open(const char * filename,int flag,int mode)
-{
-       struct m_inode * inode;
-       struct file * f;
-       int i,fd;
-
-       mode &= 0777 & ~current->umask;
-       for(fd=0 ; fd<NR_OPEN ; fd++)
-               if (!current->filp[fd])
-                       break;
-       if (fd>=NR_OPEN)
-               return -EINVAL;
-       current->close_on_exec &= ~(1<<fd);
-       f=0+file_table;
-       for (i=0 ; i<NR_FILE ; i++,f++)
-               if (!f->f_count) break;
-       if (i>=NR_FILE)
-               return -EINVAL;
-       (current->filp[fd]=f)->f_count++;
-       if ((i=open_namei(filename,flag,mode,&inode))<0) {
-               current->filp[fd]=NULL;
-               f->f_count=0;
-               return i;
-       }
-/* ttys are somewhat special (ttyxx major==4, tty major==5) */
-       if (S_ISCHR(inode->i_mode))
-               if (MAJOR(inode->i_zone[0])==4) {
-                       if (current->leader && current->tty<0) {
-                               current->tty = MINOR(inode->i_zone[0]);
-                               tty_table[current->tty].pgrp = current->pgrp;
-                       }
-               } else if (MAJOR(inode->i_zone[0])==5)
-                       if (current->tty<0) {
-                               iput(inode);
-                               current->filp[fd]=NULL;
-                               f->f_count=0;
-                               return -EPERM;
-                       }
-/* Likewise with block-devices: check for floppy_change */
-       if (S_ISBLK(inode->i_mode))
-               check_disk_change(inode->i_zone[0]);
-       f->f_mode = inode->i_mode;
-       f->f_flags = flag;
-       f->f_count = 1;
-       f->f_inode = inode;
-       f->f_pos = 0;
-       return (fd);
-}
-
-int sys_creat(const char * pathname, int mode)
-{
-       return sys_open(pathname, O_CREAT | O_TRUNC, mode);
-}
-
-int sys_close(unsigned int fd)
-{      
-       struct file * filp;
-
-       if (fd >= NR_OPEN)
-               return -EINVAL;
-       current->close_on_exec &= ~(1<<fd);
-       if (!(filp = current->filp[fd]))
-               return -EINVAL;
-       current->filp[fd] = NULL;
-       if (filp->f_count == 0)
-               panic("Close: file count is 0");
-       if (--filp->f_count)
-               return (0);
-       iput(filp->f_inode);
-       return (0);
-}
index f8f4e3eb922cc40dff4360745bb62f9842a50197..341274acde8eb3487d54653274f90fe3217d4dd8 100644 (file)
@@ -64,7 +64,7 @@ int sys_read(unsigned int fd,char * buf,int count)
        verify_area(buf,count);
        inode = file->f_inode;
        if (inode->i_pipe)
-               return (file->f_mode&1)?read_pipe(inode,buf,count):-1;
+               return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
        if (S_ISCHR(inode->i_mode))
                return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
        if (S_ISBLK(inode->i_mode))
@@ -91,7 +91,7 @@ int sys_write(unsigned int fd,char * buf,int count)
                return 0;
        inode=file->f_inode;
        if (inode->i_pipe)
-               return (file->f_mode&2)?write_pipe(inode,buf,count):-1;
+               return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
        if (S_ISCHR(inode->i_mode))
                return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
        if (S_ISBLK(inode->i_mode))
index 25ba5b6fa9e143bd3d9f36157321cce8d0bce926..b73fdca5abe4f896365978125bef95e6d69c11fd 100644 (file)
@@ -74,6 +74,7 @@ struct super_block * get_super(int dev)
 void put_super(int dev)
 {
        struct super_block * sb;
+       struct m_inode * inode;
        int i;
 
        if (dev == ROOT_DEV) {
@@ -183,9 +184,9 @@ int sys_umount(char * dev_name)
                return -ENOENT;
        if (!sb->s_imount->i_mount)
                printk("Mounted inode has i_mount=0\n");
-       for(inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
+       for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
                if (inode->i_dev==dev && inode->i_count)
-                       return -EBUSY;
+                               return -EBUSY;
        sb->s_imount->i_mount=0;
        iput(sb->s_imount);
        sb->s_imount = NULL;
diff --git a/fs/tty_ioctl.c b/fs/tty_ioctl.c
deleted file mode 100644 (file)
index fd936dc..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  linux/fs/tty_ioctl.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <termios.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-static void flush(struct tty_queue * queue)
-{
-       cli();
-       queue->head = queue->tail;
-       sti();
-}
-
-static void wait_until_sent(struct tty_struct * tty)
-{
-       /* do nothing - not implemented */
-}
-
-static void send_break(struct tty_struct * tty)
-{
-       /* do nothing - not implemented */
-}
-
-static int get_termios(struct tty_struct * tty, struct termios * termios)
-{
-       int i;
-
-       verify_area(termios, sizeof (*termios));
-       for (i=0 ; i< (sizeof (*termios)) ; i++)
-               put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
-       return 0;
-}
-
-static int set_termios(struct tty_struct * tty, struct termios * termios)
-{
-       int i;
-
-       for (i=0 ; i< (sizeof (*termios)) ; i++)
-               ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
-       return 0;
-}
-
-static int get_termio(struct tty_struct * tty, struct termio * termio)
-{
-       int i;
-       struct termio tmp_termio;
-
-       verify_area(termio, sizeof (*termio));
-       tmp_termio.c_iflag = tty->termios.c_iflag;
-       tmp_termio.c_oflag = tty->termios.c_oflag;
-       tmp_termio.c_cflag = tty->termios.c_cflag;
-       tmp_termio.c_lflag = tty->termios.c_lflag;
-       tmp_termio.c_line = tty->termios.c_line;
-       for(i=0 ; i < NCC ; i++)
-               tmp_termio.c_cc[i] = tty->termios.c_cc[i];
-       for (i=0 ; i< (sizeof (*termio)) ; i++)
-               put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
-       return 0;
-}
-
-/*
- * This only works as the 386 is low-byt-first
- */
-static int set_termio(struct tty_struct * tty, struct termio * termio)
-{
-       int i;
-       struct termio tmp_termio;
-
-       for (i=0 ; i< (sizeof (*termio)) ; i++)
-               ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
-       *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
-       *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
-       *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
-       *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
-       tty->termios.c_line = tmp_termio.c_line;
-       for(i=0 ; i < NCC ; i++)
-               tty->termios.c_cc[i] = tmp_termio.c_cc[i];
-       return 0;
-}
-
-int tty_ioctl(int dev, int cmd, int arg)
-{
-       struct tty_struct * tty;
-       if (MAJOR(dev) == 5) {
-               dev=current->tty;
-               if (dev<0)
-                       panic("tty_ioctl: dev<0");
-       } else
-               dev=MINOR(dev);
-       tty = dev + tty_table;
-       switch (cmd) {
-               case TCGETS:
-                       return get_termios(tty,(struct termios *) arg);
-               case TCSETSF:
-                       flush(&tty->read_q); /* fallthrough */
-               case TCSETSW:
-                       wait_until_sent(tty); /* fallthrough */
-               case TCSETS:
-                       return set_termios(tty,(struct termios *) arg);
-               case TCGETA:
-                       return get_termio(tty,(struct termio *) arg);
-               case TCSETAF:
-                       flush(&tty->read_q); /* fallthrough */
-               case TCSETAW:
-                       wait_until_sent(tty); /* fallthrough */
-               case TCSETA:
-                       return set_termio(tty,(struct termio *) arg);
-               case TCSBRK:
-                       if (!arg) {
-                               wait_until_sent(tty);
-                               send_break(tty);
-                       }
-                       return 0;
-               case TCXONC:
-                       return -EINVAL; /* not implemented */
-               case TCFLSH:
-                       if (arg==0)
-                               flush(&tty->read_q);
-                       else if (arg==1)
-                               flush(&tty->write_q);
-                       else if (arg==2) {
-                               flush(&tty->read_q);
-                               flush(&tty->write_q);
-                       } else
-                               return -EINVAL;
-                       return 0;
-               case TIOCEXCL:
-                       return -EINVAL; /* not implemented */
-               case TIOCNXCL:
-                       return -EINVAL; /* not implemented */
-               case TIOCSCTTY:
-                       return -EINVAL; /* set controlling term NI */
-               case TIOCGPGRP:
-                       verify_area((void *) arg,4);
-                       put_fs_long(tty->pgrp,(unsigned long *) arg);
-                       return 0;
-               case TIOCSPGRP:
-                       tty->pgrp=get_fs_long((unsigned long *) arg);
-                       return 0;
-               case TIOCOUTQ:
-                       verify_area((void *) arg,4);
-                       put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
-                       return 0;
-               case TIOCSTI:
-                       return -EINVAL; /* not implemented */
-               case TIOCGWINSZ:
-                       return -EINVAL; /* not implemented */
-               case TIOCSWINSZ:
-                       return -EINVAL; /* not implemented */
-               case TIOCMGET:
-                       return -EINVAL; /* not implemented */
-               case TIOCMBIS:
-                       return -EINVAL; /* not implemented */
-               case TIOCMBIC:
-                       return -EINVAL; /* not implemented */
-               case TIOCMSET:
-                       return -EINVAL; /* not implemented */
-               case TIOCGSOFTCAR:
-                       return -EINVAL; /* not implemented */
-               case TIOCSSOFTCAR:
-                       return -EINVAL; /* not implemented */
-               default:
-                       return -EINVAL;
-       }
-}
diff --git a/include/RCS/ctype.h,v b/include/RCS/ctype.h,v
deleted file mode 100644 (file)
index 85b38dc..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.11.15.19.30.40;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.15.16.16.12;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Fixed bug in tolower().  Plus sign should have been a minus sign.
-@
-text
-@#ifndef _CTYPE_H
-#define _CTYPE_H
-
-#define _U     0x01    /* upper */
-#define _L     0x02    /* lower */
-#define _D     0x04    /* digit */
-#define _C     0x08    /* cntrl */
-#define _P     0x10    /* punct */
-#define _S     0x20    /* white space (space/lf/tab) */
-#define _X     0x40    /* hex digit */
-#define _SP    0x80    /* hard space (0x20) */
-
-extern unsigned char _ctype[];
-extern char _ctmp;
-
-#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D))
-#define isalpha(c) ((_ctype+1)[c]&(_U|_L))
-#define iscntrl(c) ((_ctype+1)[c]&(_C))
-#define isdigit(c) ((_ctype+1)[c]&(_D))
-#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D))
-#define islower(c) ((_ctype+1)[c]&(_L))
-#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP))
-#define ispunct(c) ((_ctype+1)[c]&(_P))
-#define isspace(c) ((_ctype+1)[c]&(_S))
-#define isupper(c) ((_ctype+1)[c]&(_U))
-#define isxdigit(c) ((_ctype+1)[c]&(_D|_X))
-
-#define isascii(c) (((unsigned) c)<=0x7f)
-#define toascii(c) (((unsigned) c)&0x7f)
-
-#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp+('a'-'A'):_ctmp)
-#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp+('A'-'a'):_ctmp)
-
-#endif
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d31 1
-a31 1
-#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp+('a'+'A'):_ctmp)
-@
diff --git a/include/asm/RCS/segment.h,v b/include/asm/RCS/segment.h,v
deleted file mode 100644 (file)
index 7543f54..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-head     1.1;
-branch   ;
-access   ;
-symbols  ;
-locks    tytso:1.1; strict;
-comment  @ * @;
-
-
-1.1
-date     91.11.25.10.43.03;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-
-1.1
-log
-@Initial revision
-@
-text
-@extern inline unsigned char get_fs_byte(const char * addr)
-{
-       unsigned register char _v;
-
-       __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
-       return _v;
-}
-
-extern inline unsigned short get_fs_word(const unsigned short *addr)
-{
-       unsigned short _v;
-
-       __asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
-       return _v;
-}
-
-extern inline unsigned long get_fs_long(const unsigned long *addr)
-{
-       unsigned long _v;
-
-       __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
-       return _v;
-}
-
-extern inline void put_fs_byte(char val,char *addr)
-{
-__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
-}
-
-extern inline void put_fs_word(short val,short * addr)
-{
-__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
-}
-
-extern inline void put_fs_long(unsigned long val,unsigned long * addr)
-{
-__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
-}
-@
index 936ed726ce081ee7fa91ad18af09d56fc96c5183..c03657f2acde87bd4b6017f877f83f24f76ef3ea 100644 (file)
@@ -41,6 +41,7 @@ __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
  * Someone who knows GNU asm better than I should double check the followig.
  * It seems to work, but I don't know if I'm doing something subtly wrong.
  * --- TYT, 11/24/91
+ * [ nothing wrong here, Linus ]
  */
 
 extern inline unsigned long get_fs() 
@@ -62,4 +63,3 @@ extern inline void set_fs(unsigned long val)
        __asm__("mov %0,%%fs"::"a" ((unsigned short) val));
 }
 
-
index ad7cb773a36b1ce2a5d16e6851402042850bd1a3..7acf55d10e427ce64361a93c0f7660fa7d5a8ff5 100644 (file)
@@ -28,7 +28,7 @@ extern char _ctmp;
 #define isascii(c) (((unsigned) c)<=0x7f)
 #define toascii(c) (((unsigned) c)&0x7f)
 
-#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp+('a'-'A'):_ctmp)
-#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp+('A'-'a'):_ctmp)
+#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp)
+#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp)
 
 #endif
diff --git a/include/ctype.h~ b/include/ctype.h~
deleted file mode 100644 (file)
index 4043d6e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _CTYPE_H
-#define _CTYPE_H
-
-#define _U     0x01    /* upper */
-#define _L     0x02    /* lower */
-#define _D     0x04    /* digit */
-#define _C     0x08    /* cntrl */
-#define _P     0x10    /* punct */
-#define _S     0x20    /* white space (space/lf/tab) */
-#define _X     0x40    /* hex digit */
-#define _SP    0x80    /* hard space (0x20) */
-
-extern unsigned char _ctype[];
-extern char _ctmp;
-
-#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D))
-#define isalpha(c) ((_ctype+1)[c]&(_U|_L))
-#define iscntrl(c) ((_ctype+1)[c]&(_C))
-#define isdigit(c) ((_ctype+1)[c]&(_D))
-#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D))
-#define islower(c) ((_ctype+1)[c]&(_L))
-#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP))
-#define ispunct(c) ((_ctype+1)[c]&(_P))
-#define isspace(c) ((_ctype+1)[c]&(_S))
-#define isupper(c) ((_ctype+1)[c]&(_U))
-#define isxdigit(c) ((_ctype+1)[c]&(_D|_X))
-
-#define isascii(c) (((unsigned) c)<=0x7f)
-#define toascii(c) (((unsigned) c)&0x7f)
-
-#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp+('a'+'A'):_ctmp)
-#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp+('A'-'a'):_ctmp)
-
-#endif
diff --git a/include/linux/RCS/kernel.h,v b/include/linux/RCS/kernel.h,v
deleted file mode 100644 (file)
index ded1106..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    tytso:1.2; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.22.22;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.08.56.53;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to Linus
-@
-text
-@/*
- * 'kernel.h' contains some often-used function prototypes etc
- */
-void verify_area(void * addr,int count);
-volatile void panic(const char * str);
-int printf(const char * fmt, ...);
-int printk(const char * fmt, ...);
-int tty_write(unsigned ch,char * buf,int count);
-
-/*
- * This is defined as a macro, but at some point this might become a
- * real subroutine that sets a flag if it returns true (to do
- * BSD-style accounting where the process is flagged if it uses root
- * privs).  The implication of this is that you should do normal
- * permissions checks first, and check suser() last.
- */
-#define suser() (current->euid == 0)
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d9 9
-@
index e515cf110d0343efc9aa164305ba970e23cb5241..b706122ceb7ba83dc50cc2455255fedbeb4e1d2e 100644 (file)
@@ -6,9 +6,17 @@
  * root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s
  */
 
-/* define your keyboard here - US (KBD_US) or Finnish (KBD_FINNISH) */
-#define KBD_US
-/* #define KBD_FINNISH */
+/*
+ * define your keyboard here -
+ * KBD_FINNISH for Finnish keyboards
+ * KBD_US for US-type
+ * KBD_GR for German keyboards
+ * KBD_FR for Frech keyboard
+ */
+/*#define KBD_US */
+/*#define KBD_GR */
+/*#define KBD_FR */
+#define KBD_FINNISH
 
 /*
  * Normally, Linux can get the drive parameters from the BIOS at
@@ -34,7 +42,7 @@
  with more than 8 heads.
 
  If you want the BIOS to tell what kind of drive you have, just
- leave HD_TYPE undefined.
+ leave HD_TYPE undefined. This is the normal thing to do.
 */
 
 #endif
index da58aecd4252a301b52deaf2f5109bd19c6726c6..7a90b10a67117a831e0f7100502701a0549cb306 100644 (file)
@@ -26,6 +26,7 @@
 #define READ 0
 #define WRITE 1
 #define READA 2                /* read-ahead - don't pause */
+#define WRITEA 3       /* "write-ahead" - silly, but somewhat useful */
 
 void buffer_init(long buffer_end);
 
@@ -66,8 +67,8 @@ typedef char buffer_block[BLOCK_SIZE];
 
 struct buffer_head {
        char * b_data;                  /* pointer to data block (1024 bytes) */
+       unsigned long b_blocknr;        /* block number */
        unsigned short b_dev;           /* device (0 = free) */
-       unsigned short b_blocknr;       /* block number */
        unsigned char b_uptodate;
        unsigned char b_dirt;           /* 0-clean,1-dirty */
        unsigned char b_count;          /* users using this block */
@@ -186,6 +187,7 @@ extern struct buffer_head * getblk(int dev, int block);
 extern void ll_rw_block(int rw, struct buffer_head * bh);
 extern void brelse(struct buffer_head * buf);
 extern struct buffer_head * bread(int dev,int block);
+extern void bread_page(unsigned long addr,int dev,int b[4]);
 extern struct buffer_head * breada(int dev,int block,...);
 extern int new_block(int dev);
 extern void free_block(int dev, int block);
index 2f2fb75d9e99b09c109e82105bfb52e4d6ae683b..cb40dd5d02a6cfaed962967f6a4e4d025b19453d 100644 (file)
@@ -6,10 +6,10 @@ volatile void panic(const char * str);
 int printf(const char * fmt, ...);
 int printk(const char * fmt, ...);
 int tty_write(unsigned ch,char * buf,int count);
-void *malloc(unsigned int len);
-void free_s(void *obj, int size);
+void * malloc(unsigned int size);
+void free_s(void * obj, int size);
 
-#define free(x)  free_s((x), 0)
+#define free(x) free_s((x), 0)
 
 /*
  * This is defined as a macro, but at some point this might become a
@@ -19,3 +19,4 @@ void free_s(void *obj, int size);
  * permissions checks first, and check suser() last.
  */
 #define suser() (current->euid == 0)
+
diff --git a/include/linux/kernel.h.orig b/include/linux/kernel.h.orig
deleted file mode 100644 (file)
index 5a7e7e9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 'kernel.h' contains some often-used function prototypes etc
- */
-void verify_area(void * addr,int count);
-volatile void panic(const char * str);
-int printf(const char * fmt, ...);
-int printk(const char * fmt, ...);
-int tty_write(unsigned ch,char * buf,int count);
-
-/*
- * This is defined as a macro, but at some point this might become a
- * real subroutine that sets a flag if it returns true (to do
- * BSD-style accounting where the process is flagged if it uses root
- * privs).  The implication of this is that you should do normal
- * permissions checks first, and check suser() last.
- */
-#define suser() (current->euid == 0)
diff --git a/include/linux/kernel.h~ b/include/linux/kernel.h~
deleted file mode 100644 (file)
index 9e533a7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * 'kernel.h' contains some often-used function prototypes etc
- */
-void verify_area(void * addr,int count);
-volatile void panic(const char * str);
-int printf(const char * fmt, ...);
-int printk(const char * fmt, ...);
-int tty_write(unsigned ch,char * buf,int count);
index f41827f3c895aee2ac15816992ab4193e9df131d..3407bb95c08e7b30c2764a803910e039a518b868 100644 (file)
@@ -27,7 +27,7 @@
 #endif
 
 extern int copy_page_tables(unsigned long from, unsigned long to, long size);
-extern int free_page_tables(unsigned long from, long size);
+extern int free_page_tables(unsigned long from, unsigned long size);
 
 extern void sched_init(void);
 extern void schedule(void);
@@ -85,7 +85,7 @@ struct task_struct {
        long blocked;   /* bitmap of masked signals */
 /* various fields */
        int exit_code;
-       unsigned long end_code,end_data,brk,start_stack;
+       unsigned long start_code,end_code,end_data,brk,start_stack;
        long pid,father,pgrp,session,leader;
        unsigned short uid,euid,suid;
        unsigned short gid,egid,sgid;
@@ -97,6 +97,7 @@ struct task_struct {
        unsigned short umask;
        struct m_inode * pwd;
        struct m_inode * root;
+       struct m_inode * executable;
        unsigned long close_on_exec;
        struct file * filp[NR_OPEN];
 /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
@@ -112,12 +113,12 @@ struct task_struct {
 #define INIT_TASK \
 /* state etc */        { 0,15,15, \
 /* signals */  0,{{},},0, \
-/* ec,brk... */        0,0,0,0,0, \
+/* ec,brk... */        0,0,0,0,0,0, \
 /* pid etc.. */        0,-1,0,0,0, \
 /* uid etc */  0,0,0,0,0,0, \
 /* alarm */    0,0,0,0,0,0, \
 /* math */     0, \
-/* fs info */  -1,0022,NULL,NULL,0, \
+/* fs info */  -1,0022,NULL,NULL,NULL,0, \
 /* filp */     {NULL,}, \
        { \
                {0,0}, \
index 33f172cc28baa33d11ba62c658f6bb7793e8bae3..c538fc1d97d1a43019c03ee787cce69c297be4d5 100644 (file)
@@ -68,6 +68,8 @@ extern int sys_setsid();
 extern int sys_sigaction();
 extern int sys_sgetmask();
 extern int sys_ssetmask();
+extern int sys_setreuid();
+extern int sys_setregid();
 
 fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
 sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
@@ -80,4 +82,5 @@ sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
 sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
 sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
 sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
-sys_getpgrp,sys_setsid,sys_sigaction,sys_sgetmask,sys_ssetmask };
+sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
+sys_setreuid,sys_setregid };
index f70767419203978651c5e1a7329622c196fd5450..2b7b91366fedcce281bf0146e41172f97172b99b 100644 (file)
@@ -31,6 +31,7 @@
 #define TIOCMSET       0x5418
 #define TIOCGSOFTCAR   0x5419
 #define TIOCSSOFTCAR   0x541A
+#define TIOCINQ                0x541B
 
 struct winsize {
        unsigned short ws_row;
@@ -145,6 +146,8 @@ struct termios {
 #define  B9600 0000015
 #define  B19200        0000016
 #define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
 #define CSIZE  0000060
 #define   CS5  0000000
 #define   CS6  0000020
@@ -159,6 +162,9 @@ struct termios {
 #define CIBAUD 03600000                /* input baud rate (not used) */
 #define CRTSCTS        020000000000            /* flow control */
 
+#define PARENB CPARENB
+#define PARODD CPARODD
+
 /* c_lflag bits */
 #define ISIG   0000001
 #define ICANON 0000002
index 441836347cd425dacd5b61c8ce9a7d7750fbc591..bf71dcb2f8a4bf8d358a3834666a5e3ac1b70c11 100644 (file)
@@ -5,7 +5,7 @@
 #define _POSIX_VERSION 198808L
 
 #define _POSIX_CHOWN_RESTRICTED        /* only root can do a chown (I think..) */
-/* #define _POSIX_NO_TRUNC*/   /* pathname truncation (but see in kernel) */
+#define _POSIX_NO_TRUNC                /* no pathname truncation (but see in kernel) */
 #define _POSIX_VDISABLE '\0'   /* character to disable things like ^C */
 /*#define _POSIX_SAVED_IDS */  /* we'll get to this yet */
 /*#define _POSIX_JOB_CONTROL */        /* we aren't there quite yet. Soon hopefully */
 #define __NR_getpgrp   65
 #define __NR_setsid    66
 #define __NR_sigaction 67
+#define __NR_sgetmask  68
+#define __NR_ssetmask  69
+#define __NR_setreuid  70
+#define __NR_setregid  71
 
 #define _syscall0(type,name) \
 type name(void) \
 { \
-type __res; \
+long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name)); \
 if (__res >= 0) \
-       return __res; \
+       return (type) __res; \
 errno = -__res; \
 return -1; \
 }
@@ -142,12 +146,12 @@ return -1; \
 #define _syscall1(type,name,atype,a) \
 type name(atype a) \
 { \
-type __res; \
+long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" (a)); \
+       : "0" (__NR_##name),"b" ((long)(a))); \
 if (__res >= 0) \
-       return __res; \
+       return (type) __res; \
 errno = -__res; \
 return -1; \
 }
@@ -155,12 +159,12 @@ return -1; \
 #define _syscall2(type,name,atype,a,btype,b) \
 type name(atype a,btype b) \
 { \
-type __res; \
+long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" (a),"c" (b)); \
+       : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
 if (__res >= 0) \
-       return __res; \
+       return (type) __res; \
 errno = -__res; \
 return -1; \
 }
@@ -168,13 +172,14 @@ return -1; \
 #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
 type name(atype a,btype b,ctype c) \
 { \
-type __res; \
+long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" (a),"c" (b),"d" (c)); \
-if (__res<0) \
-       errno=-__res , __res = -1; \
-return __res;\
+       : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
+if (__res>=0) \
+       return (type) __res; \
+errno=-__res; \
+return -1; \
 }
 
 #endif /* __LIBRARY__ */
index ce55e24d98c550cca248309101a44a81c1ad1fa0..25de9e0d70fc8afa911f000545f36f89f15de4d2 100644 (file)
@@ -48,6 +48,7 @@ extern void chr_dev_init(void);
 extern void hd_init(void);
 extern void floppy_init(void);
 extern void mem_init(long start, long end);
+extern long rd_init(long mem_start, int length);
 extern long kernel_mktime(struct tm * tm);
 extern long startup_time;
 
@@ -96,6 +97,7 @@ static void time_init(void)
 
 static long memory_end = 0;
 static long buffer_memory_end = 0;
+static long main_memory_start = 0;
 
 struct drive_info { char dummy[32]; } drive_info;
 
@@ -111,11 +113,17 @@ void main(void)           /* This really IS void, no error here. */
        memory_end &= 0xfffff000;
        if (memory_end > 16*1024*1024)
                memory_end = 16*1024*1024;
-       if (memory_end > 6*1024*1024)
+       if (memory_end > 12*1024*1024) 
+               buffer_memory_end = 4*1024*1024;
+       else if (memory_end > 6*1024*1024)
                buffer_memory_end = 2*1024*1024;
        else
                buffer_memory_end = 1*1024*1024;
-       mem_init(buffer_memory_end,memory_end);
+       main_memory_start = buffer_memory_end;
+#ifdef RAMDISK
+       main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
+#endif
+       mem_init(main_memory_start,memory_end);
        trap_init();
        blk_dev_init();
        chr_dev_init();
@@ -151,35 +159,51 @@ static int printf(const char *fmt, ...)
        return i;
 }
 
+static char * argv_rc[] = { "/bin/sh", NULL };
+static char * envp_rc[] = { "HOME=/", NULL };
+
 static char * argv[] = { "-/bin/sh",NULL };
 static char * envp[] = { "HOME=/usr/root", NULL };
 
 void init(void)
 {
-       int i,j;
+       int pid,i;
 
        setup((void *) &drive_info);
-       if (!fork())
-               _exit(execve("/bin/update",NULL,NULL));
        (void) open("/dev/tty0",O_RDWR,0);
        (void) dup(0);
        (void) dup(0);
        printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
                NR_BUFFERS*BLOCK_SIZE);
-       printf("Free mem: %d bytes\n\r",memory_end-buffer_memory_end);
-       printf(" Ok.\n\r");
-       if ((i=fork())<0)
-               printf("Fork failed in init\r\n");
-       else if (!i) {
-               close(0);close(1);close(2);
-               setsid();
-               (void) open("/dev/tty0",O_RDWR,0);
-               (void) dup(0);
-               (void) dup(0);
-               _exit(execve("/bin/sh",argv,envp));
+       printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
+       if (!(pid=fork())) {
+               close(0);
+               if (open("/etc/rc",O_RDONLY,0))
+                       _exit(1);
+               execve("/bin/sh",argv_rc,envp_rc);
+               _exit(2);
+       }
+       if (pid>0)
+               while (pid != wait(&i))
+                       /* nothing */;
+       while (1) {
+               if ((pid=fork())<0) {
+                       printf("Fork failed in init\r\n");
+                       continue;
+               }
+               if (!pid) {
+                       close(0);close(1);close(2);
+                       setsid();
+                       (void) open("/dev/tty0",O_RDWR,0);
+                       (void) dup(0);
+                       (void) dup(0);
+                       _exit(execve("/bin/sh",argv,envp));
+               }
+               while (1)
+                       if (pid == wait(&i))
+                               break;
+               printf("\n\rchild %d died with code %04x\n\r",pid,i);
+               sync();
        }
-       j=wait(&i);
-       printf("child %d died with code %04x\n",j,i);
-       sync();
        _exit(0);       /* NOTE! _exit, not exit() */
 }
index d75e141fcb22ee314ad1713d683b1d8fb4c7875f..07d7f61566cb694d5b2eae196e93c1069f021ee2 100644 (file)
@@ -37,6 +37,7 @@ clean:
        for i in *.c;do rm -f `basename $$i .c`.s;done
        (cd chr_drv; make clean)
        (cd blk_drv; make clean)
+       (cd math; make clean)
 
 dep:
        sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
diff --git a/kernel/RCS/exit.c,v b/kernel/RCS/exit.c,v
deleted file mode 100644 (file)
index ae8e8b1..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-head     1.3;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.3
-date     91.12.01.09.21.46;  author tytso;  state Exp;
-branches ;
-next     1.2;
-
-1.2
-date     91.11.20.00.10.00;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.16.21.02.17;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.3
-log
-@Patches sent to Linus
-@
-text
-@/*
- *  linux/kernel/exit.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <asm/segment.h>
-
-int sys_pause(void);
-int sys_close(int fd);
-
-void release(struct task_struct * p)
-{
-       int i;
-
-       if (!p)
-               return;
-       for (i=1 ; i<NR_TASKS ; i++)
-               if (task[i]==p) {
-                       task[i]=NULL;
-                       free_page((long)p);
-                       schedule();
-                       return;
-               }
-       panic("trying to release non-existent task");
-}
-
-static inline int send_sig(long sig,struct task_struct * p,int priv)
-{
-       if (!p || sig<1 || sig>32)
-               return -EINVAL;
-       if (priv || (current->euid==p->euid) || suser())
-               p->signal |= (1<<(sig-1));
-       else
-               return -EPERM;
-       return 0;
-}
-
-static void kill_session(void)
-{
-       struct task_struct **p = NR_TASKS + task;
-       
-       while (--p > &FIRST_TASK) {
-               if (*p && (*p)->session == current->session)
-                       (*p)->signal |= 1<<(SIGHUP-1);
-       }
-}
-
-/*
- * XXX need to check permissions needed to send signals to process
- * groups, etc. etc.  kill() permissions semantics are tricky!
- */
-int sys_kill(int pid,int sig)
-{
-       struct task_struct **p = NR_TASKS + task;
-       int err, retval = 0;
-
-       if (!pid) while (--p > &FIRST_TASK) {
-               if (*p && (*p)->pgrp == current->pid) 
-                       if (err=send_sig(sig,*p,1))
-                               retval = err;
-       } else if (pid>0) while (--p > &FIRST_TASK) {
-               if (*p && (*p)->pid == pid) 
-                       if (err=send_sig(sig,*p,0))
-                               retval = err;
-       } else if (pid == -1) while (--p > &FIRST_TASK)
-               if (err = send_sig(sig,*p,0))
-                       retval = err;
-       else while (--p > &FIRST_TASK)
-               if (*p && (*p)->pgrp == -pid)
-                       if (err = send_sig(sig,*p,0))
-                               retval = err;
-       return retval;
-}
-
-static void tell_father(int pid)
-{
-       int i;
-
-       if (pid)
-               for (i=0;i<NR_TASKS;i++) {
-                       if (!task[i])
-                               continue;
-                       if (task[i]->pid != pid)
-                               continue;
-                       task[i]->signal |= (1<<(SIGCHLD-1));
-                       return;
-               }
-/* if we don't find any fathers, we just release ourselves */
-       release(current);
-}
-
-int do_exit(long code)
-{
-       int i;
-
-       free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
-       free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
-       for (i=0 ; i<NR_TASKS ; i++)
-               if (task[i] && task[i]->father == current->pid)
-                       task[i]->father = 0;
-       for (i=0 ; i<NR_OPEN ; i++)
-               if (current->filp[i])
-                       sys_close(i);
-       iput(current->pwd);
-       current->pwd=NULL;
-       iput(current->root);
-       current->root=NULL;
-       if (current->leader && current->tty >= 0)
-               tty_table[current->tty].pgrp = 0;
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
-       if (current->leader)
-               kill_session();
-       current->state = TASK_ZOMBIE;
-       current->exit_code = code;
-       tell_father(current->father);
-       schedule();
-       return (-1);    /* just to suppress warnings */
-}
-
-int sys_exit(int error_code)
-{
-       return do_exit((error_code&0xff)<<8);
-}
-
-int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
-{
-       int flag;
-       struct task_struct ** p;
-
-       verify_area(stat_addr,4);
-repeat:
-       flag=0;
-       for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
-               if (!*p || *p == current)
-                       continue;
-               if ((*p)->father != current->pid)
-                       continue;
-               if (pid>0) {
-                       if ((*p)->pid != pid)
-                               continue;
-               } else if (!pid) {
-                       if ((*p)->pgrp != current->pgrp)
-                               continue;
-               } else if (pid != -1) {
-                       if ((*p)->pgrp != -pid)
-                               continue;
-               }
-               switch ((*p)->state) {
-                       case TASK_STOPPED:
-                               if (!(options & WUNTRACED))
-                                       continue;
-                               put_fs_long(0x7f,stat_addr);
-                               return (*p)->pid;
-                       case TASK_ZOMBIE:
-                               current->cutime += (*p)->utime;
-                               current->cstime += (*p)->stime;
-                               flag = (*p)->pid;
-                               put_fs_long((*p)->exit_code,stat_addr);
-                               release(*p);
-                               return flag;
-                       default:
-                               flag=1;
-                               continue;
-               }
-       }
-       if (flag) {
-               if (options & WNOHANG)
-                       return 0;
-               current->state=TASK_INTERRUPTIBLE;
-               schedule();
-               if (!(current->signal &= ~(1<<(SIGCHLD-1))))
-                       goto repeat;
-               else
-                       return -EINTR;
-       }
-       return -ECHILD;
-}
-
-
-@
-
-
-1.2
-log
-@Fixed bug in waitpid() so that the proper exit code would be returned.
-@
-text
-@d35 1
-a35 1
-static inline void send_sig(long sig,struct task_struct * p,int priv)
-d38 2
-a39 6
-               return;
-       if (priv ||
-               current->uid==p->uid ||
-               current->euid==p->uid ||
-               current->uid==p->euid ||
-               current->euid==p->euid)
-d41 3
-d49 1
-a49 1
-
-d56 5
-a60 1
-void do_kill(long pid,long sig,int priv)
-d63 1
-d66 3
-a68 2
-               if (*p && (*p)->pgrp == current->pid)
-                       send_sig(sig,*p,priv);
-d70 3
-a72 2
-               if (*p && (*p)->pid == pid)
-                       send_sig(sig,*p,priv);
-d74 2
-a75 1
-               send_sig(sig,*p,priv);
-d78 3
-a80 7
-                       send_sig(sig,*p,priv);
-}
-
-int sys_kill(int pid,int sig)
-{
-       do_kill(pid,sig,!(current->uid || current->euid));
-       return 0;
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d164 1
-a165 1
-                               put_fs_long((*p)->exit_code,stat_addr);
-@
diff --git a/kernel/RCS/sched.c,v b/kernel/RCS/sched.c,v
deleted file mode 100644 (file)
index a57ab92..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.21.22;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.08.47.30;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to linus
-@
-text
-@/*
- *  linux/kernel/sched.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- * 'sched.c' is the main kernel file. It contains scheduling primitives
- * (sleep_on, wakeup, schedule etc) as well as a number of simple system
- * call functions (type getpid(), which just extracts a field from
- * current-task
- */
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/sys.h>
-#include <linux/fdreg.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-
-#include <signal.h>
-
-#define _S(nr) (1<<((nr)-1))
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-
-void show_task(int nr,struct task_struct * p)
-{
-       printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
-       printk("eip=%04x:%08x\n\r",p->tss.cs&0xffff,p->tss.eip);
-}
-
-void show_stat(void)
-{
-       int i;
-
-       for (i=0;i<NR_TASKS;i++)
-               if (task[i])
-                       show_task(i,task[i]);
-}
-
-#define LATCH (1193180/HZ)
-
-extern void mem_use(void);
-
-extern int timer_interrupt(void);
-extern int system_call(void);
-
-union task_union {
-       struct task_struct task;
-       char stack[PAGE_SIZE];
-};
-
-static union task_union init_task = {INIT_TASK,};
-
-long volatile jiffies=0;
-long startup_time=0;
-struct task_struct *current = &(init_task.task);
-struct task_struct *last_task_used_math = NULL;
-
-struct task_struct * task[NR_TASKS] = {&(init_task.task), };
-
-long user_stack [ PAGE_SIZE>>2 ] ;
-
-struct {
-       long * a;
-       short b;
-       } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
-/*
- *  'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task
- */
-void math_state_restore()
-{
-       if (last_task_used_math == current)
-               return;
-       if (last_task_used_math) {
-               __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
-       }
-       if (current->used_math) {
-               __asm__("frstor %0"::"m" (current->tss.i387));
-       } else {
-               __asm__("fninit"::);
-               current->used_math=1;
-       }
-       last_task_used_math=current;
-}
-
-/*
- *  'schedule()' is the scheduler function. This is GOOD CODE! There
- * probably won't be any reason to change this, as it should work well
- * in all circumstances (ie gives IO-bound processes good response etc).
- * The one thing you might take a look at is the signal-handler code here.
- *
- *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other
- * tasks can run. It can not be killed, and it cannot sleep. The 'state'
- * information in task[0] is never used.
- */
-void schedule(void)
-{
-       int i,next,c;
-       struct task_struct ** p;
-
-/* check alarm, wake up any interruptible tasks that have got a signal */
-
-       for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
-               if (*p) {
-                       if ((*p)->alarm && (*p)->alarm < jiffies) {
-                                       (*p)->signal |= (1<<(SIGALRM-1));
-                                       (*p)->alarm = 0;
-                               }
-                       if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
-                       (*p)->state==TASK_INTERRUPTIBLE)
-                               (*p)->state=TASK_RUNNING;
-               }
-
-/* this is the scheduler proper: */
-
-       while (1) {
-               c = -1;
-               next = 0;
-               i = NR_TASKS;
-               p = &task[NR_TASKS];
-               while (--i) {
-                       if (!*--p)
-                               continue;
-                       if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
-                               c = (*p)->counter, next = i;
-               }
-               if (c) break;
-               for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
-                       if (*p)
-                               (*p)->counter = ((*p)->counter >> 1) +
-                                               (*p)->priority;
-       }
-       switch_to(next);
-}
-
-int sys_pause(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       return 0;
-}
-
-void sleep_on(struct task_struct **p)
-{
-       struct task_struct *tmp;
-
-       if (!p)
-               return;
-       if (current == &(init_task.task))
-               panic("task[0] trying to sleep");
-       tmp = *p;
-       *p = current;
-       current->state = TASK_UNINTERRUPTIBLE;
-       schedule();
-       if (tmp)
-               tmp->state=0;
-}
-
-void interruptible_sleep_on(struct task_struct **p)
-{
-       struct task_struct *tmp;
-
-       if (!p)
-               return;
-       if (current == &(init_task.task))
-               panic("task[0] trying to sleep");
-       tmp=*p;
-       *p=current;
-repeat:        current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       if (*p && *p != current) {
-               (**p).state=0;
-               goto repeat;
-       }
-       *p=NULL;
-       if (tmp)
-               tmp->state=0;
-}
-
-void wake_up(struct task_struct **p)
-{
-       if (p && *p) {
-               (**p).state=0;
-               *p=NULL;
-       }
-}
-
-/*
- * OK, here are some floppy things that shouldn't be in the kernel
- * proper. They are here because the floppy needs a timer, and this
- * was the easiest way of doing it.
- */
-static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
-static int  mon_timer[4]={0,0,0,0};
-static int moff_timer[4]={0,0,0,0};
-unsigned char current_DOR = 0x0C;
-unsigned char selected = 0;
-struct task_struct * wait_on_floppy_select = NULL;
-
-void floppy_select(unsigned int nr)
-{
-       if (nr>3)
-               printk("floppy_select: nr>3\n\r");
-       cli();
-       while (selected)
-               sleep_on(&wait_on_floppy_select);
-       current_DOR &= 0xFC;
-       current_DOR |= nr;
-       outb(current_DOR,FD_DOR);
-       sti();
-}
-
-void floppy_deselect(unsigned int nr)
-{
-       if (nr != (current_DOR & 3))
-               printk("floppy_deselect: drive not selected\n\r");
-       selected = 0;
-       wake_up(&wait_on_floppy_select);
-}
-
-int ticks_to_floppy_on(unsigned int nr)
-{
-       unsigned char mask = 1<<(nr+4);
-
-       if (nr>3)
-               panic("floppy_on: nr>3");
-       moff_timer[nr]=10000;           /* 100 s = very big :-) */
-       cli();                          /* use floppy_off to turn it off */
-       if (!(mask & current_DOR)) {
-               current_DOR |= mask;
-               if (!selected) {
-                       current_DOR &= 0xFC;
-                       current_DOR |= nr;
-               }
-               outb(current_DOR,FD_DOR);
-               mon_timer[nr] = HZ;
-       }
-       sti();
-       return mon_timer[nr];
-}
-
-void floppy_on(unsigned int nr)
-{
-       cli();
-       while (ticks_to_floppy_on(nr))
-               sleep_on(nr+wait_motor);
-       sti();
-}
-
-void floppy_off(unsigned int nr)
-{
-       moff_timer[nr]=3*HZ;
-}
-
-void do_floppy_timer(void)
-{
-       int i;
-       unsigned char mask = 0x10;
-
-       for (i=0 ; i<4 ; i++,mask <<= 1) {
-               if (!(mask & current_DOR))
-                       continue;
-               if (mon_timer[i]) {
-                       if (!--mon_timer[i])
-                               wake_up(i+wait_motor);
-               } else if (!moff_timer[i]) {
-                       current_DOR &= ~mask;
-                       outb(current_DOR,FD_DOR);
-               } else
-                       moff_timer[i]--;
-       }
-}
-
-#define TIME_REQUESTS 64
-
-static struct timer_list {
-       long jiffies;
-       void (*fn)();
-       struct timer_list * next;
-} timer_list[TIME_REQUESTS], * next_timer = NULL;
-
-void add_timer(long jiffies, void (*fn)(void))
-{
-       struct timer_list * p;
-
-       if (!fn)
-               return;
-       cli();
-       if (jiffies <= 0)
-               (fn)();
-       else {
-               for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
-                       if (!p->fn)
-                               break;
-               if (p >= timer_list + TIME_REQUESTS)
-                       panic("No more time requests free");
-               p->fn = fn;
-               p->jiffies = jiffies;
-               p->next = next_timer;
-               next_timer = p;
-               while (p->next && p->next->jiffies < p->jiffies) {
-                       p->jiffies -= p->next->jiffies;
-                       fn = p->fn;
-                       p->fn = p->next->fn;
-                       p->next->fn = fn;
-                       jiffies = p->jiffies;
-                       p->jiffies = p->next->jiffies;
-                       p->next->jiffies = jiffies;
-                       p = p->next;
-               }
-       }
-       sti();
-}
-
-void do_timer(long cpl)
-{
-       if (cpl)
-               current->utime++;
-       else
-               current->stime++;
-       if (next_timer) {
-               next_timer->jiffies--;
-               while (next_timer && next_timer->jiffies <= 0) {
-                       void (*fn)(void);
-                       
-                       fn = next_timer->fn;
-                       next_timer->fn = NULL;
-                       next_timer = next_timer->next;
-                       (fn)();
-               }
-       }
-       if (current_DOR & 0xf0)
-               do_floppy_timer();
-       if ((--current->counter)>0) return;
-       current->counter=0;
-       if (!cpl) return;
-       schedule();
-}
-
-int sys_alarm(long seconds)
-{
-       int old = current->alarm;
-
-       if (old)
-               old = (old - jiffies) / HZ;
-       current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
-       return (old);
-}
-
-int sys_getpid(void)
-{
-       return current->pid;
-}
-
-int sys_getppid(void)
-{
-       return current->father;
-}
-
-int sys_getuid(void)
-{
-       return current->uid;
-}
-
-int sys_geteuid(void)
-{
-       return current->euid;
-}
-
-int sys_getgid(void)
-{
-       return current->gid;
-}
-
-int sys_getegid(void)
-{
-       return current->egid;
-}
-
-int sys_nice(long increment)
-{
-       if (current->priority-increment>0)
-               current->priority -= increment;
-       return 0;
-}
-
-void sched_init(void)
-{
-       int i;
-       struct desc_struct * p;
-
-       if (sizeof(struct sigaction) != 16)
-               panic("Struct sigaction MUST be 16 bytes");
-       set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
-       set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
-       p = gdt+2+FIRST_TSS_ENTRY;
-       for(i=1;i<NR_TASKS;i++) {
-               task[i] = NULL;
-               p->a=p->b=0;
-               p++;
-               p->a=p->b=0;
-               p++;
-       }
-       ltr(0);
-       lldt(0);
-       outb_p(0x36,0x43);              /* binary, mode 3, LSB/MSB, ch 0 */
-       outb_p(LATCH & 0xff , 0x40);    /* LSB */
-       outb(LATCH >> 8 , 0x40);        /* MSB */
-       set_intr_gate(0x20,&timer_interrupt);
-       outb(inb_p(0x21)&~0x01,0x21);
-       set_system_gate(0x80,&system_call);
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d344 4
-d349 1
-a349 1
-       return seconds;
-@
diff --git a/kernel/RCS/sys.c,v b/kernel/RCS/sys.c,v
deleted file mode 100644 (file)
index 9d4c1cf..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.12.01.09.21.30;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.21.09.18.36;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Patches sent to linus
-@
-text
-@/*
- *  linux/kernel/sys.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-#include <sys/times.h>
-#include <sys/utsname.h>
-
-int sys_ftime()
-{
-       return -ENOSYS;
-}
-
-int sys_break()
-{
-       return -ENOSYS;
-}
-
-int sys_ptrace()
-{
-       return -ENOSYS;
-}
-
-int sys_stty()
-{
-       return -ENOSYS;
-}
-
-int sys_gtty()
-{
-       return -ENOSYS;
-}
-
-int sys_rename()
-{
-       return -ENOSYS;
-}
-
-int sys_prof()
-{
-       return -ENOSYS;
-}
-
-int sys_setregid(int rgid, int egid)
-{
-       if (rgid>0) {
-               if ((current->gid == rgid) || 
-                   suser())
-                       current->gid = rgid;
-               else
-                       return(-EPERM);
-       }
-       if (egid>0) {
-               if ((current->gid == egid) ||
-                   (current->egid == egid) ||
-                   (current->sgid == egid) ||
-                   suser())
-                       current->egid = egid;
-               else
-                       return(-EPERM);
-       }
-       return 0;
-}
-
-int sys_setgid(int gid)
-{
-       return(sys_setregid(gid, gid));
-}
-
-int sys_acct()
-{
-       return -ENOSYS;
-}
-
-int sys_phys()
-{
-       return -ENOSYS;
-}
-
-int sys_lock()
-{
-       return -ENOSYS;
-}
-
-int sys_mpx()
-{
-       return -ENOSYS;
-}
-
-int sys_ulimit()
-{
-       return -ENOSYS;
-}
-
-int sys_time(long * tloc)
-{
-       int i;
-
-       i = CURRENT_TIME;
-       if (tloc) {
-               verify_area(tloc,4);
-               put_fs_long(i,(unsigned long *)tloc);
-       }
-       return i;
-}
-
-/*
- * Unprivileged users may change the real user id to the effective uid
- * or vice versa.
- */
-int sys_setreuid(int ruid, int euid)
-{
-       int old_ruid = current->uid;
-       
-       if (ruid>0) {
-               if ((current->euid==ruid) ||
-                    (old_ruid == ruid) ||
-                   suser())
-                       current->uid = ruid;
-               else
-                       return(-EPERM);
-       }
-       if (euid>0) {
-               if ((old_ruid == euid) ||
-                    (current->euid == euid) ||
-                   suser())
-                       current->euid = euid;
-               else {
-                       current->uid = old_ruid;
-                       return(-EPERM);
-               }
-       }
-       return 0;
-}
-
-int sys_setuid(int uid)
-{
-       return(sys_setreuid(uid, uid));
-}
-
-int sys_stime(long * tptr)
-{
-       if (!suser())
-               return -EPERM;
-       startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
-       return 0;
-}
-
-int sys_times(struct tms * tbuf)
-{
-       if (tbuf) {
-               verify_area(tbuf,sizeof *tbuf);
-               put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
-               put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
-               put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
-               put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
-       }
-       return jiffies;
-}
-
-int sys_brk(unsigned long end_data_seg)
-{
-       if (end_data_seg >= current->end_code &&
-           end_data_seg < current->start_stack - 16384)
-               current->brk = end_data_seg;
-       return current->brk;
-}
-
-/*
- * This needs some heave checking ...
- * I just haven't get the stomach for it. I also don't fully
- * understand sessions/pgrp etc. Let somebody who does explain it.
- */
-int sys_setpgid(int pid, int pgid)
-{
-       int i;
-
-       if (!pid)
-               pid = current->pid;
-       if (!pgid)
-               pgid = current->pid;
-       for (i=0 ; i<NR_TASKS ; i++)
-               if (task[i] && task[i]->pid==pid) {
-                       if (task[i]->leader)
-                               return -EPERM;
-                       if (task[i]->session != current->session)
-                               return -EPERM;
-                       task[i]->pgrp = pgid;
-                       return 0;
-               }
-       return -ESRCH;
-}
-
-int sys_getpgrp(void)
-{
-       return current->pgrp;
-}
-
-int sys_setsid(void)
-{
-       if (current->leader && !suser())
-               return -EPERM;
-       current->leader = 1;
-       current->session = current->pgrp = current->pid;
-       current->tty = -1;
-       return current->pgrp;
-}
-
-int sys_uname(struct utsname * name)
-{
-       static struct utsname thisname = {
-               "linux .0","nodename","release ","version ","machine "
-       };
-       int i;
-
-       if (!name) return -ERROR;
-       verify_area(name,sizeof *name);
-       for(i=0;i<sizeof *name;i++)
-               put_fs_byte(((char *) &thisname)[i],i+(char *) name);
-       return 0;
-}
-
-int sys_umask(int mask)
-{
-       int old = current->umask;
-
-       current->umask = mask & 0777;
-       return (old);
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d51 1
-a51 1
-int sys_setgid(int gid)
-d53 4
-a56 3
-       if (current->euid && current->uid)
-               if (current->gid==gid || current->sgid==gid)
-                       current->egid = gid;
-d58 11
-a68 3
-                       return -EPERM;
-       else
-               current->gid = current->egid = gid;
-d72 5
-d114 5
-a118 1
-int sys_setuid(int uid)
-d120 7
-a126 3
-       if (current->euid && current->uid)
-               if (uid==current->uid || current->suid==current->uid)
-                       current->euid=uid;
-d128 12
-a139 3
-                       return -EPERM;
-       else
-               current->euid=current->uid=uid;
-d143 5
-d150 1
-a150 1
-       if (current->euid && current->uid)
-d208 1
-a208 3
-       if (current->uid && current->euid)
-               return -EPERM;
-       if (current->leader)
-@
index c19900fc23dff2c5c79405e649fbee06563c31be..e72a9ab142f49c7e4e30e7dcf8704ac4b31830a2 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
-.globl _device_not_available,_double_fault,_coprocessor_segment_overrun
+.globl _double_fault,_coprocessor_segment_overrun
 .globl _invalid_TSS,_segment_not_present,_stack_segment
 .globl _general_protection,_coprocessor_error,_irq13,_reserved
 
@@ -74,28 +74,6 @@ _invalid_op:
        pushl $_do_invalid_op
        jmp no_error_code
 
-math_emulate:
-       popl %eax
-       pushl $_do_device_not_available
-       jmp no_error_code
-_device_not_available:
-       pushl %eax
-       movl %cr0,%eax
-       testl $0x4,%eax                 # EM (math emulation bit)
-       jne math_emulate
-       clts                            # clear TS so that we can use math
-       pushl %ecx
-       pushl %edx
-       push %ds
-       movl $0x10,%eax
-       mov %ax,%ds
-       call _math_state_restore
-       pop %ds
-       popl %edx
-       popl %ecx
-       popl %eax
-       iret
-
 _coprocessor_segment_overrun:
        pushl $_do_coprocessor_segment_overrun
        jmp no_error_code
@@ -114,10 +92,7 @@ _irq13:
 1:     jmp 1f
 1:     outb %al,$0xA0
        popl %eax
-_coprocessor_error:
-       fnclex
-       pushl $_do_coprocessor_error
-       jmp no_error_code
+       jmp _coprocessor_error
 
 _double_fault:
        pushl $_do_double_fault
index a830c3f6074c1cfb4a15ce4d1fa8c621fe3a7764..0fd7cb001cea84f305e7a02ee34ace0c81068500 100644 (file)
@@ -24,7 +24,7 @@ CPP   =gcc -E -nostdinc -I../../include
        $(CC) $(CFLAGS) \
        -c -o $*.o $<
 
-OBJS  = ll_rw_blk.o floppy.o hd.o
+OBJS  = ll_rw_blk.o floppy.o hd.o ramdisk.o
 
 blk_drv.a: $(OBJS)
        $(AR) rcs blk_drv.a $(OBJS)
index 1682465a3b98d965ae6b749fdcfe58c784481335..c4a7cde7c9792526dab88119a5093c9e5e260e95 100644 (file)
@@ -2,7 +2,17 @@
 #define _BLK_H
 
 #define NR_BLK_DEV     7
-#define NR_REQUEST     64
+/*
+ * NR_REQUEST is the number of entries in the request-queue.
+ * NOTE that writes may use only the low 2/3 of these: reads
+ * take precedence.
+ *
+ * 32 seems to be a reasonable number: enough to get some benefit
+ * from the elevator-mechanism, but not so much as to lock a lot of
+ * buffers when they are in the queue. 64 seems to be too many (easily
+ * long pauses in reading when heavy writing/syncing is going on)
+ */
+#define NR_REQUEST     32
 
 /*
  * Ok, this is an expanded form so that we can use the same
@@ -22,9 +32,15 @@ struct request {
        struct request * next;
 };
 
+/*
+ * This is used in the elevator algorithm: Note that
+ * reads always go before writes. This is natural: reads
+ * are much more time-critical than writes.
+ */
 #define IN_ORDER(s1,s2) \
+((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \
 ((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
-(s1)->sector < (s2)->sector))
+(s1)->sector < (s2)->sector)))
 
 struct blk_dev_struct {
        void (*request_fn)(void);
@@ -41,7 +57,16 @@ extern struct task_struct * wait_for_request;
  * Add entries as needed. Currently the only block devices
  * supported are hard-disks and floppies.
  */
-#if (MAJOR_NR == 2)
+
+#if (MAJOR_NR == 1)
+/* ram disk */
+#define DEVICE_NAME "ramdisk"
+#define DEVICE_REQUEST do_rd_request
+#define DEVICE_NR(device) ((device) & 7)
+#define DEVICE_ON(device) 
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == 2)
 /* floppy */
 #define DEVICE_NAME "floppy"
 #define DEVICE_INTR do_floppy
@@ -68,7 +93,9 @@ extern struct task_struct * wait_for_request;
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
 #define CURRENT_DEV DEVICE_NR(CURRENT->dev)
 
+#ifdef DEVICE_INTR
 void (*DEVICE_INTR)(void) = NULL;
+#endif
 static void (DEVICE_REQUEST)(void);
 
 extern inline void unlock_buffer(struct buffer_head * bh)
@@ -103,13 +130,10 @@ repeat: \
                return; \
        if (MAJOR(CURRENT->dev) != MAJOR_NR) \
                panic(DEVICE_NAME ": request list destroyed"); \
-       if (CURRENT->bh) \
+       if (CURRENT->bh) \
                if (!CURRENT->bh->b_lock) \
                        panic(DEVICE_NAME ": block not locked"); \
-               else { \
-                       CURRENT->bh->b_dirt = 0; \
-                       CURRENT->bh->b_uptodate = 0; \
-               }
+       }
 
 #endif
 
index 47ee961edfb1b2e9d0097254f81405e15cde66b9..2500a882eeb0ab22cbbd9681c0c547f6756a8f0c 100644 (file)
@@ -4,6 +4,21 @@
  *  (C) 1991  Linus Torvalds
  */
 
+/*
+ * 02.12.91 - Changed to static variables to indicate need for reset
+ * and recalibrate. This makes some things easier (output_byte reset
+ * checking etc), and means less interrupt jumping in case of errors,
+ * so the code is hopefully easier to understand.
+ */
+
+/*
+ * This file is certainly a mess. I've tried my best to get it working,
+ * but I don't like programming floppies, and I have only one anyway.
+ * Urgel. I should check for more errors, and do more graceful error
+ * recovery. Seems there are problems with several drives. I've tried to
+ * correct them. No promises. 
+ */
+
 /*
  * As with hd.c, all routines within this file can (and will) be called
  * by interrupts, so extreme caution is needed. A hardware interrupt
 #define MAJOR_NR 2
 #include "blk.h"
 
-static void reset_floppy(void);
-static void seek_interrupt(void);
-static void rw_interrupt(void);
+static int recalibrate = 0;
+static int reset = 0;
+static int seek = 0;
 
 extern unsigned char current_DOR;
-extern unsigned char selected;
 
 #define immoutb_p(val,port) \
 __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
@@ -39,11 +53,11 @@ __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
 #define TYPE(x) ((x)>>2)
 #define DRIVE(x) ((x)&0x03)
 /*
- * Note that MAX_ERRORS=10 doesn't imply that we retry every bad read
- * max 10 times - some types of errors increase the errorcount by 2,
- * so we might actually retry only 6-7 times before giving up.
+ * Note that MAX_ERRORS=8 doesn't imply that we retry every bad read
+ * max 8 times - some types of errors increase the errorcount by 2,
+ * so we might actually retry only 5-6 times before giving up.
  */
-#define MAX_ERRORS 10
+#define MAX_ERRORS 8
 
 /*
  * globals used by 'result()'
@@ -58,14 +72,15 @@ static unsigned char reply_buffer[MAX_REPLIES];
 /*
  * This struct defines the different floppy types. Unlike minix
  * linux doesn't have a "search for right type"-type, as the code
- * for that is convoluted and weird.
+ * for that is convoluted and weird. I've got enough problems with
+ * this driver as it is.
  *
  * The 'stretch' tells if the tracks need to be boubled for some
  * types (ie 360kB diskette in 1.2MB drive etc). Others should
  * be self-explanatory.
  */
 static struct floppy_struct {
-       int size, sect, head, track, stretch;
+       unsigned int size, sect, head, track, stretch;
        unsigned char gap,rate,spec1;
 } floppy_type[] = {
        {    0, 0,0, 0,0,0x00,0x00,0x00 },      /* no testing */
@@ -102,16 +117,33 @@ static unsigned char sector = 0;
 static unsigned char head = 0;
 static unsigned char track = 0;
 static unsigned char seek_track = 0;
+static unsigned char current_track = 255;
 static unsigned char command = 0;
+unsigned char selected = 0;
+struct task_struct * wait_on_floppy_select = NULL;
+
+void floppy_deselect(unsigned int nr)
+{
+       if (nr != (current_DOR & 3))
+               printk("floppy_deselect: drive not selected\n\r");
+       selected = 0;
+       wake_up(&wait_on_floppy_select);
+}
 
 /*
  * floppy-change is never called from an interrupt, so we can relax a bit
- * here.
+ * here, sleep etc. Note that floppy-on tries to set current_DOR to point
+ * to the desired drive, but it will probably not survive the sleep if
+ * several floppies are used at the same time: thus the loop.
  */
 int floppy_change(unsigned int nr)
 {
+repeat:
        floppy_on(nr);
-       floppy_select(nr);
+       while ((current_DOR & 3) != nr && selected)
+               interruptible_sleep_on(&wait_on_floppy_select);
+       if ((current_DOR & 3) != nr)
+               goto repeat;
        if (inb(FD_DIR) & 0x80) {
                floppy_off(nr);
                return 1;
@@ -129,6 +161,7 @@ static void setup_DMA(void)
 {
        long addr = (long) CURRENT->buffer;
 
+       cli();
        if (addr >= 0x100000) {
                addr = (long) tmp_floppy_area;
                if (command == FD_WRITE)
@@ -155,6 +188,7 @@ static void setup_DMA(void)
        immoutb_p(3,5);
 /* activate DMA 2 */
        immoutb_p(0|2,10);
+       sti();
 }
 
 static void output_byte(char byte)
@@ -162,13 +196,16 @@ static void output_byte(char byte)
        int counter;
        unsigned char status;
 
+       if (reset)
+               return;
        for(counter = 0 ; counter < 10000 ; counter++) {
-               status = inb(FD_STATUS) & (STATUS_READY | STATUS_DIR);
+               status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
                if (status == STATUS_READY) {
                        outb(byte,FD_DATA);
                        return;
                }
        }
+       reset = 1;
        printk("Unable to send byte to FDC\n\r");
 }
 
@@ -176,56 +213,61 @@ static int result(void)
 {
        int i = 0, counter, status;
 
+       if (reset)
+               return -1;
        for (counter = 0 ; counter < 10000 ; counter++) {
-               status = inb(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
+               status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
                if (status == STATUS_READY)
                        return i;
                if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
                        if (i >= MAX_REPLIES)
                                break;
-                       reply_buffer[i++] = inb(FD_DATA);
+                       reply_buffer[i++] = inb_p(FD_DATA);
                }
        }
+       reset = 1;
        printk("Getstatus times out\n\r");
        return -1;
 }
 
+static void bad_flp_intr(void)
+{
+       CURRENT->errors++;
+       if (CURRENT->errors > MAX_ERRORS) {
+               floppy_deselect(current_drive);
+               end_request(0);
+       }
+       if (CURRENT->errors > MAX_ERRORS/2)
+               reset = 1;
+       else
+               recalibrate = 1;
+}      
+
 /*
- * This is the routine called after every seek (or recalibrate) interrupt
- * from the floppy controller. Note that the "unexpected interrupt" routine
- * also does a recalibrate, but doesn't come here.
+ * Ok, this interrupt is called after a DMA read/write has succeeded,
+ * so we check the results, and copy any buffers.
  */
-static void seek_interrupt(void)
+static void rw_interrupt(void)
 {
-/* sense drive status */
-       output_byte(FD_SENSEI);
-       if (result() != 2 || (ST0 & 0xF8) != 0x20) {
-               CURRENT->errors++;
-               if (CURRENT->errors > MAX_ERRORS) {
+       if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {
+               if (ST1 & 0x02) {
+                       printk("Drive %d is write protected\n\r",current_drive);
                        floppy_deselect(current_drive);
                        end_request(0);
-                       reset_floppy();
-                       return;
-               }
-               output_byte(FD_RECALIBRATE);
-               output_byte(head<<2 | current_drive);
+               } else
+                       bad_flp_intr();
+               do_fd_request();
                return;
        }
-/* are we on the right track? */
-       if (ST1 != seek_track) {
-               CURRENT->errors++;
-               if (CURRENT->errors > MAX_ERRORS) {
-                       floppy_deselect(current_drive);
-                       end_request(0);
-                       reset_floppy();
-                       return;
-               }
-               output_byte(FD_SEEK);
-               output_byte(head<<2 | current_drive);
-               output_byte(seek_track);
-               return;
-       }
-/* yes - set up DMA and read/write command */
+       if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000)
+               copy_buffer(tmp_floppy_area,CURRENT->buffer);
+       floppy_deselect(current_drive);
+       end_request(1);
+       do_fd_request();
+}
+
+inline void setup_rw_floppy(void)
+{
        setup_DMA();
        do_floppy = rw_interrupt;
        output_byte(command);
@@ -237,36 +279,26 @@ static void seek_interrupt(void)
        output_byte(floppy->sect);
        output_byte(floppy->gap);
        output_byte(0xFF);      /* sector size (0xff when n!=0 ?) */
+       if (reset)
+               do_fd_request();
 }
 
 /*
- * Ok, this interrupt is called after a DMA read/write has succeeded,
- * so we check the results, and copy any buffers.
+ * This is the routine called after every seek (or recalibrate) interrupt
+ * from the floppy controller. Note that the "unexpected interrupt" routine
+ * also does a recalibrate, but doesn't come here.
  */
-static void rw_interrupt(void)
+static void seek_interrupt(void)
 {
-       if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) ||
-           (ST2 & 0x73)) {
-               CURRENT->errors++;
-               if (CURRENT->errors > MAX_ERRORS || (ST1 & 0x02)) {
-                       if (ST1 & 0x02)
-                               printk("Drive %d is write protected\n\r",
-                               current_drive);
-                       floppy_deselect(current_drive);
-                       end_request(0);
-                       do_fd_request();
-                       return;
-               }
-               do_floppy = seek_interrupt;
-               output_byte(FD_RECALIBRATE);
-               output_byte(head<<2 | current_drive);
+/* sense drive status */
+       output_byte(FD_SENSEI);
+       if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
+               bad_flp_intr();
+               do_fd_request();
                return;
        }
-       if (command == FD_READ && (long)(CURRENT->buffer) >= 0x100000)
-               copy_buffer(tmp_floppy_area,CURRENT->buffer);
-       floppy_deselect(current_drive);
-       end_request(1);
-       do_fd_request();
+       current_track = ST1;
+       setup_rw_floppy();
 }
 
 /*
@@ -284,6 +316,14 @@ static void transfer(void)
        }
        if (cur_rate != floppy->rate)
                outb_p(cur_rate = floppy->rate,FD_DCR);
+       if (reset) {
+               do_fd_request();
+               return;
+       }
+       if (!seek) {
+               setup_rw_floppy();
+               return;
+       }
        do_floppy = seek_interrupt;
        if (seek_track) {
                output_byte(FD_SEEK);
@@ -293,6 +333,8 @@ static void transfer(void)
                output_byte(FD_RECALIBRATE);
                output_byte(head<<2 | current_drive);
        }
+       if (reset)
+               do_fd_request();
 }
 
 /*
@@ -300,59 +342,95 @@ static void transfer(void)
  */
 static void recal_interrupt(void)
 {
-       do_floppy = NULL;
        output_byte(FD_SENSEI);
-       if (result()!=2 || (ST0 & 0xE0) == 0x60) {
-               reset_floppy();
-               return;
-       }
+       if (result()!=2 || (ST0 & 0xE0) == 0x60)
+               reset = 1;
+       else
+               recalibrate = 0;
        do_fd_request();
 }
 
 void unexpected_floppy_interrupt(void)
 {
        output_byte(FD_SENSEI);
-       if (result()!=2 || (ST0 & 0xE0) == 0x60) {
-               reset_floppy();
-               return;
-       }
+       if (result()!=2 || (ST0 & 0xE0) == 0x60)
+               reset = 1;
+       else
+               recalibrate = 1;
+}
+
+static void recalibrate_floppy(void)
+{
+       recalibrate = 0;
+       current_track = 0;
        do_floppy = recal_interrupt;
        output_byte(FD_RECALIBRATE);
        output_byte(head<<2 | current_drive);
+       if (reset)
+               do_fd_request();
 }
 
 static void reset_interrupt(void)
 {
        output_byte(FD_SENSEI);
        (void) result();
-       do_floppy = recal_interrupt;
-       output_byte(FD_RECALIBRATE);
-       output_byte(head<<2 | current_drive);
+       output_byte(FD_SPECIFY);
+       output_byte(cur_spec1);         /* hut etc */
+       output_byte(6);                 /* Head load time =6ms, DMA */
+       do_fd_request();
 }
 
+/*
+ * reset is done by pulling bit 2 of DOR low for a while.
+ */
 static void reset_floppy(void)
 {
+       int i;
+
+       reset = 0;
+       cur_spec1 = -1;
+       cur_rate = -1;
+       recalibrate = 1;
        printk("Reset-floppy called\n\r");
+       cli();
        do_floppy = reset_interrupt;
-       outb_p(0,FD_DOR);
+       outb_p(current_DOR & ~0x04,FD_DOR);
+       for (i=0 ; i<100 ; i++)
+               __asm__("nop");
        outb(current_DOR,FD_DOR);
+       sti();
 }
 
 static void floppy_on_interrupt(void)
 {
 /* We cannot do a floppy-select, as that might sleep. We just force it */
        selected = 1;
-       current_DOR &= 0xFC;
-       current_DOR |= current_drive;
-       transfer();
+       if (current_drive != (current_DOR & 3)) {
+               current_DOR &= 0xFC;
+               current_DOR |= current_drive;
+               outb(current_DOR,FD_DOR);
+               add_timer(2,&transfer);
+       } else
+               transfer();
 }
 
 void do_fd_request(void)
 {
        unsigned int block;
 
+       seek = 0;
+       if (reset) {
+               reset_floppy();
+               return;
+       }
+       if (recalibrate) {
+               recalibrate_floppy();
+               return;
+       }
        INIT_REQUEST;
        floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
+       if (current_drive != CURRENT_DEV)
+               seek = 1;
        current_drive = CURRENT_DEV;
        block = CURRENT->sector;
        if (block+2 > floppy->size) {
@@ -364,6 +442,8 @@ void do_fd_request(void)
        head = block % floppy->head;
        track = block / floppy->head;
        seek_track = track << floppy->stretch;
+       if (seek_track != current_track)
+               seek = 1;
        sector++;
        if (CURRENT->cmd == READ)
                command = FD_READ;
@@ -377,6 +457,6 @@ void do_fd_request(void)
 void floppy_init(void)
 {
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       set_intr_gate(0x26,&floppy_interrupt);
+       set_trap_gate(0x26,&floppy_interrupt);
        outb(inb_p(0x21)&~0x40,0x21);
 }
index bfb8701cc719f55f60087c3b50f5bf9cfbda5e57..23c58d42a33a1cdf026a3cd357da39acbbbd74db 100644 (file)
@@ -9,6 +9,8 @@
  * request-list, using interrupts to jump between functions. As
  * all the functions are called within interrupts, we may not
  * sleep. Special care is recommended.
+ * 
+ *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
  */
 
 #include <linux/config.h>
 #define MAJOR_NR 3
 #include "blk.h"
 
+#define CMOS_READ(addr) ({ \
+outb_p(0x80|addr,0x70); \
+inb_p(0x71); \
+})
+
 /* Max read/write errors/sector */
-#define MAX_ERRORS     5
+#define MAX_ERRORS     7
 #define MAX_HD         2
 
+static void recal_intr(void);
+
+static int recalibrate = 1;
+static int reset = 1;
+
 /*
  *  This struct defines the HD's and their types.
  */
@@ -53,12 +65,14 @@ __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
 __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
 
 extern void hd_interrupt(void);
+extern void rd_load(void);
 
 /* This may be used only once, enforced by 'static int callable' */
 int sys_setup(void * BIOS)
 {
        static int callable = 1;
        int i,drive;
+       unsigned char cmos_disks;
        struct partition *p;
        struct buffer_head * bh;
 
@@ -85,6 +99,40 @@ int sys_setup(void * BIOS)
                hd[i*5].nr_sects = hd_info[i].head*
                                hd_info[i].sect*hd_info[i].cyl;
        }
+
+       /*
+               We querry CMOS about hard disks : it could be that 
+               we have a SCSI/ESDI/etc controller that is BIOS
+               compatable with ST-506, and thus showing up in our
+               BIOS table, but not register compatable, and therefore
+               not present in CMOS.
+
+               Furthurmore, we will assume that our ST-506 drives
+               <if any> are the primary drives in the system, and 
+               the ones reflected as drive 1 or 2.
+
+               The first drive is stored in the high nibble of CMOS
+               byte 0x12, the second in the low nibble.  This will be
+               either a 4 bit drive type or 0xf indicating use byte 0x19 
+               for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
+
+               Needless to say, a non-zero value means we have 
+               an AT controller hard disk for that drive.
+
+               
+       */
+
+       if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
+               if (cmos_disks & 0x0f)
+                       NR_HD = 2;
+               else
+                       NR_HD = 1;
+       else
+               NR_HD = 0;
+       for (i = NR_HD ; i < 2 ; i++) {
+               hd[i*5].start_sect = 0;
+               hd[i*5].nr_sects = 0;
+       }
        for (drive=0 ; drive<NR_HD ; drive++) {
                if (!(bh = bread(0x300 + drive*5,0))) {
                        printk("Unable to read partition table of drive %d\n\r",
@@ -103,22 +151,24 @@ int sys_setup(void * BIOS)
                }
                brelse(bh);
        }
-       printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
+       if (NR_HD)
+               printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
+       rd_load();
        mount_root();
        return (0);
 }
 
 static int controller_ready(void)
 {
-       int retries=1000;
+       int retries=10000;
 
-       while (--retries && (inb(HD_STATUS)&0xc0)!=0x40);
+       while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40);
        return (retries);
 }
 
 static int win_result(void)
 {
-       int i=inb(HD_STATUS);
+       int i=inb_p(HD_STATUS);
 
        if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
                == (READY_STAT | SEEK_STAT))
@@ -138,7 +188,7 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
        if (!controller_ready())
                panic("HD controller not ready");
        do_hd = intr_addr;
-       outb(hd_info[drive].ctl,HD_CMD);
+       outb_p(hd_info[drive].ctl,HD_CMD);
        port=HD_DATA;
        outb_p(hd_info[drive].wpcom>>2,++port);
        outb_p(nsect,++port);
@@ -153,8 +203,8 @@ static int drive_busy(void)
 {
        unsigned int i;
 
-       for (i = 0; i < 100000; i++)
-               if (READY_STAT == (inb(HD_STATUS) & (BUSY_STAT | READY_STAT)))
+       for (i = 0; i < 10000; i++)
+               if (READY_STAT == (inb_p(HD_STATUS) & (BUSY_STAT|READY_STAT)))
                        break;
        i = inb(HD_STATUS);
        i &= BUSY_STAT | READY_STAT | SEEK_STAT;
@@ -169,26 +219,19 @@ static void reset_controller(void)
        int     i;
 
        outb(4,HD_CMD);
-       for(i = 0; i < 1000; i++) nop();
-       outb(0,HD_CMD);
-       for(i = 0; i < 10000 && drive_busy(); i++) /* nothing */;
+       for(i = 0; i < 100; i++) nop();
+       outb(hd_info[0].ctl & 0x0f ,HD_CMD);
        if (drive_busy())
                printk("HD-controller still busy\n\r");
-       if((i = inb(ERR_STAT)) != 1)
+       if ((i = inb(HD_ERROR)) != 1)
                printk("HD-controller reset failed: %02x\n\r",i);
 }
 
-static void redo_hd_request(void)
-{
-       do_hd = NULL;
-       do_hd_request();
-}
-
 static void reset_hd(int nr)
 {
        reset_controller();
        hd_out(nr,hd_info[nr].sect,hd_info[nr].sect,hd_info[nr].head-1,
-               hd_info[nr].cyl,WIN_SPECIFY,&redo_hd_request);
+               hd_info[nr].cyl,WIN_SPECIFY,&recal_intr);
 }
 
 void unexpected_hd_interrupt(void)
@@ -198,25 +241,27 @@ void unexpected_hd_interrupt(void)
 
 static void bad_rw_intr(void)
 {
-       int i = CURRENT_DEV;
-
-       if (CURRENT->errors++ >= MAX_ERRORS)
+       if (++CURRENT->errors >= MAX_ERRORS)
                end_request(0);
-       reset_hd(i);
+       if (CURRENT->errors > MAX_ERRORS/2)
+               reset = 1;
 }
 
 static void read_intr(void)
 {
        if (win_result()) {
                bad_rw_intr();
+               do_hd_request();
                return;
        }
        port_read(HD_DATA,CURRENT->buffer,256);
        CURRENT->errors = 0;
        CURRENT->buffer += 512;
        CURRENT->sector++;
-       if (--CURRENT->nr_sectors)
+       if (--CURRENT->nr_sectors) {
+               do_hd = &read_intr;
                return;
+       }
        end_request(1);
        do_hd_request();
 }
@@ -225,11 +270,13 @@ static void write_intr(void)
 {
        if (win_result()) {
                bad_rw_intr();
+               do_hd_request();
                return;
        }
        if (--CURRENT->nr_sectors) {
                CURRENT->sector++;
                CURRENT->buffer += 512;
+               do_hd = &write_intr;
                port_write(HD_DATA,CURRENT->buffer,256);
                return;
        }
@@ -237,6 +284,13 @@ static void write_intr(void)
        do_hd_request();
 }
 
+static void recal_intr(void)
+{
+       if (win_result())
+               bad_rw_intr();
+       do_hd_request();
+}
+
 void do_hd_request(void)
 {
        int i,r;
@@ -259,13 +313,25 @@ void do_hd_request(void)
                "r" (hd_info[dev].head));
        sec++;
        nsect = CURRENT->nr_sectors;
+       if (reset) {
+               reset = 0;
+               recalibrate = 1;
+               reset_hd(CURRENT_DEV);
+               return;
+       }
+       if (recalibrate) {
+               recalibrate = 0;
+               hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
+                       WIN_RESTORE,&recal_intr);
+               return;
+       }       
        if (CURRENT->cmd == WRITE) {
                hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
                for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
                        /* nothing */ ;
                if (!r) {
-                       reset_hd(CURRENT_DEV);
-                       return;
+                       bad_rw_intr();
+                       goto repeat;
                }
                port_write(HD_DATA,CURRENT->buffer,256);
        } else if (CURRENT->cmd == READ) {
@@ -277,7 +343,7 @@ void do_hd_request(void)
 void hd_init(void)
 {
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       set_trap_gate(0x2E,&hd_interrupt);
+       set_intr_gate(0x2E,&hd_interrupt);
        outb_p(inb_p(0x21)&0xfb,0x21);
        outb(inb_p(0xA1)&0xbf,0xA1);
 }
index ae8741be8d06a082a246b1b37db87fb408841a41..f57d9980bc4aa0d6114601a42bc84d9bb0b4cf13 100644 (file)
@@ -67,49 +67,69 @@ static void add_request(struct blk_dev_struct * dev, struct request * req)
 
        req->next = NULL;
        cli();
+       if (req->bh)
+               req->bh->b_dirt = 0;
        if (!(tmp = dev->current_request)) {
                dev->current_request = req;
                sti();
                (dev->request_fn)();
-       } else {
-               for ( ; tmp->next ; tmp=tmp->next)
-                       if ((IN_ORDER(tmp,req) ||
-                           !IN_ORDER(tmp,tmp->next)) &&
-                           IN_ORDER(req,tmp->next))
-                               break;
-               req->next=tmp->next;
-               tmp->next=req;
+               return;
        }
+       for ( ; tmp->next ; tmp=tmp->next)
+               if ((IN_ORDER(tmp,req) ||
+                   !IN_ORDER(tmp,tmp->next)) &&
+                   IN_ORDER(req,tmp->next))
+                       break;
+       req->next=tmp->next;
+       tmp->next=req;
        sti();
 }
 
 static void make_request(int major,int rw, struct buffer_head * bh)
 {
        struct request * req;
+       int rw_ahead;
 
-/* READA is special case - the read is not really needed, so if the   */
+/* WRITEA/READA is special case - it is not really needed, so if the */
 /* buffer is locked, we just forget about it, else it's a normal read */
-       if (rw == READA) {
+       if (rw_ahead = (rw == READA || rw == WRITEA)) {
                if (bh->b_lock)
                        return;
+               if (rw == READA)
+                       rw = READ;
                else
-                       rw=READ;
+                       rw = WRITE;
        }
        if (rw!=READ && rw!=WRITE)
-               panic("Bad block dev command, must be R/W/RA");
+               panic("Bad block dev command, must be R/W/RA/WA");
        lock_buffer(bh);
        if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
                unlock_buffer(bh);
                return;
        }
 repeat:
-       for (req=0+request ; req<NR_REQUEST+request ; req++)
+/* we don't allow the write-requests to fill up the queue completely:
+ * we want some room for reads: they take precedence. The last third
+ * of the requests are only for reads.
+ */
+       if (rw == READ)
+               req = request+NR_REQUEST;
+       else
+               req = request+((NR_REQUEST*2)/3);
+/* find an empty request */
+       while (--req >= request)
                if (req->dev<0)
                        break;
-       if (req==NR_REQUEST+request) {
+/* if none found, sleep on new requests: check for rw_ahead */
+       if (req < request) {
+               if (rw_ahead) {
+                       unlock_buffer(bh);
+                       return;
+               }
                sleep_on(&wait_for_request);
                goto repeat;
        }
+/* fill up the request-info, and add it to the queue */
        req->dev = bh->b_dev;
        req->cmd = rw;
        req->errors=0;
@@ -127,8 +147,10 @@ void ll_rw_block(int rw, struct buffer_head * bh)
        unsigned int major;
 
        if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
-       !(blk_dev[major].request_fn))
-               panic("Trying to read nonexistent block-device");
+       !(blk_dev[major].request_fn)) {
+               printk("Trying to read nonexistent block-device\n\r");
+               return;
+       }
        make_request(major,rw,bh);
 }
 
index 01313769d3d62353cc7cb620d802ec410b89d27f..dc99f7cd1f11ce1008d01538fe37d91f8412c76a 100644 (file)
@@ -1,13 +1,15 @@
 /*
  *  linux/kernel/blk_drv/ramdisk.c
  *
- *  Written by Theodore Ts'o
+ *  Written by Theodore Ts'o, 12/2/91
  */
 
+#include <string.h>
+
 #include <linux/config.h>
+#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/hdreg.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/memory.h>
 #define MAJOR_NR 1
 #include "blk.h"
 
-char   *ram_disk;                      /* Start of ram disk */
-int    ram_disk_size;                  /* Size of ram disk */
+char   *rd_start;
+int    rd_length = 0;
 
-void do_ram_request(void)
+void do_rd_request(void)
 {
-       int i,r;
-       unsigned int block,dev;
-       unsigned int sec,head,cyl;
-       unsigned int nsect;
+       int     len;
+       char    *addr;
 
        INIT_REQUEST;
-       if (MINOR(CURRENT->dev) != 0) {
+       addr = rd_start + (CURRENT->sector << 9);
+       len = CURRENT->nr_sectors << 9;
+       if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {
                end_request(0);
                goto repeat;
        }
-       block = CURRENT->sector;
+       if (CURRENT-> cmd == WRITE) {
+               (void ) memcpy(addr,
+                             CURRENT->buffer,
+                             len);
+       } else if (CURRENT->cmd == READ) {
+               (void) memcpy(CURRENT->buffer, 
+                             addr,
+                             len);
+       } else
+               panic("unknown ramdisk-command");
        end_request(1);
+       goto repeat;
 }
 
-void ram_init(void)
+/*
+ * Returns amount of memory which needs to be reserved.
+ */
+long rd_init(long mem_start, int length)
 {
+       int     i;
+       char    *cp;
 
+       blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+       rd_start = (char *) mem_start;
+       rd_length = length;
+       cp = rd_start;
+       for (i=0; i < length; i++)
+               *cp++ = '\0';
+       return(length);
+}
+
+/*
+ * If the root device is the ram disk, try to load it.
+ * In order to do this, the root device is originally set to the
+ * floppy, and we later change it to be ram disk.
+ */
+void rd_load(void)
+{
+       struct buffer_head *bh;
+       struct super_block      s;
+       int             block = 256;    /* Start at block 256 */
+       int             i = 1;
+       int             nblocks;
+       char            *cp;            /* Move pointer */
+       
+       if (!rd_length)
+               return;
+       printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length,
+               (int) rd_start);
+       if (MAJOR(ROOT_DEV) != 2)
+               return;
+       bh = breada(ROOT_DEV,block+1,block,block+2,-1);
+       if (!bh) {
+               printk("Disk error while looking for ramdisk!\n");
+               return;
+       }
+       *((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data);
+       brelse(bh);
+       if (s.s_magic != SUPER_MAGIC)
+               /* No ram disk image present, assume normal floppy boot */
+               return;
+       nblocks = s.s_nzones << s.s_log_zone_size;
+       if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
+               printk("Ram disk image too big!  (%d blocks, %d avail)\n", 
+                       nblocks, rd_length >> BLOCK_SIZE_BITS);
+               return;
+       }
+       printk("Loading %d bytes into ram disk... 0000k", 
+               nblocks << BLOCK_SIZE_BITS);
+       cp = rd_start;
+       while (nblocks) {
+               if (nblocks > 2) 
+                       bh = breada(ROOT_DEV, block, block+1, block+2, -1);
+               else
+                       bh = bread(ROOT_DEV, block);
+               if (!bh) {
+                       printk("I/O error on block %d, aborting load\n", 
+                               block);
+                       return;
+               }
+               (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
+               brelse(bh);
+               printk("\010\010\010\010\010%4dk",i);
+               cp += BLOCK_SIZE;
+               block++;
+               nblocks--;
+               i++;
+       }
+       printk("\010\010\010\010\010done \n");
+       ROOT_DEV=0x0101;
 }
diff --git a/kernel/blk_drv/ramdisk.c~ b/kernel/blk_drv/ramdisk.c~
deleted file mode 100644 (file)
index 1d9cb89..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  linux/kernel/blk_drv/ramdisk.c
- *
- *  Written by Theodore Ts'o
- */
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-
-#define MAJOR_NR 2
-#include "blk.h"
-
-void do_ram_request(void)
-{
-       int i,r;
-       unsigned int block,dev;
-       unsigned int sec,head,cyl;
-       unsigned int nsect;
-
-       INIT_REQUEST;
-       dev = MINOR(CURRENT->dev);
-       block = CURRENT->sector;
-       if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
-               end_request(0);
-               goto repeat;
-       }
-       block += hd[dev].start_sect;
-       dev /= 5;
-       __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
-               "r" (hd_info[dev].sect));
-       __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
-               "r" (hd_info[dev].head));
-       sec++;
-       nsect = CURRENT->nr_sectors;
-       if (CURRENT->cmd == WRITE) {
-               hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
-               for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
-                       /* nothing */ ;
-               if (!r) {
-                       reset_hd(CURRENT_DEV);
-                       return;
-               }
-               port_write(HD_DATA,CURRENT->buffer,256);
-       } else if (CURRENT->cmd == READ) {
-               hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
-       } else
-               panic("unknown hd-command");
-}
-
-void ram_init(void)
-{
-
-}
index 140563816ed85a590cade1a0bb82e640d31565df..9e2b848379bd2071fe55e0e24decd13313c897a6 100644 (file)
@@ -24,7 +24,8 @@ CPP   =gcc -E -nostdinc -I../../include
        $(CC) $(CFLAGS) \
        -c -o $*.o $<
 
-OBJS  = tty_io.o console.o keyboard.o serial.o rs_io.o
+OBJS  = tty_io.o console.o keyboard.o serial.o rs_io.o \
+       tty_ioctl.o
 
 chr_drv.a: $(OBJS)
        $(AR) rcs chr_drv.a $(OBJS)
@@ -59,3 +60,9 @@ tty_io.s tty_io.o : tty_io.c ../../include/ctype.h ../../include/errno.h \
   ../../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/tty.h \
   ../../include/termios.h ../../include/asm/segment.h \
   ../../include/asm/system.h 
+tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h \
+  ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
+  ../../include/signal.h ../../include/linux/kernel.h \
+  ../../include/linux/tty.h ../../include/asm/io.h \
+  ../../include/asm/segment.h ../../include/asm/system.h 
diff --git a/kernel/chr_drv/RCS/keyboard.S,v b/kernel/chr_drv/RCS/keyboard.S,v
deleted file mode 100644 (file)
index 909225d..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-head     1.1;
-branch   ;
-access   ;
-symbols  ;
-locks    tytso:1.1; strict;
-comment  @@;
-
-
-1.1
-date     91.11.21.14.50.43;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-
-1.1
-log
-@Initial revision
-@
-text
-@/*
- *  linux/kernel/keyboard.S
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *     Thanks to Alfred Leung for US keyboard patches
- */
-
-#include <linux/config.h>
-
-.text
-.globl _keyboard_interrupt
-
-/*
- * these are for the keyboard read functions
- */
-size   = 1024          /* must be a power of two ! And MUST be the same
-                          as in tty_io.c !!!! */
-head = 4
-tail = 8
-proc_list = 12
-buf = 16
-
-mode:  .byte 0         /* caps, alt, ctrl and shift mode */
-leds:  .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
-e0:    .byte 0
-
-/*
- *  con_int is the real interrupt routine that reads the
- *  keyboard scan-code and converts it into the appropriate
- *  ascii character(s).
- */
-_keyboard_interrupt:
-       pushl %eax
-       pushl %ebx
-       pushl %ecx
-       pushl %edx
-       push %ds
-       push %es
-       movl $0x10,%eax
-       mov %ax,%ds
-       mov %ax,%es
-       xorl %al,%al            /* %eax is scan code */
-       inb $0x60,%al
-       cmpb $0xe0,%al
-       je set_e0
-       cmpb $0xe1,%al
-       je set_e1
-       call key_table(,%eax,4)
-       movb $0,e0
-e0_e1: inb $0x61,%al
-       jmp 1f
-1:     jmp 1f
-1:     orb $0x80,%al
-       jmp 1f
-1:     jmp 1f
-1:     outb %al,$0x61
-       jmp 1f
-1:     jmp 1f
-1:     andb $0x7F,%al
-       outb %al,$0x61
-       movb $0x20,%al
-       outb %al,$0x20
-       pushl $0
-       call _do_tty_interrupt
-       addl $4,%esp
-       pop %es
-       pop %ds
-       popl %edx
-       popl %ecx
-       popl %ebx
-       popl %eax
-       iret
-set_e0:        movb $1,e0
-       jmp e0_e1
-set_e1:        movb $2,e0
-       jmp e0_e1
-
-/*
- * This routine fills the buffer with max 8 bytes, taken from
- * %ebx:%eax. (%edx is high). The bytes are written in the
- * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
- */
-put_queue:
-       pushl %ecx
-       pushl %edx
-       movl _table_list,%edx           # read-queue for console
-       movl head(%edx),%ecx
-1:     movb %al,buf(%edx,%ecx)
-       incl %ecx
-       andl $size-1,%ecx
-       cmpl tail(%edx),%ecx            # buffer full - discard everything
-       je 3f
-       shrdl $8,%ebx,%eax
-       je 2f
-       shrl $8,%ebx
-       jmp 1b
-2:     movl %ecx,head(%edx)
-       movl proc_list(%edx),%ecx
-       testl %ecx,%ecx
-       je 3f
-       movl $0,(%ecx)
-3:     popl %edx
-       popl %ecx
-       ret
-
-ctrl:  movb $0x04,%al
-       jmp 1f
-alt:   movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     orb %al,mode
-       ret
-unctrl:        movb $0x04,%al
-       jmp 1f
-unalt: movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     notb %al
-       andb %al,mode
-       ret
-
-lshift:
-       orb $0x01,mode
-       ret
-unlshift:
-       andb $0xfe,mode
-       ret
-rshift:
-       orb $0x02,mode
-       ret
-unrshift:
-       andb $0xfd,mode
-       ret
-
-caps:  testb $0x80,mode
-       jne 1f
-       xorb $4,leds
-       xorb $0x40,mode
-       orb $0x80,mode
-set_leds:
-       call kb_wait
-       movb $0xed,%al          /* set leds command */
-       outb %al,$0x60
-       call kb_wait
-       movb leds,%al
-       outb %al,$0x60
-       ret
-uncaps:        andb $0x7f,mode
-       ret
-scroll:
-       xorb $1,leds
-       jmp set_leds
-num:   xorb $2,leds
-       jmp set_leds
-
-/*
- *  curosr-key/numeric keypad cursor keys are handled here.
- *  checking for numeric keypad etc.
- */
-cursor:
-       subb $0x47,%al
-       jb 1f
-       cmpb $12,%al
-       ja 1f
-       jne cur2                /* check for ctrl-alt-del */
-       testb $0x0c,mode
-       je cur2
-       testb $0x30,mode
-       jne reboot
-cur2:  cmpb $0x01,e0           /* e0 forces cursor movement */
-       je cur
-       testb $0x02,leds        /* not num-lock forces cursor */
-       je cur
-       testb $0x03,mode        /* shift forces cursor */
-       jne cur
-       xorl %ebx,%ebx
-       movb num_table(%eax),%al
-       jmp put_queue
-1:     ret
-
-cur:   movb cur_table(%eax),%al
-       cmpb $'9,%al
-       ja ok_cur
-       movb $'~,%ah
-ok_cur:        shll $16,%eax
-       movw $0x5b1b,%ax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-num_table:
-       .ascii "789 456 1230,"
-cur_table:
-       .ascii "HA5 DGC YB623"
-
-/*
- * this routine handles function keys
- */
-func:
-       pushl %eax
-       pushl %ecx
-       pushl %edx
-       call _show_stat
-       popl %edx
-       popl %ecx
-       popl %eax
-       subb $0x3B,%al
-       jb end_func
-       cmpb $9,%al
-       jbe ok_func
-       subb $18,%al
-       cmpb $10,%al
-       jb end_func
-       cmpb $11,%al
-       ja end_func
-ok_func:
-       cmpl $4,%ecx            /* check that there is enough room */
-       jl end_func
-       movl func_table(,%eax,4),%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-end_func:
-       ret
-
-/*
- * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
- */
-func_table:
-       .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
-       .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
-       .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
-
-#if    defined(KBD_FINNISH)
-key_map:
-       .byte 0,27
-       .ascii "1234567890+'"
-       .byte 127,9
-       .ascii "qwertyuiop}"
-       .byte 0,13,0
-       .ascii "asdfghjkl|{"
-       .byte 0,0
-       .ascii "'zxcvbnm,.-"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-shift_map:
-       .byte 0,27
-       .ascii "!\"#$%&/()=?`"
-       .byte 127,9
-       .ascii "QWERTYUIOP]^"
-       .byte 13,0
-       .ascii "ASDFGHJKL\\["
-       .byte 0,0
-       .ascii "*ZXCVBNM;:_"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#elif defined(KBD_US)
-
-key_map:
-       .byte 0,27
-       .ascii "1234567890-="
-       .byte 127,9
-       .ascii "qwertyuiop[]"
-       .byte 13,0
-       .ascii "asdfghjkl;'"
-       .byte '`,0
-       .ascii "\\zxcvbnm,./"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-
-shift_map:
-       .byte 0,27
-       .ascii "!@@#$%^&*()_+"
-       .byte 127,9
-       .ascii "QWERTYUIOP{}"
-       .byte 13,0
-       .ascii "ASDFGHJKL:\""
-       .byte '~,0
-       .ascii "|ZXCVBNM<>?"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#else
-#error "KBD-type not defined"
-#endif
-/*
- * do_self handles "normal" keys, ie keys that don't change meaning
- * and which have just one character returns.
- */
-do_self:
-       lea alt_map,%ebx
-       testb $0x20,mode                /* alt-gr */
-       jne 1f
-       lea shift_map,%ebx
-       testb $0x03,mode
-       jne 1f
-       lea key_map,%ebx
-1:     movb (%ebx,%eax),%al
-       orb %al,%al
-       je none
-       testb $0x4c,mode                /* ctrl or caps */
-       je 2f
-       cmpb $'a,%al
-       jb 2f
-       cmpb $'},%al
-       ja 2f
-       subb $32,%al
-2:     testb $0x0c,mode                /* ctrl */
-       je 3f
-       cmpb $64,%al
-       jb 3f
-       cmpb $64+32,%al
-       jae 3f
-       subb $64,%al
-3:     testb $0x10,mode                /* left alt */
-       je 4f
-       orb $0x80,%al
-4:     andl $0xff,%eax
-       xorl %ebx,%ebx
-       call put_queue
-none:  ret
-
-/*
- * minus has a routine of it's own, as a 'E0h' before
- * the scan code for minus means that the numeric keypad
- * slash was pushed.
- */
-minus: cmpb $1,e0
-       jne do_self
-       movl $'/,%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-/*
- * This table decides which routine to call when a scan-code has been
- * gotten. Most routines just call do_self, or none, depending if
- * they are make or break.
- */
-key_table:
-       .long none,do_self,do_self,do_self      /* 00-03 s0 esc 1 2 */
-       .long do_self,do_self,do_self,do_self   /* 04-07 3 4 5 6 */
-       .long do_self,do_self,do_self,do_self   /* 08-0B 7 8 9 0 */
-       .long do_self,do_self,do_self,do_self   /* 0C-0F + ' bs tab */
-       .long do_self,do_self,do_self,do_self   /* 10-13 q w e r */
-       .long do_self,do_self,do_self,do_self   /* 14-17 t y u i */
-       .long do_self,do_self,do_self,do_self   /* 18-1B o p } ^ */
-       .long do_self,ctrl,do_self,do_self      /* 1C-1F enter ctrl a s */
-       .long do_self,do_self,do_self,do_self   /* 20-23 d f g h */
-       .long do_self,do_self,do_self,do_self   /* 24-27 j k l | */
-       .long do_self,do_self,lshift,do_self    /* 28-2B { para lshift , */
-       .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
-       .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
-       .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
-       .long alt,do_self,caps,func             /* 38-3B alt sp caps f1 */
-       .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
-       .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
-       .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
-       .long cursor,cursor,do_self,cursor      /* 48-4B up pgup - left */
-       .long cursor,cursor,do_self,cursor      /* 4C-4F n5 right + end */
-       .long cursor,cursor,cursor,cursor       /* 50-53 dn pgdn ins del */
-       .long none,none,do_self,func            /* 54-57 sysreq ? < f11 */
-       .long func,none,none,none               /* 58-5B f12 ? ? ? */
-       .long none,none,none,none               /* 5C-5F ? ? ? ? */
-       .long none,none,none,none               /* 60-63 ? ? ? ? */
-       .long none,none,none,none               /* 64-67 ? ? ? ? */
-       .long none,none,none,none               /* 68-6B ? ? ? ? */
-       .long none,none,none,none               /* 6C-6F ? ? ? ? */
-       .long none,none,none,none               /* 70-73 ? ? ? ? */
-       .long none,none,none,none               /* 74-77 ? ? ? ? */
-       .long none,none,none,none               /* 78-7B ? ? ? ? */
-       .long none,none,none,none               /* 7C-7F ? ? ? ? */
-       .long none,none,none,none               /* 80-83 ? br br br */
-       .long none,none,none,none               /* 84-87 br br br br */
-       .long none,none,none,none               /* 88-8B br br br br */
-       .long none,none,none,none               /* 8C-8F br br br br */
-       .long none,none,none,none               /* 90-93 br br br br */
-       .long none,none,none,none               /* 94-97 br br br br */
-       .long none,none,none,none               /* 98-9B br br br br */
-       .long none,unctrl,none,none             /* 9C-9F br unctrl br br */
-       .long none,none,none,none               /* A0-A3 br br br br */
-       .long none,none,none,none               /* A4-A7 br br br br */
-       .long none,none,unlshift,none           /* A8-AB br br unlshift br */
-       .long none,none,none,none               /* AC-AF br br br br */
-       .long none,none,none,none               /* B0-B3 br br br br */
-       .long none,none,unrshift,none           /* B4-B7 br br unrshift br */
-       .long unalt,none,uncaps,none            /* B8-BB unalt br uncaps br */
-       .long none,none,none,none               /* BC-BF br br br br */
-       .long none,none,none,none               /* C0-C3 br br br br */
-       .long none,none,none,none               /* C4-C7 br br br br */
-       .long none,none,none,none               /* C8-CB br br br br */
-       .long none,none,none,none               /* CC-CF br br br br */
-       .long none,none,none,none               /* D0-D3 br br br br */
-       .long none,none,none,none               /* D4-D7 br br br br */
-       .long none,none,none,none               /* D8-DB br ? ? ? */
-       .long none,none,none,none               /* DC-DF ? ? ? ? */
-       .long none,none,none,none               /* E0-E3 e0 e1 ? ? */
-       .long none,none,none,none               /* E4-E7 ? ? ? ? */
-       .long none,none,none,none               /* E8-EB ? ? ? ? */
-       .long none,none,none,none               /* EC-EF ? ? ? ? */
-       .long none,none,none,none               /* F0-F3 ? ? ? ? */
-       .long none,none,none,none               /* F4-F7 ? ? ? ? */
-       .long none,none,none,none               /* F8-FB ? ? ? ? */
-       .long none,none,none,none               /* FC-FF ? ? ? ? */
-
-/*
- * kb_wait waits for the keyboard controller buffer to empty.
- * there is no timeout - if the buffer doesn't empty, we hang.
- */
-kb_wait:
-       pushl %eax
-1:     inb $0x64,%al
-       testb $0x02,%al
-       jne 1b
-       popl %eax
-       ret
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low.
- */
-reboot:
-       call kb_wait
-       movw $0x1234,0x472      /* don't do memory check */
-       movb $0xfc,%al          /* pulse reset and A20 low */
-       outb %al,$0x64
-die:   jmp die
-@
index 3ca4169368df11ec9efdb556f5ee92b9dd4fba54..ae6bbdec13993b44491396c54ec4f8d9dabb7264 100644 (file)
@@ -12,6 +12,7 @@
  *     'void con_write(struct tty_queue * queue)'
  * Hopefully this will be a rather complete VT102 implementation.
  *
+ * Beeping thanks to John T Kohl.
  */
 
 /*
  * interrupt, as we use trap-gates. Hopefully all is well.
  */
 
+/*
+ * Code to check for different video-cards mostly by Galen Hunt,
+ * <g-hunt@ee.utah.edu>
+ */
+
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <asm/io.h>
 /*
  * These are set up by the setup-routine at boot-time:
  */
-#define ORIG_X (*(unsigned char *)0x90000)
-#define ORIG_Y (*(unsigned char *)0x90001)
 
-#define SCREEN_START 0xb8000
-#define SCREEN_END   0xc0000
-#define LINES 25
-#define COLUMNS 80
+#define ORIG_X                 (*(unsigned char *)0x90000)
+#define ORIG_Y                 (*(unsigned char *)0x90001)
+#define ORIG_VIDEO_PAGE                (*(unsigned short *)0x90004)
+#define ORIG_VIDEO_MODE                ((*(unsigned short *)0x90006) & 0xff)
+#define ORIG_VIDEO_COLS        (((*(unsigned short *)0x90006) & 0xff00) >> 8)
+#define ORIG_VIDEO_LINES       (25)
+#define ORIG_VIDEO_EGA_AX      (*(unsigned short *)0x90008)
+#define ORIG_VIDEO_EGA_BX      (*(unsigned short *)0x9000a)
+#define ORIG_VIDEO_EGA_CX      (*(unsigned short *)0x9000c)
+
+#define VIDEO_TYPE_MDA         0x10    /* Monochrome Text Display      */
+#define VIDEO_TYPE_CGA         0x11    /* CGA Display                  */
+#define VIDEO_TYPE_EGAM                0x20    /* EGA/VGA in Monochrome Mode   */
+#define VIDEO_TYPE_EGAC                0x21    /* EGA/VGA in Color Mode        */
+
 #define NPAR 16
 
 extern void keyboard_interrupt(void);
 
-static unsigned long origin=SCREEN_START;
-static unsigned long scr_end=SCREEN_START+LINES*COLUMNS*2;
-static unsigned long pos;
-static unsigned long x,y;
-static unsigned long top=0,bottom=LINES;
-static unsigned long lines=LINES,columns=COLUMNS;
-static unsigned long state=0;
-static unsigned long npar,par[NPAR];
-static unsigned long ques=0;
-static unsigned char attr=0x07;
+static unsigned char   video_type;             /* Type of display being used   */
+static unsigned long   video_num_columns;      /* Number of text columns       */
+static unsigned long   video_size_row;         /* Bytes per row                */
+static unsigned long   video_num_lines;        /* Number of test lines         */
+static unsigned char   video_page;             /* Initial video page           */
+static unsigned long   video_mem_start;        /* Start of video RAM           */
+static unsigned long   video_mem_end;          /* End of video RAM (sort of)   */
+static unsigned short  video_port_reg;         /* Video register select port   */
+static unsigned short  video_port_val;         /* Video register value port    */
+static unsigned short  video_erase_char;       /* Char+Attrib to erase with    */
+
+static unsigned long   origin;         /* Used for EGA/VGA fast scroll */
+static unsigned long   scr_end;        /* Used for EGA/VGA fast scroll */
+static unsigned long   pos;
+static unsigned long   x,y;
+static unsigned long   top,bottom;
+static unsigned long   state=0;
+static unsigned long   npar,par[NPAR];
+static unsigned long   ques=0;
+static unsigned char   attr=0x07;
+
+static void sysbeep(void);
 
 /*
  * this is what the terminal answers to a ESC-Z or csi0c
@@ -57,93 +84,128 @@ static unsigned char attr=0x07;
  */
 #define RESPONSE "\033[?1;2c"
 
-/* NOTE! gotoxy thinks x==columns is ok */
+/* NOTE! gotoxy thinks x==video_num_columns is ok */
 static inline void gotoxy(unsigned int new_x,unsigned int new_y)
 {
-       if (new_x > columns || new_y >= lines)
+       if (new_x > video_num_columns || new_y >= video_num_lines)
                return;
        x=new_x;
        y=new_y;
-       pos=origin+((y*columns+x)<<1);
+       pos=origin + y*video_size_row + (x<<1);
 }
 
 static inline void set_origin(void)
 {
        cli();
-       outb_p(12,0x3d4);
-       outb_p(0xff&((origin-SCREEN_START)>>9),0x3d5);
-       outb_p(13,0x3d4);
-       outb_p(0xff&((origin-SCREEN_START)>>1),0x3d5);
+       outb_p(12, video_port_reg);
+       outb_p(0xff&((origin-video_mem_start)>>9), video_port_val);
+       outb_p(13, video_port_reg);
+       outb_p(0xff&((origin-video_mem_start)>>1), video_port_val);
        sti();
 }
 
 static void scrup(void)
 {
-       if (!top && bottom==lines) {
-               origin += columns<<1;
-               pos += columns<<1;
-               scr_end += columns<<1;
-               if (scr_end>SCREEN_END) {
+       if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
+       {
+               if (!top && bottom == video_num_lines) {
+                       origin += video_size_row;
+                       pos += video_size_row;
+                       scr_end += video_size_row;
+                       if (scr_end > video_mem_end) {
+                               __asm__("cld\n\t"
+                                       "rep\n\t"
+                                       "movsl\n\t"
+                                       "movl _video_num_columns,%1\n\t"
+                                       "rep\n\t"
+                                       "stosw"
+                                       ::"a" (video_erase_char),
+                                       "c" ((video_num_lines-1)*video_num_columns>>1),
+                                       "D" (video_mem_start),
+                                       "S" (origin)
+                                       :"cx","di","si");
+                               scr_end -= origin-video_mem_start;
+                               pos -= origin-video_mem_start;
+                               origin = video_mem_start;
+                       } else {
+                               __asm__("cld\n\t"
+                                       "rep\n\t"
+                                       "stosw"
+                                       ::"a" (video_erase_char),
+                                       "c" (video_num_columns),
+                                       "D" (scr_end-video_size_row)
+                                       :"cx","di");
+                       }
+                       set_origin();
+               } else {
                        __asm__("cld\n\t"
                                "rep\n\t"
                                "movsl\n\t"
-                               "movl _columns,%1\n\t"
+                               "movl _video_num_columns,%%ecx\n\t"
                                "rep\n\t"
                                "stosw"
-                               ::"a" (0x0720),
-                               "c" ((lines-1)*columns>>1),
-                               "D" (SCREEN_START),
-                               "S" (origin)
+                               ::"a" (video_erase_char),
+                               "c" ((bottom-top-1)*video_num_columns>>1),
+                               "D" (origin+video_size_row*top),
+                               "S" (origin+video_size_row*(top+1))
                                :"cx","di","si");
-                       scr_end -= origin-SCREEN_START;
-                       pos -= origin-SCREEN_START;
-                       origin = SCREEN_START;
-               } else {
-                       __asm__("cld\n\t"
-                               "rep\n\t"
-                               "stosl"
-                               ::"a" (0x07200720),
-                               "c" (columns>>1),
-                               "D" (scr_end-(columns<<1))
-                               :"cx","di");
                }
-               set_origin();
-       } else {
+       }
+       else            /* Not EGA/VGA */
+       {
                __asm__("cld\n\t"
                        "rep\n\t"
                        "movsl\n\t"
-                       "movl _columns,%%ecx\n\t"
+                       "movl _video_num_columns,%%ecx\n\t"
                        "rep\n\t"
                        "stosw"
-                       ::"a" (0x0720),
-                       "c" ((bottom-top-1)*columns>>1),
-                       "D" (origin+(columns<<1)*top),
-                       "S" (origin+(columns<<1)*(top+1))
+                       ::"a" (video_erase_char),
+                       "c" ((bottom-top-1)*video_num_columns>>1),
+                       "D" (origin+video_size_row*top),
+                       "S" (origin+video_size_row*(top+1))
                        :"cx","di","si");
        }
 }
 
 static void scrdown(void)
 {
-       __asm__("std\n\t"
-               "rep\n\t"
-               "movsl\n\t"
-               "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
-               "movl _columns,%%ecx\n\t"
-               "rep\n\t"
-               "stosw"
-               ::"a" (0x0720),
-               "c" ((bottom-top-1)*columns>>1),
-               "D" (origin+(columns<<1)*bottom-4),
-               "S" (origin+(columns<<1)*(bottom-1)-4)
-               :"ax","cx","di","si");
+       if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
+       {
+               __asm__("std\n\t"
+                       "rep\n\t"
+                       "movsl\n\t"
+                       "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
+                       "movl _video_num_columns,%%ecx\n\t"
+                       "rep\n\t"
+                       "stosw"
+                       ::"a" (video_erase_char),
+                       "c" ((bottom-top-1)*video_num_columns>>1),
+                       "D" (origin+video_size_row*bottom-4),
+                       "S" (origin+video_size_row*(bottom-1)-4)
+                       :"ax","cx","di","si");
+       }
+       else            /* Not EGA/VGA */
+       {
+               __asm__("std\n\t"
+                       "rep\n\t"
+                       "movsl\n\t"
+                       "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
+                       "movl _video_num_columns,%%ecx\n\t"
+                       "rep\n\t"
+                       "stosw"
+                       ::"a" (video_erase_char),
+                       "c" ((bottom-top-1)*video_num_columns>>1),
+                       "D" (origin+video_size_row*bottom-4),
+                       "S" (origin+video_size_row*(bottom-1)-4)
+                       :"ax","cx","di","si");
+       }
 }
 
 static void lf(void)
 {
        if (y+1<bottom) {
                y++;
-               pos += columns<<1;
+               pos += video_size_row;
                return;
        }
        scrup();
@@ -153,7 +215,7 @@ static void ri(void)
 {
        if (y>top) {
                y--;
-               pos -= columns<<1;
+               pos -= video_size_row;
                return;
        }
        scrdown();
@@ -170,7 +232,7 @@ static void del(void)
        if (x) {
                pos -= 2;
                x--;
-               *(unsigned short *)pos = 0x0720;
+               *(unsigned short *)pos = video_erase_char;
        }
 }
 
@@ -189,7 +251,7 @@ static void csi_J(int par)
                        start = origin;
                        break;
                case 2: /* erase whole display */
-                       count = columns*lines;
+                       count = video_num_columns * video_num_lines;
                        start = origin;
                        break;
                default:
@@ -199,7 +261,7 @@ static void csi_J(int par)
                "rep\n\t"
                "stosw\n\t"
                ::"c" (count),
-               "D" (start),"a" (0x0720)
+               "D" (start),"a" (video_erase_char)
                :"cx","di");
 }
 
@@ -210,18 +272,18 @@ static void csi_K(int par)
 
        switch (par) {
                case 0: /* erase from cursor to end of line */
-                       if (x>=columns)
+                       if (x>=video_num_columns)
                                return;
-                       count = columns-x;
+                       count = video_num_columns-x;
                        start = pos;
                        break;
                case 1: /* erase from start of line to cursor */
                        start = pos - (x<<1);
-                       count = (x<columns)?x:columns;
+                       count = (x<video_num_columns)?x:video_num_columns;
                        break;
                case 2: /* erase whole line */
                        start = pos - (x<<1);
-                       count = columns;
+                       count = video_num_columns;
                        break;
                default:
                        return;
@@ -230,7 +292,7 @@ static void csi_K(int par)
                "rep\n\t"
                "stosw\n\t"
                ::"c" (count),
-               "D" (start),"a" (0x0720)
+               "D" (start),"a" (video_erase_char)
                :"cx","di");
 }
 
@@ -251,10 +313,10 @@ void csi_m(void)
 static inline void set_cursor(void)
 {
        cli();
-       outb_p(14,0x3d4);
-       outb_p(0xff&((pos-SCREEN_START)>>9),0x3d5);
-       outb_p(15,0x3d4);
-       outb_p(0xff&((pos-SCREEN_START)>>1),0x3d5);
+       outb_p(14, video_port_reg);
+       outb_p(0xff&((pos-video_mem_start)>>9), video_port_val);
+       outb_p(15, video_port_reg);
+       outb_p(0xff&((pos-video_mem_start)>>1), video_port_val);
        sti();
 }
 
@@ -274,10 +336,10 @@ static void respond(struct tty_struct * tty)
 static void insert_char(void)
 {
        int i=x;
-       unsigned short tmp,old=0x0720;
+       unsigned short tmp, old = video_erase_char;
        unsigned short * p = (unsigned short *) pos;
 
-       while (i++<columns) {
+       while (i++<video_num_columns) {
                tmp=*p;
                *p=old;
                old=tmp;
@@ -292,7 +354,7 @@ static void insert_line(void)
        oldtop=top;
        oldbottom=bottom;
        top=y;
-       bottom=lines;
+       bottom = video_num_lines;
        scrdown();
        top=oldtop;
        bottom=oldbottom;
@@ -303,14 +365,14 @@ static void delete_char(void)
        int i;
        unsigned short * p = (unsigned short *) pos;
 
-       if (x>=columns)
+       if (x>=video_num_columns)
                return;
        i = x;
-       while (++i < columns) {
+       while (++i < video_num_columns) {
                *p = *(p+1);
                p++;
        }
-       *p=0x0720;
+       *p = video_erase_char;
 }
 
 static void delete_line(void)
@@ -320,7 +382,7 @@ static void delete_line(void)
        oldtop=top;
        oldbottom=bottom;
        top=y;
-       bottom=lines;
+       bottom = video_num_lines;
        scrup();
        top=oldtop;
        bottom=oldbottom;
@@ -328,38 +390,38 @@ static void delete_line(void)
 
 static void csi_at(unsigned int nr)
 {
-       if (nr>columns)
-               nr=columns;
+       if (nr > video_num_columns)
+               nr = video_num_columns;
        else if (!nr)
-               nr=1;
+               nr = 1;
        while (nr--)
                insert_char();
 }
 
 static void csi_L(unsigned int nr)
 {
-       if (nr>lines)
-               nr=lines;
+       if (nr > video_num_lines)
+               nr = video_num_lines;
        else if (!nr)
-               nr=1;
+               nr = 1;
        while (nr--)
                insert_line();
 }
 
 static void csi_P(unsigned int nr)
 {
-       if (nr>columns)
-               nr=columns;
+       if (nr > video_num_columns)
+               nr = video_num_columns;
        else if (!nr)
-               nr=1;
+               nr = 1;
        while (nr--)
                delete_char();
 }
 
 static void csi_M(unsigned int nr)
 {
-       if (nr>lines)
-               nr=lines;
+       if (nr > video_num_lines)
+               nr = video_num_lines;
        else if (!nr)
                nr=1;
        while (nr--)
@@ -391,9 +453,9 @@ void con_write(struct tty_struct * tty)
                switch(state) {
                        case 0:
                                if (c>31 && c<127) {
-                                       if (x>=columns) {
-                                               x -= columns;
-                                               pos -= columns<<1;
+                                       if (x>=video_num_columns) {
+                                               x -= video_num_columns;
+                                               pos -= video_size_row;
                                                lf();
                                        }
                                        __asm__("movb _attr,%%ah\n\t"
@@ -419,13 +481,14 @@ void con_write(struct tty_struct * tty)
                                        c=8-(x&7);
                                        x += c;
                                        pos += c<<1;
-                                       if (x>columns) {
-                                               x -= columns;
-                                               pos -= columns<<1;
+                                       if (x>video_num_columns) {
+                                               x -= video_num_columns;
+                                               pos -= video_size_row;
                                                lf();
                                        }
                                        c=9;
-                               }
+                               } else if (c==7)
+                                       sysbeep();
                                break;
                        case 1:
                                state=0;
@@ -522,9 +585,9 @@ void con_write(struct tty_struct * tty)
                                                break;
                                        case 'r':
                                                if (par[0]) par[0]--;
-                                               if (!par[1]) par[1]=lines;
+                                               if (!par[1]) par[1] = video_num_lines;
                                                if (par[0] < par[1] &&
-                                                   par[1] <= lines) {
+                                                   par[1] <= video_num_lines) {
                                                        top=par[0];
                                                        bottom=par[1];
                                                }
@@ -547,10 +610,74 @@ void con_write(struct tty_struct * tty)
  * This routine initalizes console interrupts, and does nothing
  * else. If you want the screen to clear, call tty_write with
  * the appropriate escape-sequece.
+ *
+ * Reads the information preserved by setup.s to determine the current display
+ * type and sets everything accordingly.
  */
 void con_init(void)
 {
        register unsigned char a;
+       char *display_desc = "????";
+       char *display_ptr;
+
+       video_num_columns = ORIG_VIDEO_COLS;
+       video_size_row = video_num_columns * 2;
+       video_num_lines = ORIG_VIDEO_LINES;
+       video_page = ORIG_VIDEO_PAGE;
+       video_erase_char = 0x0720;
+       
+       if (ORIG_VIDEO_MODE == 7)                       /* Is this a monochrome display? */
+       {
+               video_mem_start = 0xb0000;
+               video_port_reg = 0x3b4;
+               video_port_val = 0x3b5;
+               if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
+               {
+                       video_type = VIDEO_TYPE_EGAM;
+                       video_mem_end = 0xb8000;
+                       display_desc = "EGAm";
+               }
+               else
+               {
+                       video_type = VIDEO_TYPE_MDA;
+                       video_mem_end   = 0xb2000;
+                       display_desc = "*MDA";
+               }
+       }
+       else                                                            /* If not, it is color. */
+       {
+               video_mem_start = 0xb8000;
+               video_port_reg  = 0x3d4;
+               video_port_val  = 0x3d5;
+               if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
+               {
+                       video_type = VIDEO_TYPE_EGAC;
+                       video_mem_end = 0xbc000;
+                       display_desc = "EGAc";
+               }
+               else
+               {
+                       video_type = VIDEO_TYPE_CGA;
+                       video_mem_end = 0xba000;
+                       display_desc = "*CGA";
+               }
+       }
+
+       /* Let the user known what kind of display driver we are using */
+       
+       display_ptr = ((char *)video_mem_start) + video_size_row - 8;
+       while (*display_desc)
+       {
+               *display_ptr++ = *display_desc++;
+               display_ptr++;
+       }
+       
+       /* Initialize the variables used for scrolling (mostly EGA/VGA) */
+       
+       origin  = video_mem_start;
+       scr_end = video_mem_start + video_num_lines * video_size_row;
+       top     = 0;
+       bottom  = video_num_lines;
 
        gotoxy(ORIG_X,ORIG_Y);
        set_trap_gate(0x21,&keyboard_interrupt);
@@ -559,3 +686,25 @@ void con_init(void)
        outb_p(a|0x80,0x61);
        outb(a,0x61);
 }
+/* from bsd-net-2: */
+
+void sysbeepstop(void)
+{
+       /* disable counter 2 */
+       outb(inb_p(0x61)&0xFC, 0x61);
+}
+
+int beepcount = 0;
+
+static void sysbeep(void)
+{
+       /* enable counter 2 */
+       outb_p(inb_p(0x61)|3, 0x61);
+       /* set command for counter 2, 2 byte write */
+       outb_p(0xB6, 0x43);
+       /* send 0x637 for 750 HZ */
+       outb_p(0x37, 0x42);
+       outb(0x06, 0x42);
+       /* 1/8 second */
+       beepcount = HZ/8;       
+}
index 120ca121019e8ae6dd3356333749f808a2290ae7..709ef9a0625bddb7eb7043634358a93cc1a149bc 100644 (file)
@@ -6,6 +6,8 @@
 
 /*
  *     Thanks to Alfred Leung for US keyboard patches
+ *             Wolfgang Thiel for German keyboard patches
+ *             Marc Corsini for the French keyboard
  */
 
 #include <linux/config.h>
@@ -26,7 +28,6 @@ buf = 16
 mode:  .byte 0         /* caps, alt, ctrl and shift mode */
 leds:  .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
 e0:    .byte 0
-flags: .byte 0         /* 0x1 - map caps lock to ctrl */
 
 /*
  *  con_int is the real interrupt routine that reads the
@@ -138,9 +139,7 @@ unrshift:
        andb $0xfd,mode
        ret
 
-caps:  testb $0x1,flags
-       je ctrl
-       testb $0x80,mode
+caps:  testb $0x80,mode
        jne 1f
        xorb $4,leds
        xorb $0x40,mode
@@ -153,9 +152,7 @@ set_leds:
        movb leds,%al
        outb %al,$0x60
        ret
-uncaps:        testb $0x1,flags
-       je unctrl
-       andb $0x7f,mode
+uncaps:        andb $0x7f,mode
        ret
 scroll:
        xorb $1,leds
@@ -197,8 +194,13 @@ ok_cur:    shll $16,%eax
        xorl %ebx,%ebx
        jmp put_queue
 
+#if defined(KBD_FR)
+num_table:
+       .ascii "789 456 1230."
+#else
 num_table:
        .ascii "789 456 1230,"
+#endif
 cur_table:
        .ascii "HA5 DGC YB623"
 
@@ -339,6 +341,108 @@ alt_map:
        .byte '|
        .fill 10,1,0
 
+#elif defined(KBD_GR)
+
+key_map:
+       .byte 0,27
+       .ascii "1234567890\\'"
+       .byte 127,9
+       .ascii "qwertzuiop@+"
+       .byte 13,0
+       .ascii "asdfghjkl[]^"
+       .byte 0,'#
+       .ascii "yxcvbnm,.-"
+       .byte 0,'*,0,32         /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte '-,0,0,0,'+       /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '<
+       .fill 10,1,0
+
+
+shift_map:
+       .byte 0,27
+       .ascii "!\"#$%&/()=?`"
+       .byte 127,9
+       .ascii "QWERTZUIOP\\*"
+       .byte 13,0
+       .ascii "ASDFGHJKL{}~"
+       .byte 0,''
+       .ascii "YXCVBNM;:_"
+       .byte 0,'*,0,32         /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte '-,0,0,0,'+       /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '>
+       .fill 10,1,0
+
+alt_map:
+       .byte 0,0
+       .ascii "\0@\0$\0\0{[]}\\\0"
+       .byte 0,0
+       .byte '@,0,0,0,0,0,0,0,0,0,0
+       .byte '~,13,0
+       .byte 0,0,0,0,0,0,0,0,0,0,0
+       .byte 0,0
+       .byte 0,0,0,0,0,0,0,0,0,0,0
+       .byte 0,0,0,0           /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte 0,0,0,0,0         /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '|
+       .fill 10,1,0
+
+
+#elif defined(KBD_FR)
+
+key_map:
+       .byte 0,27
+       .ascii "&{\"'(-}_/@)="
+       .byte 127,9
+       .ascii "azertyuiop^$"
+       .byte 13,0
+       .ascii "qsdfghjklm|"
+       .byte '`,0,42           /* coin sup gauche, don't know, [*|mu] */
+       .ascii "wxcvbn,;:!"
+       .byte 0,'*,0,32         /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte '-,0,0,0,'+       /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '<
+       .fill 10,1,0
+
+shift_map:
+       .byte 0,27
+       .ascii "1234567890]+"
+       .byte 127,9
+       .ascii "AZERTYUIOP<>"
+       .byte 13,0
+       .ascii "QSDFGHJKLM%"
+       .byte '~,0,'#
+       .ascii "WXCVBN?./\\"
+       .byte 0,'*,0,32         /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte '-,0,0,0,'+       /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '>
+       .fill 10,1,0
+
+alt_map:
+       .byte 0,0
+       .ascii "\0~#{[|`\\^@]}"
+       .byte 0,0
+       .byte '@,0,0,0,0,0,0,0,0,0,0
+       .byte '~,13,0
+       .byte 0,0,0,0,0,0,0,0,0,0,0
+       .byte 0,0
+       .byte 0,0,0,0,0,0,0,0,0,0,0
+       .byte 0,0,0,0           /* 36-39 */
+       .fill 16,1,0            /* 3A-49 */
+       .byte 0,0,0,0,0         /* 4A-4E */
+       .byte 0,0,0,0,0,0,0     /* 4F-55 */
+       .byte '|
+       .fill 10,1,0
+
 #else
 #error "KBD-type not defined"
 #endif
@@ -389,19 +493,6 @@ minus:     cmpb $1,e0
        movl $'/,%eax
        xorl %ebx,%ebx
        jmp put_queue
-/*
- * do_space handles ctrl-space as an ASCII NUL.  Old habits die hard.
- */
-do_space:
-       testb $0x04,mode                /* ctrl */
-       je do_self
-       testb $0x03,mode                /* shift */
-       jne 1f
-       xorb $0x01, flags               /* toggle caps lock flag */
-       ret
-1f:    movl $0,%al                     /* ASCII NUL */
-       xorl %ebx,%ebx
-       jmp put_queue
 
 /*
  * This table decides which routine to call when a scan-code has been
@@ -423,7 +514,7 @@ key_table:
        .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
        .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
        .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
-       .long alt,do_space,caps,func            /* 38-3B alt sp caps f1 */
+       .long alt,do_self,caps,func             /* 38-3B alt sp caps f1 */
        .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
        .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
        .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
diff --git a/kernel/chr_drv/keyboard.S.jtkohl b/kernel/chr_drv/keyboard.S.jtkohl
deleted file mode 100644 (file)
index 76774a5..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- *  linux/kernel/keyboard.S
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *     Thanks to Alfred Leung for US keyboard patches
- */
-
-#include <linux/config.h>
-
-.text
-.globl _keyboard_interrupt
-
-/*
- * these are for the keyboard read functions
- */
-size   = 1024          /* must be a power of two ! And MUST be the same
-                          as in tty_io.c !!!! */
-head = 4
-tail = 8
-proc_list = 12
-buf = 16
-
-mode:  .byte 0         /* caps, alt, ctrl and shift mode */
-leds:  .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
-e0:    .byte 0
-
-/*
- *  con_int is the real interrupt routine that reads the
- *  keyboard scan-code and converts it into the appropriate
- *  ascii character(s).
- */
-_keyboard_interrupt:
-       pushl %eax
-       pushl %ebx
-       pushl %ecx
-       pushl %edx
-       push %ds
-       push %es
-       movl $0x10,%eax
-       mov %ax,%ds
-       mov %ax,%es
-       xorl %al,%al            /* %eax is scan code */
-       inb $0x60,%al
-       cmpb $0xe0,%al
-       je set_e0
-       cmpb $0xe1,%al
-       je set_e1
-       call key_table(,%eax,4)
-       movb $0,e0
-e0_e1: inb $0x61,%al
-       jmp 1f
-1:     jmp 1f
-1:     orb $0x80,%al
-       jmp 1f
-1:     jmp 1f
-1:     outb %al,$0x61
-       jmp 1f
-1:     jmp 1f
-1:     andb $0x7F,%al
-       outb %al,$0x61
-       movb $0x20,%al
-       outb %al,$0x20
-       pushl $0
-       call _do_tty_interrupt
-       addl $4,%esp
-       pop %es
-       pop %ds
-       popl %edx
-       popl %ecx
-       popl %ebx
-       popl %eax
-       iret
-set_e0:        movb $1,e0
-       jmp e0_e1
-set_e1:        movb $2,e0
-       jmp e0_e1
-
-/*
- * This routine fills the buffer with max 8 bytes, taken from
- * %ebx:%eax. (%edx is high). The bytes are written in the
- * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
- */
-put_queue:
-       pushl %ecx
-       pushl %edx
-       movl _table_list,%edx           # read-queue for console
-       movl head(%edx),%ecx
-1:     movb %al,buf(%edx,%ecx)
-       incl %ecx
-       andl $size-1,%ecx
-       cmpl tail(%edx),%ecx            # buffer full - discard everything
-       je 3f
-       shrdl $8,%ebx,%eax
-       je 2f
-       shrl $8,%ebx
-       jmp 1b
-2:     movl %ecx,head(%edx)
-       movl proc_list(%edx),%ecx
-       testl %ecx,%ecx
-       je 3f
-       movl $0,(%ecx)
-3:     popl %edx
-       popl %ecx
-       ret
-
-ctrl:  movb $0x04,%al
-       jmp 1f
-alt:   movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     orb %al,mode
-       ret
-unctrl:        movb $0x04,%al
-       jmp 1f
-unalt: movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     notb %al
-       andb %al,mode
-       ret
-
-lshift:
-       orb $0x01,mode
-       ret
-unlshift:
-       andb $0xfe,mode
-       ret
-rshift:
-       orb $0x02,mode
-       ret
-unrshift:
-       andb $0xfd,mode
-       ret
-
-caps:  testb $0x80,mode
-       jne 1f
-       xorb $4,leds
-       xorb $0x40,mode
-       orb $0x80,mode
-set_leds:
-       call kb_wait
-       movb $0xed,%al          /* set leds command */
-       outb %al,$0x60
-       call kb_wait
-       movb leds,%al
-       outb %al,$0x60
-       ret
-uncaps:        andb $0x7f,mode
-       ret
-scroll:
-       xorb $1,leds
-       jmp set_leds
-num:   xorb $2,leds
-       jmp set_leds
-
-/*
- *  curosr-key/numeric keypad cursor keys are handled here.
- *  checking for numeric keypad etc.
- */
-cursor:
-       subb $0x47,%al
-       jb 1f
-       cmpb $12,%al
-       ja 1f
-       jne cur2                /* check for ctrl-alt-del */
-       testb $0x0c,mode
-       je cur2
-       testb $0x30,mode
-       jne reboot
-cur2:  cmpb $0x01,e0           /* e0 forces cursor movement */
-       je cur
-       testb $0x02,leds        /* not num-lock forces cursor */
-       je cur
-       testb $0x03,mode        /* shift forces cursor */
-       jne cur
-       xorl %ebx,%ebx
-       movb num_table(%eax),%al
-       jmp put_queue
-1:     ret
-
-cur:   movb cur_table(%eax),%al
-       cmpb $'9,%al
-       ja ok_cur
-       movb $'~,%ah
-ok_cur:        shll $16,%eax
-       movw $0x5b1b,%ax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-num_table:
-       .ascii "789 456 1230,"
-cur_table:
-       .ascii "HA5 DGC YB623"
-
-/*
- * this routine handles function keys
- */
-func:
-       pushl %eax
-       pushl %ecx
-       pushl %edx
-       call _show_stat
-       popl %edx
-       popl %ecx
-       popl %eax
-       subb $0x3B,%al
-       jb end_func
-       cmpb $9,%al
-       jbe ok_func
-       subb $18,%al
-       cmpb $10,%al
-       jb end_func
-       cmpb $11,%al
-       ja end_func
-ok_func:
-       cmpl $4,%ecx            /* check that there is enough room */
-       jl end_func
-       movl func_table(,%eax,4),%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-end_func:
-       ret
-
-/*
- * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
- */
-func_table:
-       .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
-       .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
-       .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
-
-#if    defined(KBD_FINNISH)
-key_map:
-       .byte 0,27
-       .ascii "1234567890+'"
-       .byte 127,9
-       .ascii "qwertyuiop}"
-       .byte 0,13,0
-       .ascii "asdfghjkl|{"
-       .byte 0,0
-       .ascii "'zxcvbnm,.-"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-shift_map:
-       .byte 0,27
-       .ascii "!\"#$%&/()=?`"
-       .byte 127,9
-       .ascii "QWERTYUIOP]^"
-       .byte 13,0
-       .ascii "ASDFGHJKL\\["
-       .byte 0,0
-       .ascii "*ZXCVBNM;:_"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#elif defined(KBD_US)
-
-key_map:
-       .byte 0,27
-       .ascii "1234567890-="
-       .byte 127,9
-       .ascii "qwertyuiop[]"
-       .byte 13,0
-       .ascii "asdfghjkl;'"
-       .byte '`,0
-       .ascii "\\zxcvbnm,./"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-
-shift_map:
-       .byte 0,27
-       .ascii "!@#$%^&*()_+"
-       .byte 127,9
-       .ascii "QWERTYUIOP{}"
-       .byte 13,0
-       .ascii "ASDFGHJKL:\""
-       .byte '~,0
-       .ascii "|ZXCVBNM<>?"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#else
-#error "KBD-type not defined"
-#endif
-/*
- * do_self handles "normal" keys, ie keys that don't change meaning
- * and which have just one character returns.
- */
-do_self:
-       lea alt_map,%ebx
-       testb $0x20,mode                /* alt-gr */
-       jne 1f
-       lea shift_map,%ebx
-       testb $0x03,mode
-       jne 1f
-       lea key_map,%ebx
-1:     movb (%ebx,%eax),%al
-       orb %al,%al
-       je none
-       testb $0x4c,mode                /* ctrl or caps */
-       je 2f
-       cmpb $'a,%al
-       jb 2f
-       cmpb $'},%al
-       ja 2f
-       subb $32,%al
-2:     testb $0x0c,mode                /* ctrl */
-       je 3f
-       cmpb $64,%al
-       jb 3f
-       cmpb $64+32,%al
-       jae 3f
-       subb $64,%al
-3:     testb $0x10,mode                /* left alt */
-       je 4f
-       orb $0x80,%al
-4:     andl $0xff,%eax
-       xorl %ebx,%ebx
-       call put_queue
-none:  ret
-
-/*
- * minus has a routine of it's own, as a 'E0h' before
- * the scan code for minus means that the numeric keypad
- * slash was pushed.
- */
-minus: cmpb $1,e0
-       jne do_self
-       movl $'/,%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-/*
- * do_space handles ctrl-space as an ASCII NUL.  Old habits die hard.
- */
-do_space:
-       testb $0x04,mode                /* ctrl */
-       je do_self
-       movl $0,%al                     /* ASCII NUL */
-       xorl %ebx,%ebx
-       jmp put_queue
-
-/*
- * This table decides which routine to call when a scan-code has been
- * gotten. Most routines just call do_self, or none, depending if
- * they are make or break.
- */
-key_table:
-       .long none,do_self,do_self,do_self      /* 00-03 s0 esc 1 2 */
-       .long do_self,do_self,do_self,do_self   /* 04-07 3 4 5 6 */
-       .long do_self,do_self,do_self,do_self   /* 08-0B 7 8 9 0 */
-       .long do_self,do_self,do_self,do_self   /* 0C-0F + ' bs tab */
-       .long do_self,do_self,do_self,do_self   /* 10-13 q w e r */
-       .long do_self,do_self,do_self,do_self   /* 14-17 t y u i */
-       .long do_self,do_self,do_self,do_self   /* 18-1B o p } ^ */
-       .long do_self,ctrl,do_self,do_self      /* 1C-1F enter ctrl a s */
-       .long do_self,do_self,do_self,do_self   /* 20-23 d f g h */
-       .long do_self,do_self,do_self,do_self   /* 24-27 j k l | */
-       .long do_self,do_self,lshift,do_self    /* 28-2B { para lshift , */
-       .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
-       .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
-       .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
-       .long alt,do_space,ctrl,func            /* 38-3B alt sp caps f1 */
-       .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
-       .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
-       .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
-       .long cursor,cursor,do_self,cursor      /* 48-4B up pgup - left */
-       .long cursor,cursor,do_self,cursor      /* 4C-4F n5 right + end */
-       .long cursor,cursor,cursor,cursor       /* 50-53 dn pgdn ins del */
-       .long none,none,do_self,func            /* 54-57 sysreq ? < f11 */
-       .long func,none,none,none               /* 58-5B f12 ? ? ? */
-       .long none,none,none,none               /* 5C-5F ? ? ? ? */
-       .long none,none,none,none               /* 60-63 ? ? ? ? */
-       .long none,none,none,none               /* 64-67 ? ? ? ? */
-       .long none,none,none,none               /* 68-6B ? ? ? ? */
-       .long none,none,none,none               /* 6C-6F ? ? ? ? */
-       .long none,none,none,none               /* 70-73 ? ? ? ? */
-       .long none,none,none,none               /* 74-77 ? ? ? ? */
-       .long none,none,none,none               /* 78-7B ? ? ? ? */
-       .long none,none,none,none               /* 7C-7F ? ? ? ? */
-       .long none,none,none,none               /* 80-83 ? br br br */
-       .long none,none,none,none               /* 84-87 br br br br */
-       .long none,none,none,none               /* 88-8B br br br br */
-       .long none,none,none,none               /* 8C-8F br br br br */
-       .long none,none,none,none               /* 90-93 br br br br */
-       .long none,none,none,none               /* 94-97 br br br br */
-       .long none,none,none,none               /* 98-9B br br br br */
-       .long none,unctrl,none,none             /* 9C-9F br unctrl br br */
-       .long none,none,none,none               /* A0-A3 br br br br */
-       .long none,none,none,none               /* A4-A7 br br br br */
-       .long none,none,unlshift,none           /* A8-AB br br unlshift br */
-       .long none,none,none,none               /* AC-AF br br br br */
-       .long none,none,none,none               /* B0-B3 br br br br */
-       .long none,none,unrshift,none           /* B4-B7 br br unrshift br */
-       .long unalt,none,unctrl,none            /* B8-BB unalt br uncaps br */
-       .long none,none,none,none               /* BC-BF br br br br */
-       .long none,none,none,none               /* C0-C3 br br br br */
-       .long none,none,none,none               /* C4-C7 br br br br */
-       .long none,none,none,none               /* C8-CB br br br br */
-       .long none,none,none,none               /* CC-CF br br br br */
-       .long none,none,none,none               /* D0-D3 br br br br */
-       .long none,none,none,none               /* D4-D7 br br br br */
-       .long none,none,none,none               /* D8-DB br ? ? ? */
-       .long none,none,none,none               /* DC-DF ? ? ? ? */
-       .long none,none,none,none               /* E0-E3 e0 e1 ? ? */
-       .long none,none,none,none               /* E4-E7 ? ? ? ? */
-       .long none,none,none,none               /* E8-EB ? ? ? ? */
-       .long none,none,none,none               /* EC-EF ? ? ? ? */
-       .long none,none,none,none               /* F0-F3 ? ? ? ? */
-       .long none,none,none,none               /* F4-F7 ? ? ? ? */
-       .long none,none,none,none               /* F8-FB ? ? ? ? */
-       .long none,none,none,none               /* FC-FF ? ? ? ? */
-
-/*
- * kb_wait waits for the keyboard controller buffer to empty.
- * there is no timeout - if the buffer doesn't empty, we hang.
- */
-kb_wait:
-       pushl %eax
-1:     inb $0x64,%al
-       testb $0x02,%al
-       jne 1b
-       popl %eax
-       ret
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low.
- */
-reboot:
-       call kb_wait
-       movw $0x1234,0x472      /* don't do memory check */
-       movb $0xfc,%al          /* pulse reset and A20 low */
-       outb %al,$0x64
-die:   jmp die
diff --git a/kernel/chr_drv/keyboard.S.orig.orig b/kernel/chr_drv/keyboard.S.orig.orig
deleted file mode 100644 (file)
index 4b22d0a..0000000
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- *  linux/kernel/keyboard.S
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *     Thanks to Alfred Leung for US keyboard patches
- */
-
-#include <linux/config.h>
-
-.text
-.globl _keyboard_interrupt
-
-/*
- * these are for the keyboard read functions
- */
-size   = 1024          /* must be a power of two ! And MUST be the same
-                          as in tty_io.c !!!! */
-head = 4
-tail = 8
-proc_list = 12
-buf = 16
-
-mode:  .byte 0         /* caps, alt, ctrl and shift mode */
-leds:  .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
-e0:    .byte 0
-
-/*
- *  con_int is the real interrupt routine that reads the
- *  keyboard scan-code and converts it into the appropriate
- *  ascii character(s).
- */
-_keyboard_interrupt:
-       pushl %eax
-       pushl %ebx
-       pushl %ecx
-       pushl %edx
-       push %ds
-       push %es
-       movl $0x10,%eax
-       mov %ax,%ds
-       mov %ax,%es
-       xorl %al,%al            /* %eax is scan code */
-       inb $0x60,%al
-       cmpb $0xe0,%al
-       je set_e0
-       cmpb $0xe1,%al
-       je set_e1
-       call key_table(,%eax,4)
-       movb $0,e0
-e0_e1: inb $0x61,%al
-       jmp 1f
-1:     jmp 1f
-1:     orb $0x80,%al
-       jmp 1f
-1:     jmp 1f
-1:     outb %al,$0x61
-       jmp 1f
-1:     jmp 1f
-1:     andb $0x7F,%al
-       outb %al,$0x61
-       movb $0x20,%al
-       outb %al,$0x20
-       pushl $0
-       call _do_tty_interrupt
-       addl $4,%esp
-       pop %es
-       pop %ds
-       popl %edx
-       popl %ecx
-       popl %ebx
-       popl %eax
-       iret
-set_e0:        movb $1,e0
-       jmp e0_e1
-set_e1:        movb $2,e0
-       jmp e0_e1
-
-/*
- * This routine fills the buffer with max 8 bytes, taken from
- * %ebx:%eax. (%edx is high). The bytes are written in the
- * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
- */
-put_queue:
-       pushl %ecx
-       pushl %edx
-       movl _table_list,%edx           # read-queue for console
-       movl head(%edx),%ecx
-1:     movb %al,buf(%edx,%ecx)
-       incl %ecx
-       andl $size-1,%ecx
-       cmpl tail(%edx),%ecx            # buffer full - discard everything
-       je 3f
-       shrdl $8,%ebx,%eax
-       je 2f
-       shrl $8,%ebx
-       jmp 1b
-2:     movl %ecx,head(%edx)
-       movl proc_list(%edx),%ecx
-       testl %ecx,%ecx
-       je 3f
-       movl $0,(%ecx)
-3:     popl %edx
-       popl %ecx
-       ret
-
-ctrl:  movb $0x04,%al
-       jmp 1f
-alt:   movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     orb %al,mode
-       ret
-unctrl:        movb $0x04,%al
-       jmp 1f
-unalt: movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     notb %al
-       andb %al,mode
-       ret
-
-lshift:
-       orb $0x01,mode
-       ret
-unlshift:
-       andb $0xfe,mode
-       ret
-rshift:
-       orb $0x02,mode
-       ret
-unrshift:
-       andb $0xfd,mode
-       ret
-
-caps:  testb $0x80,mode
-       jne 1f
-       xorb $4,leds
-       xorb $0x40,mode
-       orb $0x80,mode
-set_leds:
-       call kb_wait
-       movb $0xed,%al          /* set leds command */
-       outb %al,$0x60
-       call kb_wait
-       movb leds,%al
-       outb %al,$0x60
-       ret
-uncaps:        andb $0x7f,mode
-       ret
-scroll:
-       xorb $1,leds
-       jmp set_leds
-num:   xorb $2,leds
-       jmp set_leds
-
-/*
- *  curosr-key/numeric keypad cursor keys are handled here.
- *  checking for numeric keypad etc.
- */
-cursor:
-       subb $0x47,%al
-       jb 1f
-       cmpb $12,%al
-       ja 1f
-       jne cur2                /* check for ctrl-alt-del */
-       testb $0x0c,mode
-       je cur2
-       testb $0x30,mode
-       jne reboot
-cur2:  cmpb $0x01,e0           /* e0 forces cursor movement */
-       je cur
-       testb $0x02,leds        /* not num-lock forces cursor */
-       je cur
-       testb $0x03,mode        /* shift forces cursor */
-       jne cur
-       xorl %ebx,%ebx
-       movb num_table(%eax),%al
-       jmp put_queue
-1:     ret
-
-cur:   movb cur_table(%eax),%al
-       cmpb $'9,%al
-       ja ok_cur
-       movb $'~,%ah
-ok_cur:        shll $16,%eax
-       movw $0x5b1b,%ax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-num_table:
-       .ascii "789 456 1230,"
-cur_table:
-       .ascii "HA5 DGC YB623"
-
-/*
- * this routine handles function keys
- */
-func:
-       pushl %eax
-       pushl %ecx
-       pushl %edx
-       call _show_stat
-       popl %edx
-       popl %ecx
-       popl %eax
-       subb $0x3B,%al
-       jb end_func
-       cmpb $9,%al
-       jbe ok_func
-       subb $18,%al
-       cmpb $10,%al
-       jb end_func
-       cmpb $11,%al
-       ja end_func
-ok_func:
-       cmpl $4,%ecx            /* check that there is enough room */
-       jl end_func
-       movl func_table(,%eax,4),%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-end_func:
-       ret
-
-/*
- * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
- */
-func_table:
-       .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
-       .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
-       .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
-
-#if    defined(KBD_FINNISH)
-key_map:
-       .byte 0,27
-       .ascii "1234567890+'"
-       .byte 127,9
-       .ascii "qwertyuiop}"
-       .byte 0,13,0
-       .ascii "asdfghjkl|{"
-       .byte 0,0
-       .ascii "'zxcvbnm,.-"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-shift_map:
-       .byte 0,27
-       .ascii "!\"#$%&/()=?`"
-       .byte 127,9
-       .ascii "QWERTYUIOP]^"
-       .byte 13,0
-       .ascii "ASDFGHJKL\\["
-       .byte 0,0
-       .ascii "*ZXCVBNM;:_"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#elif defined(KBD_US)
-
-key_map:
-       .byte 0,27
-       .ascii "1234567890-="
-       .byte 127,9
-       .ascii "qwertyuiop[]"
-       .byte 13,0
-       .ascii "asdfghjkl;'"
-       .byte '`,0
-       .ascii "\\zxcvbnm,./"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-
-shift_map:
-       .byte 0,27
-       .ascii "!@#$%^&*()_+"
-       .byte 127,9
-       .ascii "QWERTYUIOP{}"
-       .byte 13,0
-       .ascii "ASDFGHJKL:\""
-       .byte '~,0
-       .ascii "|ZXCVBNM<>?"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#else
-#error "KBD-type not defined"
-#endif
-/*
- * do_self handles "normal" keys, ie keys that don't change meaning
- * and which have just one character returns.
- */
-do_self:
-       lea alt_map,%ebx
-       testb $0x20,mode                /* alt-gr */
-       jne 1f
-       lea shift_map,%ebx
-       testb $0x03,mode
-       jne 1f
-       lea key_map,%ebx
-1:     movb (%ebx,%eax),%al
-       orb %al,%al
-       je none
-       testb $0x4c,mode                /* ctrl or caps */
-       je 2f
-       cmpb $'a,%al
-       jb 2f
-       cmpb $'},%al
-       ja 2f
-       subb $32,%al
-2:     testb $0x0c,mode                /* ctrl */
-       je 3f
-       cmpb $64,%al
-       jb 3f
-       cmpb $64+32,%al
-       jae 3f
-       subb $64,%al
-3:     testb $0x10,mode                /* left alt */
-       je 4f
-       orb $0x80,%al
-4:     andl $0xff,%eax
-       xorl %ebx,%ebx
-       call put_queue
-none:  ret
-
-/*
- * minus has a routine of it's own, as a 'E0h' before
- * the scan code for minus means that the numeric keypad
- * slash was pushed.
- */
-minus: cmpb $1,e0
-       jne do_self
-       movl $'/,%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-/*
- * This table decides which routine to call when a scan-code has been
- * gotten. Most routines just call do_self, or none, depending if
- * they are make or break.
- */
-key_table:
-       .long none,do_self,do_self,do_self      /* 00-03 s0 esc 1 2 */
-       .long do_self,do_self,do_self,do_self   /* 04-07 3 4 5 6 */
-       .long do_self,do_self,do_self,do_self   /* 08-0B 7 8 9 0 */
-       .long do_self,do_self,do_self,do_self   /* 0C-0F + ' bs tab */
-       .long do_self,do_self,do_self,do_self   /* 10-13 q w e r */
-       .long do_self,do_self,do_self,do_self   /* 14-17 t y u i */
-       .long do_self,do_self,do_self,do_self   /* 18-1B o p } ^ */
-       .long do_self,ctrl,do_self,do_self      /* 1C-1F enter ctrl a s */
-       .long do_self,do_self,do_self,do_self   /* 20-23 d f g h */
-       .long do_self,do_self,do_self,do_self   /* 24-27 j k l | */
-       .long do_self,do_self,lshift,do_self    /* 28-2B { para lshift , */
-       .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
-       .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
-       .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
-       .long alt,do_self,caps,func             /* 38-3B alt sp caps f1 */
-       .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
-       .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
-       .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
-       .long cursor,cursor,do_self,cursor      /* 48-4B up pgup - left */
-       .long cursor,cursor,do_self,cursor      /* 4C-4F n5 right + end */
-       .long cursor,cursor,cursor,cursor       /* 50-53 dn pgdn ins del */
-       .long none,none,do_self,func            /* 54-57 sysreq ? < f11 */
-       .long func,none,none,none               /* 58-5B f12 ? ? ? */
-       .long none,none,none,none               /* 5C-5F ? ? ? ? */
-       .long none,none,none,none               /* 60-63 ? ? ? ? */
-       .long none,none,none,none               /* 64-67 ? ? ? ? */
-       .long none,none,none,none               /* 68-6B ? ? ? ? */
-       .long none,none,none,none               /* 6C-6F ? ? ? ? */
-       .long none,none,none,none               /* 70-73 ? ? ? ? */
-       .long none,none,none,none               /* 74-77 ? ? ? ? */
-       .long none,none,none,none               /* 78-7B ? ? ? ? */
-       .long none,none,none,none               /* 7C-7F ? ? ? ? */
-       .long none,none,none,none               /* 80-83 ? br br br */
-       .long none,none,none,none               /* 84-87 br br br br */
-       .long none,none,none,none               /* 88-8B br br br br */
-       .long none,none,none,none               /* 8C-8F br br br br */
-       .long none,none,none,none               /* 90-93 br br br br */
-       .long none,none,none,none               /* 94-97 br br br br */
-       .long none,none,none,none               /* 98-9B br br br br */
-       .long none,unctrl,none,none             /* 9C-9F br unctrl br br */
-       .long none,none,none,none               /* A0-A3 br br br br */
-       .long none,none,none,none               /* A4-A7 br br br br */
-       .long none,none,unlshift,none           /* A8-AB br br unlshift br */
-       .long none,none,none,none               /* AC-AF br br br br */
-       .long none,none,none,none               /* B0-B3 br br br br */
-       .long none,none,unrshift,none           /* B4-B7 br br unrshift br */
-       .long unalt,none,uncaps,none            /* B8-BB unalt br uncaps br */
-       .long none,none,none,none               /* BC-BF br br br br */
-       .long none,none,none,none               /* C0-C3 br br br br */
-       .long none,none,none,none               /* C4-C7 br br br br */
-       .long none,none,none,none               /* C8-CB br br br br */
-       .long none,none,none,none               /* CC-CF br br br br */
-       .long none,none,none,none               /* D0-D3 br br br br */
-       .long none,none,none,none               /* D4-D7 br br br br */
-       .long none,none,none,none               /* D8-DB br ? ? ? */
-       .long none,none,none,none               /* DC-DF ? ? ? ? */
-       .long none,none,none,none               /* E0-E3 e0 e1 ? ? */
-       .long none,none,none,none               /* E4-E7 ? ? ? ? */
-       .long none,none,none,none               /* E8-EB ? ? ? ? */
-       .long none,none,none,none               /* EC-EF ? ? ? ? */
-       .long none,none,none,none               /* F0-F3 ? ? ? ? */
-       .long none,none,none,none               /* F4-F7 ? ? ? ? */
-       .long none,none,none,none               /* F8-FB ? ? ? ? */
-       .long none,none,none,none               /* FC-FF ? ? ? ? */
-
-/*
- * kb_wait waits for the keyboard controller buffer to empty.
- * there is no timeout - if the buffer doesn't empty, we hang.
- */
-kb_wait:
-       pushl %eax
-1:     inb $0x64,%al
-       testb $0x02,%al
-       jne 1b
-       popl %eax
-       ret
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low.
- */
-reboot:
-       call kb_wait
-       movw $0x1234,0x472      /* don't do memory check */
-       movb $0xfc,%al          /* pulse reset and A20 low */
-       outb %al,$0x64
-die:   jmp die
diff --git a/kernel/chr_drv/keyboard.S~ b/kernel/chr_drv/keyboard.S~
deleted file mode 100644 (file)
index 76774a5..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- *  linux/kernel/keyboard.S
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *     Thanks to Alfred Leung for US keyboard patches
- */
-
-#include <linux/config.h>
-
-.text
-.globl _keyboard_interrupt
-
-/*
- * these are for the keyboard read functions
- */
-size   = 1024          /* must be a power of two ! And MUST be the same
-                          as in tty_io.c !!!! */
-head = 4
-tail = 8
-proc_list = 12
-buf = 16
-
-mode:  .byte 0         /* caps, alt, ctrl and shift mode */
-leds:  .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
-e0:    .byte 0
-
-/*
- *  con_int is the real interrupt routine that reads the
- *  keyboard scan-code and converts it into the appropriate
- *  ascii character(s).
- */
-_keyboard_interrupt:
-       pushl %eax
-       pushl %ebx
-       pushl %ecx
-       pushl %edx
-       push %ds
-       push %es
-       movl $0x10,%eax
-       mov %ax,%ds
-       mov %ax,%es
-       xorl %al,%al            /* %eax is scan code */
-       inb $0x60,%al
-       cmpb $0xe0,%al
-       je set_e0
-       cmpb $0xe1,%al
-       je set_e1
-       call key_table(,%eax,4)
-       movb $0,e0
-e0_e1: inb $0x61,%al
-       jmp 1f
-1:     jmp 1f
-1:     orb $0x80,%al
-       jmp 1f
-1:     jmp 1f
-1:     outb %al,$0x61
-       jmp 1f
-1:     jmp 1f
-1:     andb $0x7F,%al
-       outb %al,$0x61
-       movb $0x20,%al
-       outb %al,$0x20
-       pushl $0
-       call _do_tty_interrupt
-       addl $4,%esp
-       pop %es
-       pop %ds
-       popl %edx
-       popl %ecx
-       popl %ebx
-       popl %eax
-       iret
-set_e0:        movb $1,e0
-       jmp e0_e1
-set_e1:        movb $2,e0
-       jmp e0_e1
-
-/*
- * This routine fills the buffer with max 8 bytes, taken from
- * %ebx:%eax. (%edx is high). The bytes are written in the
- * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
- */
-put_queue:
-       pushl %ecx
-       pushl %edx
-       movl _table_list,%edx           # read-queue for console
-       movl head(%edx),%ecx
-1:     movb %al,buf(%edx,%ecx)
-       incl %ecx
-       andl $size-1,%ecx
-       cmpl tail(%edx),%ecx            # buffer full - discard everything
-       je 3f
-       shrdl $8,%ebx,%eax
-       je 2f
-       shrl $8,%ebx
-       jmp 1b
-2:     movl %ecx,head(%edx)
-       movl proc_list(%edx),%ecx
-       testl %ecx,%ecx
-       je 3f
-       movl $0,(%ecx)
-3:     popl %edx
-       popl %ecx
-       ret
-
-ctrl:  movb $0x04,%al
-       jmp 1f
-alt:   movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     orb %al,mode
-       ret
-unctrl:        movb $0x04,%al
-       jmp 1f
-unalt: movb $0x10,%al
-1:     cmpb $0,e0
-       je 2f
-       addb %al,%al
-2:     notb %al
-       andb %al,mode
-       ret
-
-lshift:
-       orb $0x01,mode
-       ret
-unlshift:
-       andb $0xfe,mode
-       ret
-rshift:
-       orb $0x02,mode
-       ret
-unrshift:
-       andb $0xfd,mode
-       ret
-
-caps:  testb $0x80,mode
-       jne 1f
-       xorb $4,leds
-       xorb $0x40,mode
-       orb $0x80,mode
-set_leds:
-       call kb_wait
-       movb $0xed,%al          /* set leds command */
-       outb %al,$0x60
-       call kb_wait
-       movb leds,%al
-       outb %al,$0x60
-       ret
-uncaps:        andb $0x7f,mode
-       ret
-scroll:
-       xorb $1,leds
-       jmp set_leds
-num:   xorb $2,leds
-       jmp set_leds
-
-/*
- *  curosr-key/numeric keypad cursor keys are handled here.
- *  checking for numeric keypad etc.
- */
-cursor:
-       subb $0x47,%al
-       jb 1f
-       cmpb $12,%al
-       ja 1f
-       jne cur2                /* check for ctrl-alt-del */
-       testb $0x0c,mode
-       je cur2
-       testb $0x30,mode
-       jne reboot
-cur2:  cmpb $0x01,e0           /* e0 forces cursor movement */
-       je cur
-       testb $0x02,leds        /* not num-lock forces cursor */
-       je cur
-       testb $0x03,mode        /* shift forces cursor */
-       jne cur
-       xorl %ebx,%ebx
-       movb num_table(%eax),%al
-       jmp put_queue
-1:     ret
-
-cur:   movb cur_table(%eax),%al
-       cmpb $'9,%al
-       ja ok_cur
-       movb $'~,%ah
-ok_cur:        shll $16,%eax
-       movw $0x5b1b,%ax
-       xorl %ebx,%ebx
-       jmp put_queue
-
-num_table:
-       .ascii "789 456 1230,"
-cur_table:
-       .ascii "HA5 DGC YB623"
-
-/*
- * this routine handles function keys
- */
-func:
-       pushl %eax
-       pushl %ecx
-       pushl %edx
-       call _show_stat
-       popl %edx
-       popl %ecx
-       popl %eax
-       subb $0x3B,%al
-       jb end_func
-       cmpb $9,%al
-       jbe ok_func
-       subb $18,%al
-       cmpb $10,%al
-       jb end_func
-       cmpb $11,%al
-       ja end_func
-ok_func:
-       cmpl $4,%ecx            /* check that there is enough room */
-       jl end_func
-       movl func_table(,%eax,4),%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-end_func:
-       ret
-
-/*
- * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
- */
-func_table:
-       .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
-       .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
-       .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
-
-#if    defined(KBD_FINNISH)
-key_map:
-       .byte 0,27
-       .ascii "1234567890+'"
-       .byte 127,9
-       .ascii "qwertyuiop}"
-       .byte 0,13,0
-       .ascii "asdfghjkl|{"
-       .byte 0,0
-       .ascii "'zxcvbnm,.-"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-shift_map:
-       .byte 0,27
-       .ascii "!\"#$%&/()=?`"
-       .byte 127,9
-       .ascii "QWERTYUIOP]^"
-       .byte 13,0
-       .ascii "ASDFGHJKL\\["
-       .byte 0,0
-       .ascii "*ZXCVBNM;:_"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#elif defined(KBD_US)
-
-key_map:
-       .byte 0,27
-       .ascii "1234567890-="
-       .byte 127,9
-       .ascii "qwertyuiop[]"
-       .byte 13,0
-       .ascii "asdfghjkl;'"
-       .byte '`,0
-       .ascii "\\zxcvbnm,./"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '<
-       .fill 10,1,0
-
-
-shift_map:
-       .byte 0,27
-       .ascii "!@#$%^&*()_+"
-       .byte 127,9
-       .ascii "QWERTYUIOP{}"
-       .byte 13,0
-       .ascii "ASDFGHJKL:\""
-       .byte '~,0
-       .ascii "|ZXCVBNM<>?"
-       .byte 0,'*,0,32         /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte '-,0,0,0,'+       /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '>
-       .fill 10,1,0
-
-alt_map:
-       .byte 0,0
-       .ascii "\0@\0$\0\0{[]}\\\0"
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte '~,13,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0
-       .byte 0,0,0,0,0,0,0,0,0,0,0
-       .byte 0,0,0,0           /* 36-39 */
-       .fill 16,1,0            /* 3A-49 */
-       .byte 0,0,0,0,0         /* 4A-4E */
-       .byte 0,0,0,0,0,0,0     /* 4F-55 */
-       .byte '|
-       .fill 10,1,0
-
-#else
-#error "KBD-type not defined"
-#endif
-/*
- * do_self handles "normal" keys, ie keys that don't change meaning
- * and which have just one character returns.
- */
-do_self:
-       lea alt_map,%ebx
-       testb $0x20,mode                /* alt-gr */
-       jne 1f
-       lea shift_map,%ebx
-       testb $0x03,mode
-       jne 1f
-       lea key_map,%ebx
-1:     movb (%ebx,%eax),%al
-       orb %al,%al
-       je none
-       testb $0x4c,mode                /* ctrl or caps */
-       je 2f
-       cmpb $'a,%al
-       jb 2f
-       cmpb $'},%al
-       ja 2f
-       subb $32,%al
-2:     testb $0x0c,mode                /* ctrl */
-       je 3f
-       cmpb $64,%al
-       jb 3f
-       cmpb $64+32,%al
-       jae 3f
-       subb $64,%al
-3:     testb $0x10,mode                /* left alt */
-       je 4f
-       orb $0x80,%al
-4:     andl $0xff,%eax
-       xorl %ebx,%ebx
-       call put_queue
-none:  ret
-
-/*
- * minus has a routine of it's own, as a 'E0h' before
- * the scan code for minus means that the numeric keypad
- * slash was pushed.
- */
-minus: cmpb $1,e0
-       jne do_self
-       movl $'/,%eax
-       xorl %ebx,%ebx
-       jmp put_queue
-/*
- * do_space handles ctrl-space as an ASCII NUL.  Old habits die hard.
- */
-do_space:
-       testb $0x04,mode                /* ctrl */
-       je do_self
-       movl $0,%al                     /* ASCII NUL */
-       xorl %ebx,%ebx
-       jmp put_queue
-
-/*
- * This table decides which routine to call when a scan-code has been
- * gotten. Most routines just call do_self, or none, depending if
- * they are make or break.
- */
-key_table:
-       .long none,do_self,do_self,do_self      /* 00-03 s0 esc 1 2 */
-       .long do_self,do_self,do_self,do_self   /* 04-07 3 4 5 6 */
-       .long do_self,do_self,do_self,do_self   /* 08-0B 7 8 9 0 */
-       .long do_self,do_self,do_self,do_self   /* 0C-0F + ' bs tab */
-       .long do_self,do_self,do_self,do_self   /* 10-13 q w e r */
-       .long do_self,do_self,do_self,do_self   /* 14-17 t y u i */
-       .long do_self,do_self,do_self,do_self   /* 18-1B o p } ^ */
-       .long do_self,ctrl,do_self,do_self      /* 1C-1F enter ctrl a s */
-       .long do_self,do_self,do_self,do_self   /* 20-23 d f g h */
-       .long do_self,do_self,do_self,do_self   /* 24-27 j k l | */
-       .long do_self,do_self,lshift,do_self    /* 28-2B { para lshift , */
-       .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
-       .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
-       .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
-       .long alt,do_space,ctrl,func            /* 38-3B alt sp caps f1 */
-       .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
-       .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
-       .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
-       .long cursor,cursor,do_self,cursor      /* 48-4B up pgup - left */
-       .long cursor,cursor,do_self,cursor      /* 4C-4F n5 right + end */
-       .long cursor,cursor,cursor,cursor       /* 50-53 dn pgdn ins del */
-       .long none,none,do_self,func            /* 54-57 sysreq ? < f11 */
-       .long func,none,none,none               /* 58-5B f12 ? ? ? */
-       .long none,none,none,none               /* 5C-5F ? ? ? ? */
-       .long none,none,none,none               /* 60-63 ? ? ? ? */
-       .long none,none,none,none               /* 64-67 ? ? ? ? */
-       .long none,none,none,none               /* 68-6B ? ? ? ? */
-       .long none,none,none,none               /* 6C-6F ? ? ? ? */
-       .long none,none,none,none               /* 70-73 ? ? ? ? */
-       .long none,none,none,none               /* 74-77 ? ? ? ? */
-       .long none,none,none,none               /* 78-7B ? ? ? ? */
-       .long none,none,none,none               /* 7C-7F ? ? ? ? */
-       .long none,none,none,none               /* 80-83 ? br br br */
-       .long none,none,none,none               /* 84-87 br br br br */
-       .long none,none,none,none               /* 88-8B br br br br */
-       .long none,none,none,none               /* 8C-8F br br br br */
-       .long none,none,none,none               /* 90-93 br br br br */
-       .long none,none,none,none               /* 94-97 br br br br */
-       .long none,none,none,none               /* 98-9B br br br br */
-       .long none,unctrl,none,none             /* 9C-9F br unctrl br br */
-       .long none,none,none,none               /* A0-A3 br br br br */
-       .long none,none,none,none               /* A4-A7 br br br br */
-       .long none,none,unlshift,none           /* A8-AB br br unlshift br */
-       .long none,none,none,none               /* AC-AF br br br br */
-       .long none,none,none,none               /* B0-B3 br br br br */
-       .long none,none,unrshift,none           /* B4-B7 br br unrshift br */
-       .long unalt,none,unctrl,none            /* B8-BB unalt br uncaps br */
-       .long none,none,none,none               /* BC-BF br br br br */
-       .long none,none,none,none               /* C0-C3 br br br br */
-       .long none,none,none,none               /* C4-C7 br br br br */
-       .long none,none,none,none               /* C8-CB br br br br */
-       .long none,none,none,none               /* CC-CF br br br br */
-       .long none,none,none,none               /* D0-D3 br br br br */
-       .long none,none,none,none               /* D4-D7 br br br br */
-       .long none,none,none,none               /* D8-DB br ? ? ? */
-       .long none,none,none,none               /* DC-DF ? ? ? ? */
-       .long none,none,none,none               /* E0-E3 e0 e1 ? ? */
-       .long none,none,none,none               /* E4-E7 ? ? ? ? */
-       .long none,none,none,none               /* E8-EB ? ? ? ? */
-       .long none,none,none,none               /* EC-EF ? ? ? ? */
-       .long none,none,none,none               /* F0-F3 ? ? ? ? */
-       .long none,none,none,none               /* F4-F7 ? ? ? ? */
-       .long none,none,none,none               /* F8-FB ? ? ? ? */
-       .long none,none,none,none               /* FC-FF ? ? ? ? */
-
-/*
- * kb_wait waits for the keyboard controller buffer to empty.
- * there is no timeout - if the buffer doesn't empty, we hang.
- */
-kb_wait:
-       pushl %eax
-1:     inb $0x64,%al
-       testb $0x02,%al
-       jne 1b
-       popl %eax
-       ret
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low.
- */
-reboot:
-       call kb_wait
-       movw $0x1234,0x472      /* don't do memory check */
-       movb $0xfc,%al          /* pulse reset and A20 low */
-       outb %al,$0x64
-die:   jmp die
index ec92914a6fe065db61e7083ecd62a6d36dbf5970..b8da64355a1ccb90f52e04a5ad6ac2749a33215c 100644 (file)
@@ -6,8 +6,9 @@
 
 /*
  * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
- * or rs-channels. It also implements echoing, cooked mode etc (well,
- * not currently, but ...)
+ * or rs-channels. It also implements echoing, cooked mode etc.
+ *
+ * Kill-line thanks to John T Kohl.
  */
 #include <ctype.h>
 #include <errno.h>
 
 struct tty_struct tty_table[] = {
        {
-               {ICRNL,
+               {ICRNL,         /* change incoming CR to NL */
                OPOST|ONLCR,    /* change outgoing NL to CRNL */
                0,
-               ICANON | ECHO | ECHOCTL | ECHOKE,
+               ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
                0,              /* console termio */
                INIT_C_CC},
                0,                      /* initial pgrp */
@@ -62,8 +63,8 @@ struct tty_struct tty_table[] = {
                {0,0,0,0,""},           /* console write-queue */
                {0,0,0,0,""}            /* console secondary queue */
        },{
-               {0, /*IGNCR*/
-               OPOST | ONLRET,         /* change outgoing NL to CR */
+               {0, /* no translation */
+               0,  /* no translation */
                B2400 | CS8,
                0,
                0,
@@ -75,8 +76,8 @@ struct tty_struct tty_table[] = {
                {0x3f8,0,0,0,""},
                {0,0,0,0,""}
        },{
-               {0, /*IGNCR*/
-               OPOST | ONLRET,         /* change outgoing NL to CR */
+               {0, /* no translation */
+               0,  /* no translation */
                B2400 | CS8,
                0,
                0,
@@ -158,6 +159,21 @@ void copy_to_cooked(struct tty_struct * tty)
                if (I_UCLC(tty))
                        c=tolower(c);
                if (L_CANON(tty)) {
+                       if (c==KILL_CHAR(tty)) {
+                               /* deal with killing the input line */
+                               while(!(EMPTY(tty->secondary) ||
+                                       (c=LAST(tty->secondary))==10 ||
+                                       c==EOF_CHAR(tty))) {
+                                       if (L_ECHO(tty)) {
+                                               if (c<32)
+                                                       PUTCH(127,tty->write_q);
+                                               PUTCH(127,tty->write_q);
+                                               tty->write(tty);
+                                       }
+                                       DEC(tty->secondary.head);
+                               }
+                               continue;
+                       }
                        if (c==ERASE_CHAR(tty)) {
                                if (EMPTY(tty->secondary) ||
                                   (c=LAST(tty->secondary))==10 ||
@@ -181,13 +197,13 @@ void copy_to_cooked(struct tty_struct * tty)
                                continue;
                        }
                }
-               if (!L_ISIG(tty)) {
+               if (L_ISIG(tty)) {
                        if (c==INTR_CHAR(tty)) {
                                tty_intr(tty,INTMASK);
                                continue;
                        }
-                       if (c==KILL_CHAR(tty)) {
-                               tty_intr(tty,KILLMASK);
+                       if (c==QUIT_CHAR(tty)) {
+                               tty_intr(tty,QUITMASK);
                                continue;
                        }
                }
@@ -221,8 +237,8 @@ int tty_read(unsigned channel, char * buf, int nr)
        if (channel>2 || nr<0) return -1;
        tty = &tty_table[channel];
        oldalarm = current->alarm;
-       time = (unsigned) 10*tty->termios.c_cc[VTIME];
-       minimum = (unsigned) tty->termios.c_cc[VMIN];
+       time = 10L*tty->termios.c_cc[VTIME];
+       minimum = tty->termios.c_cc[VMIN];
        if (time && !minimum) {
                minimum=1;
                if (flag=(!oldalarm || time+jiffies<oldalarm))
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
new file mode 100644 (file)
index 0000000..e4e3745
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *  linux/kernel/chr_drv/tty_ioctl.c
+ *
+ *  (C) 1991  Linus Torvalds
+ */
+
+#include <errno.h>
+#include <termios.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+static unsigned short quotient[] = {
+       0, 2304, 1536, 1047, 857,
+       768, 576, 384, 192, 96,
+       64, 48, 24, 12, 6, 3
+};
+
+static void change_speed(struct tty_struct * tty)
+{
+       unsigned short port,quot;
+
+       if (!(port = tty->read_q.data))
+               return;
+       quot = quotient[tty->termios.c_cflag & CBAUD];
+       cli();
+       outb_p(0x80,port+3);            /* set DLAB */
+       outb_p(quot & 0xff,port);       /* LS of divisor */
+       outb_p(quot >> 8,port+1);       /* MS of divisor */
+       outb(0x03,port+3);              /* reset DLAB */
+       sti();
+}
+
+static void flush(struct tty_queue * queue)
+{
+       cli();
+       queue->head = queue->tail;
+       sti();
+}
+
+static void wait_until_sent(struct tty_struct * tty)
+{
+       /* do nothing - not implemented */
+}
+
+static void send_break(struct tty_struct * tty)
+{
+       /* do nothing - not implemented */
+}
+
+static int get_termios(struct tty_struct * tty, struct termios * termios)
+{
+       int i;
+
+       verify_area(termios, sizeof (*termios));
+       for (i=0 ; i< (sizeof (*termios)) ; i++)
+               put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
+       return 0;
+}
+
+static int set_termios(struct tty_struct * tty, struct termios * termios)
+{
+       int i;
+
+       for (i=0 ; i< (sizeof (*termios)) ; i++)
+               ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
+       change_speed(tty);
+       return 0;
+}
+
+static int get_termio(struct tty_struct * tty, struct termio * termio)
+{
+       int i;
+       struct termio tmp_termio;
+
+       verify_area(termio, sizeof (*termio));
+       tmp_termio.c_iflag = tty->termios.c_iflag;
+       tmp_termio.c_oflag = tty->termios.c_oflag;
+       tmp_termio.c_cflag = tty->termios.c_cflag;
+       tmp_termio.c_lflag = tty->termios.c_lflag;
+       tmp_termio.c_line = tty->termios.c_line;
+       for(i=0 ; i < NCC ; i++)
+               tmp_termio.c_cc[i] = tty->termios.c_cc[i];
+       for (i=0 ; i< (sizeof (*termio)) ; i++)
+               put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
+       return 0;
+}
+
+/*
+ * This only works as the 386 is low-byt-first
+ */
+static int set_termio(struct tty_struct * tty, struct termio * termio)
+{
+       int i;
+       struct termio tmp_termio;
+
+       for (i=0 ; i< (sizeof (*termio)) ; i++)
+               ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
+       *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
+       *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
+       *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
+       *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
+       tty->termios.c_line = tmp_termio.c_line;
+       for(i=0 ; i < NCC ; i++)
+               tty->termios.c_cc[i] = tmp_termio.c_cc[i];
+       change_speed(tty);
+       return 0;
+}
+
+int tty_ioctl(int dev, int cmd, int arg)
+{
+       struct tty_struct * tty;
+       if (MAJOR(dev) == 5) {
+               dev=current->tty;
+               if (dev<0)
+                       panic("tty_ioctl: dev<0");
+       } else
+               dev=MINOR(dev);
+       tty = dev + tty_table;
+       switch (cmd) {
+               case TCGETS:
+                       return get_termios(tty,(struct termios *) arg);
+               case TCSETSF:
+                       flush(&tty->read_q); /* fallthrough */
+               case TCSETSW:
+                       wait_until_sent(tty); /* fallthrough */
+               case TCSETS:
+                       return set_termios(tty,(struct termios *) arg);
+               case TCGETA:
+                       return get_termio(tty,(struct termio *) arg);
+               case TCSETAF:
+                       flush(&tty->read_q); /* fallthrough */
+               case TCSETAW:
+                       wait_until_sent(tty); /* fallthrough */
+               case TCSETA:
+                       return set_termio(tty,(struct termio *) arg);
+               case TCSBRK:
+                       if (!arg) {
+                               wait_until_sent(tty);
+                               send_break(tty);
+                       }
+                       return 0;
+               case TCXONC:
+                       return -EINVAL; /* not implemented */
+               case TCFLSH:
+                       if (arg==0)
+                               flush(&tty->read_q);
+                       else if (arg==1)
+                               flush(&tty->write_q);
+                       else if (arg==2) {
+                               flush(&tty->read_q);
+                               flush(&tty->write_q);
+                       } else
+                               return -EINVAL;
+                       return 0;
+               case TIOCEXCL:
+                       return -EINVAL; /* not implemented */
+               case TIOCNXCL:
+                       return -EINVAL; /* not implemented */
+               case TIOCSCTTY:
+                       return -EINVAL; /* set controlling term NI */
+               case TIOCGPGRP:
+                       verify_area((void *) arg,4);
+                       put_fs_long(tty->pgrp,(unsigned long *) arg);
+                       return 0;
+               case TIOCSPGRP:
+                       tty->pgrp=get_fs_long((unsigned long *) arg);
+                       return 0;
+               case TIOCOUTQ:
+                       verify_area((void *) arg,4);
+                       put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
+                       return 0;
+               case TIOCINQ:
+                       verify_area((void *) arg,4);
+                       put_fs_long(CHARS(tty->secondary),
+                               (unsigned long *) arg);
+                       return 0;
+               case TIOCSTI:
+                       return -EINVAL; /* not implemented */
+               case TIOCGWINSZ:
+                       return -EINVAL; /* not implemented */
+               case TIOCSWINSZ:
+                       return -EINVAL; /* not implemented */
+               case TIOCMGET:
+                       return -EINVAL; /* not implemented */
+               case TIOCMBIS:
+                       return -EINVAL; /* not implemented */
+               case TIOCMBIC:
+                       return -EINVAL; /* not implemented */
+               case TIOCMSET:
+                       return -EINVAL; /* not implemented */
+               case TIOCGSOFTCAR:
+                       return -EINVAL; /* not implemented */
+               case TIOCSSOFTCAR:
+                       return -EINVAL; /* not implemented */
+               default:
+                       return -EINVAL;
+       }
+}
index 1b0aa030431123ff3aa117285c0fbec54982a990..2406ebe0175522b883d2ecd3df14b0079d8cf40e 100644 (file)
@@ -94,6 +94,8 @@ static void tell_father(int pid)
                        return;
                }
 /* if we don't find any fathers, we just release ourselves */
+/* This is not really OK. Must change it to make father 1 */
+       printk("BAD BAD - no father found\n\r");
        release(current);
 }
 
@@ -104,8 +106,12 @@ int do_exit(long code)
        free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
        free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
        for (i=0 ; i<NR_TASKS ; i++)
-               if (task[i] && task[i]->father == current->pid)
-                       task[i]->father = 0;
+               if (task[i] && task[i]->father == current->pid) {
+                       task[i]->father = 1;
+                       if (task[i]->state == TASK_ZOMBIE)
+                               /* assumption task[1] is always init */
+                               (void) send_sig(SIGCHLD, task[1], 1);
+               }
        for (i=0 ; i<NR_OPEN ; i++)
                if (current->filp[i])
                        sys_close(i);
@@ -113,6 +119,8 @@ int do_exit(long code)
        current->pwd=NULL;
        iput(current->root);
        current->root=NULL;
+       iput(current->executable);
+       current->executable=NULL;
        if (current->leader && current->tty >= 0)
                tty_table[current->tty].pgrp = 0;
        if (last_task_used_math == current)
@@ -133,7 +141,7 @@ int sys_exit(int error_code)
 
 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
 {
-       int flag;
+       int flag, code;
        struct task_struct ** p;
 
        verify_area(stat_addr,4);
@@ -164,8 +172,9 @@ repeat:
                                current->cutime += (*p)->utime;
                                current->cstime += (*p)->stime;
                                flag = (*p)->pid;
-                               put_fs_long((*p)->exit_code,stat_addr);
+                               code = (*p)->exit_code;
                                release(*p);
+                               put_fs_long(code,stat_addr);
                                return flag;
                        default:
                                flag=1;
diff --git a/kernel/exit.c~ b/kernel/exit.c~
deleted file mode 100644 (file)
index fccd8d9..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- *  linux/kernel/exit.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <asm/segment.h>
-
-int sys_pause(void);
-int sys_close(int fd);
-
-void release(struct task_struct * p)
-{
-       int i;
-
-       if (!p)
-               return;
-       for (i=1 ; i<NR_TASKS ; i++)
-               if (task[i]==p) {
-                       task[i]=NULL;
-                       free_page((long)p);
-                       schedule();
-                       return;
-               }
-       panic("trying to release non-existent task");
-}
-
-static inline void send_sig(long sig,struct task_struct * p,int priv)
-{
-       if (!p || sig<1 || sig>32)
-               return;
-       if (priv ||
-               current->uid==p->uid ||
-               current->euid==p->uid ||
-               current->uid==p->euid ||
-               current->euid==p->euid)
-               p->signal |= (1<<(sig-1));
-}
-
-static void kill_session(void)
-{
-       struct task_struct **p = NR_TASKS + task;
-
-       while (--p > &FIRST_TASK) {
-               if (*p && (*p)->session == current->session)
-                       (*p)->signal |= 1<<(SIGHUP-1);
-       }
-}
-
-void do_kill(long pid,long sig,int priv)
-{
-       struct task_struct **p = NR_TASKS + task;
-
-       if (!pid) while (--p > &FIRST_TASK) {
-               if (*p && (*p)->pgrp == current->pid)
-                       send_sig(sig,*p,priv);
-       } else if (pid>0) while (--p > &FIRST_TASK) {
-               if (*p && (*p)->pid == pid)
-                       send_sig(sig,*p,priv);
-       } else if (pid == -1) while (--p > &FIRST_TASK)
-               send_sig(sig,*p,priv);
-       else while (--p > &FIRST_TASK)
-               if (*p && (*p)->pgrp == -pid)
-                       send_sig(sig,*p,priv);
-}
-
-int sys_kill(int pid,int sig)
-{
-       do_kill(pid,sig,!(current->uid || current->euid));
-       return 0;
-}
-
-static void tell_father(int pid)
-{
-       int i;
-
-       if (pid)
-               for (i=0;i<NR_TASKS;i++) {
-                       if (!task[i])
-                               continue;
-                       if (task[i]->pid != pid)
-                               continue;
-                       task[i]->signal |= (1<<(SIGCHLD-1));
-                       return;
-               }
-/* if we don't find any fathers, we just release ourselves */
-       release(current);
-}
-
-int do_exit(long code)
-{
-       int i;
-
-       free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
-       free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
-       for (i=0 ; i<NR_TASKS ; i++)
-               if (task[i] && task[i]->father == current->pid)
-                       task[i]->father = 0;
-       for (i=0 ; i<NR_OPEN ; i++)
-               if (current->filp[i])
-                       sys_close(i);
-       iput(current->pwd);
-       current->pwd=NULL;
-       iput(current->root);
-       current->root=NULL;
-       if (current->leader && current->tty >= 0)
-               tty_table[current->tty].pgrp = 0;
-       if (last_task_used_math == current)
-               last_task_used_math = NULL;
-       if (current->leader)
-               kill_session();
-       current->state = TASK_ZOMBIE;
-       current->exit_code = code;
-       tell_father(current->father);
-       schedule();
-       return (-1);    /* just to suppress warnings */
-}
-
-int sys_exit(int error_code)
-{
-       return do_exit((error_code&0xff)<<8);
-}
-
-int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
-{
-       int flag;
-       struct task_struct ** p;
-
-       verify_area(stat_addr,4);
-repeat:
-       flag=0;
-       for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
-               if (!*p || *p == current)
-                       continue;
-               if ((*p)->father != current->pid)
-                       continue;
-               if (pid>0) {
-                       if ((*p)->pid != pid)
-                               continue;
-               } else if (!pid) {
-                       if ((*p)->pgrp != current->pgrp)
-                               continue;
-               } else if (pid != -1) {
-                       if ((*p)->pgrp != -pid)
-                               continue;
-               }
-               switch ((*p)->state) {
-                       case TASK_STOPPED:
-                               if (!(options & WUNTRACED))
-                                       continue;
-                               put_fs_long(0x7f,stat_addr);
-                               return (*p)->pid;
-                       case TASK_ZOMBIE:
-                               current->cutime += (*p)->utime;
-                               current->cstime += (*p)->stime;
-                               flag = (*p)->pid;
-                               put_fs_long((*p)->exit_code,stat_addr);
-                               release(*p);
-                               return flag;
-                       default:
-                               flag=1;
-                               continue;
-               }
-       }
-       if (flag) {
-               if (options & WNOHANG)
-                       return 0;
-               current->state=TASK_INTERRUPTIBLE;
-               schedule();
-               if (!(current->signal &= ~(1<<(SIGCHLD-1))))
-                       goto repeat;
-               else
-                       return -EINTR;
-       }
-       return -ECHILD;
-}
-
-
index f776896e9c7cf705e9c3274fcc9e42b49d7886a4..38a997a4a46de95f78b2e05330aec1d79cfffd12 100644 (file)
@@ -50,6 +50,7 @@ int copy_mem(int nr,struct task_struct * p)
        if (data_limit < code_limit)
                panic("Bad data_limit");
        new_data_base = new_code_base = nr * 0x4000000;
+       p->start_code = new_code_base;
        set_base(p->ldt[1],new_code_base);
        set_base(p->ldt[2],new_data_base);
        if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
@@ -76,8 +77,9 @@ int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
        p = (struct task_struct *) get_free_page();
        if (!p)
                return -EAGAIN;
+       task[nr] = p;
        *p = *current;  /* NOTE! this doesn't copy the supervisor stack */
-       p->state = TASK_RUNNING;
+       p->state = TASK_UNINTERRUPTIBLE;
        p->pid = last_pid;
        p->father = current->pid;
        p->counter = p->priority;
@@ -109,8 +111,9 @@ int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
        p->tss.ldt = _LDT(nr);
        p->tss.trace_bitmap = 0x80000000;
        if (last_task_used_math == current)
-               __asm__("fnsave %0"::"m" (p->tss.i387));
+               __asm__("clts ; fnsave %0"::"m" (p->tss.i387));
        if (copy_mem(nr,p)) {
+               task[nr] = NULL;
                free_page((long) p);
                return -EAGAIN;
        }
@@ -121,9 +124,11 @@ int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
                current->pwd->i_count++;
        if (current->root)
                current->root->i_count++;
+       if (current->executable)
+               current->executable->i_count++;
        set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
        set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
-       task[nr] = p;   /* do this last, just in case */
+       p->state = TASK_RUNNING;        /* do this last, just in case */
        return last_pid;
 }
 
diff --git a/kernel/malloc.c b/kernel/malloc.c
deleted file mode 100644 (file)
index 42723a7..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * malloc.c --- a general purpose kernel memory allocator for Linux.
- * 
- * Written by Theodore Ts'o (tytso@mit.edu), 11/29/91
- *
- * This routine is written to be as fast as possible, so that it
- * can be called from the interrupt level.
- *
- * Limitations: maximum size of memory we can allocate using this routine
- *     is 4k, the size of a page in Linux.
- *
- * The general game plan is that each page (called a bucket) will only hold
- * objects of a given size.  When all of the object on a page are released,
- * the page can be returned to the general free pool.  When malloc() is
- * called, it looks for the smallest bucket size which will fulfill its
- * request, and allocate a piece of memory from that bucket pool.
- *
- * Each bucket has as its control block a bucket descriptor which keeps 
- * track of how many objects are in use on that page, and the free list
- * for that page.  Like the buckets themselves, bucket descriptors are
- * stored on pages requested from get_free_page().  However, unlike buckets,
- * pages devoted to bucket descriptor pages are never released back to the
- * system.  Fortunately, a system should probably only need 1 or 2 bucket
- * descriptor pages, since a page can hold 256 bucket descriptors (which
- * corresponds to 1 megabyte worth of bucket pages.)  If the kernel is using 
- * that much allocated memory, it's probably doing something wrong.  :-)
- *
- * Note: malloc() and free() both call get_free_page() and free_page()
- *     in sections of code where interrupts are turned off, to allow
- *     malloc() and free() to be safely called from an interrupt routine.
- *     (We will probably need this functionality when networking code,
- *     particularily things like NFS, is added to Linux.)  However, this
- *     presumes that get_free_page() and free_page() are interrupt-level
- *     safe, which they may not be once paging is added.  If this is the
- *     case, we will need to modify malloc() to keep a few unused pages
- *     "pre-allocated" so that it can safely draw upon those pages if
- *     it is called from an interrupt routine.
- *
- *     Another concern is that get_free_page() should not sleep; if it 
- *     does, the code is carefully ordered so as to avoid any race 
- *     conditions.  The catch is that if malloc() is called re-entrantly, 
- *     there is a chance that unecessary pages will be grabbed from the 
- *     system.  Except for the pages for the bucket descriptor page, the 
- *     extra pages will eventually get released back to the system, though,
- *     so it isn't all that bad.
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/system.h>
-
-struct bucket_desc {   /* 16 bytes */
-       void                    *page;
-       struct bucket_desc      *next;
-       void                    *freeptr;
-       unsigned short          refcnt;
-       unsigned short          bucket_size;
-};
-
-struct _bucket_dir {   /* 8 bytes */
-       int                     size;
-       struct bucket_desc      *chain;
-};
-
-/*
- * The following is the where we store a pointer to the first bucket
- * descriptor for a given size.  
- *
- * If it turns out that the Linux kernel allocates a lot of objects of a
- * specific size, then we may want to add that specific size to this list,
- * since that will allow the memory to be allocated more efficiently.
- * However, since an entire page must be dedicated to each specific size
- * on this list, some amount of temperance must be exercised here.
- *
- * Note that this list *must* be kept in order.
- */
-struct _bucket_dir bucket_dir[] = {
-       { 16,   (struct bucket_desc *) 0},
-       { 32,   (struct bucket_desc *) 0},
-       { 64,   (struct bucket_desc *) 0},
-       { 128,  (struct bucket_desc *) 0},
-       { 256,  (struct bucket_desc *) 0},
-       { 512,  (struct bucket_desc *) 0},
-       { 1024, (struct bucket_desc *) 0},
-       { 2048, (struct bucket_desc *) 0},
-       { 4096, (struct bucket_desc *) 0},
-       { 0,    (struct bucket_desc *) 0}};   /* End of list marker */
-
-/*
- * This contains a linked list of free bucket descriptor blocks
- */
-struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;
-
-/*
- * This routine initializes a bucket description page.
- */
-static inline void init_bucket_desc()
-{
-       struct bucket_desc *bdesc, *first;
-       int     i;
-       
-       first = bdesc = (struct bucket_desc *) get_free_page();
-       if (!bdesc)
-               panic("Out of memory in init_bucket_desc()");
-       for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
-               bdesc->next = bdesc+1;
-               bdesc++;
-       }
-       /*
-        * This is done last, to avoid race conditions in case 
-        * get_free_page() sleeps and this routine gets called again....
-        */
-       bdesc->next = free_bucket_desc;
-       free_bucket_desc = first;
-}
-
-void *malloc(unsigned int len)
-{
-       struct _bucket_dir      *bdir;
-       struct bucket_desc      *bdesc;
-       void                    *retval;
-
-       /*
-        * First we search the bucket_dir to find the right bucket change
-        * for this request.
-        */
-       for (bdir = bucket_dir; bdir->size; bdir++)
-               if (bdir->size >= len)
-                       break;
-       if (!bdir->size) {
-               printk("malloc called with impossibly large argument (%d)\n",
-                       len);
-               panic("malloc: bad arg");
-       }
-       /*
-        * Now we search for a bucket descriptor which has free space
-        */
-       cli();  /* Avoid race conditions */
-       for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) 
-               if (bdesc->freeptr)
-                       break;
-       /*
-        * If we didn't find a bucket with free space, then we'll 
-        * allocate a new one.
-        */
-       if (!bdesc) {
-               char            *cp;
-               int             i;
-
-               if (!free_bucket_desc)  
-                       init_bucket_desc();
-               bdesc = free_bucket_desc;
-               free_bucket_desc = bdesc->next;
-               bdesc->refcnt = 0;
-               bdesc->bucket_size = bdir->size;
-               bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
-               if (!cp)
-                       panic("Out of memory in kernel malloc()");
-               /* Set up the chain of free objects */
-               for (i=PAGE_SIZE/bdir->size; i > 1; i--) {
-                       *((char **) cp) = cp + bdir->size;
-                       cp += bdir->size;
-               }
-               *((char **) cp) = 0;
-               bdesc->next = bdir->chain; /* OK, link it in! */
-               bdir->chain = bdesc;
-       }
-       retval = (void *) bdesc->freeptr;
-       bdesc->freeptr = *((void **) retval);
-       bdesc->refcnt++;
-       sti();  /* OK, we're safe again */
-       return(retval);
-}
-
-/*
- * Here is the free routine.  If you know the size of the object that you
- * are freeing, then free_s() will use that information to speed up the
- * search for the bucket descriptor.
- * 
- * We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"
- */
-void free_s(void *obj, int size)
-{
-       void            *page;
-       struct _bucket_dir      *bdir;
-       struct bucket_desc      *bdesc, *prev;
-
-       /* Calculate what page this object lives in */
-       page = (void *)  ((unsigned long) obj & 0xfffff000);
-       /* Now search the buckets looking for that page */
-       for (bdir = bucket_dir; bdir->size; bdir++) {
-               prev = 0;
-               /* If size is zero then this conditional is always false */
-               if (bdir->size < size)
-                       continue;
-               for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
-                       if (bdesc->page == page) 
-                               goto found;
-                       prev = bdesc;
-               }
-       }
-       panic("Bad address passed to kernel free_s()");
-found:
-       cli(); /* To avoid race conditions */
-       *((void **)obj) = bdesc->freeptr;
-       bdesc->freeptr = obj;
-       bdesc->refcnt--;
-       if (bdesc->refcnt == 0) {
-               /*
-                * We need to make sure that prev is still accurate.  It
-                * may not be, if someone rudely interrupted us....
-                */
-               if ((prev && (prev->next != bdesc)) ||
-                   (!prev && (bdir->chain != bdesc)))
-                       for (prev = bdir->chain; prev; prev = prev->next)
-                               if (prev->next == bdesc)
-                                       break;
-               if (prev)
-                       prev->next = bdesc->next;
-               else {
-                       if (bdir->chain != bdesc)
-                               panic("malloc bucket chains corrupted");
-                       bdir->chain = bdesc->next;
-               }
-               free_page((unsigned long) bdesc->page);
-               bdesc->next = free_bucket_desc;
-               free_bucket_desc = bdesc;
-       }
-       sti();
-       return;
-}
-
diff --git a/kernel/math/Makefile b/kernel/math/Makefile
new file mode 100644 (file)
index 0000000..7e0b4c4
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# Makefile for the FREAX-kernel character device drivers.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+AR     =gar
+AS     =gas
+LD     =gld
+LDFLAGS        =-s -x
+CC     =gcc
+CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
+       -finline-functions -mstring-insns -nostdinc -I../../include
+CPP    =gcc -E -nostdinc -I../../include
+
+.c.s:
+       $(CC) $(CFLAGS) \
+       -S -o $*.s $<
+.s.o:
+       $(AS) -c -o $*.o $<
+.c.o:
+       $(CC) $(CFLAGS) \
+       -c -o $*.o $<
+
+OBJS  = math_emulate.o
+
+math.a: $(OBJS)
+       $(AR) rcs math.a $(OBJS)
+       sync
+
+clean:
+       rm -f core *.o *.a tmp_make
+       for i in *.c;do rm -f `basename $$i .c`.s;done
+
+dep:
+       sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+       (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+               $(CPP) -M $$i;done) >> tmp_make
+       cp tmp_make Makefile
+
+### Dependencies:
diff --git a/kernel/math/math_emulate.c b/kernel/math/math_emulate.c
new file mode 100644 (file)
index 0000000..825e528
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * linux/kernel/math/math_emulate.c
+ *
+ * (C) 1991 Linus Torvalds
+ */
+
+/*
+ * This directory should contain the math-emulation code.
+ * Currently only results in a signal.
+ */
+
+#include <signal.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <asm/segment.h>
+
+void math_emulate(long edi, long esi, long ebp, long sys_call_ret,
+       long eax,long ebx,long ecx,long edx,
+       unsigned short fs,unsigned short es,unsigned short ds,
+       unsigned long eip,unsigned short cs,unsigned long eflags,
+       unsigned short ss, unsigned long esp)
+{
+       unsigned char first, second;
+
+/* 0x0007 means user code space */
+       if (cs != 0x000F) {
+               printk("math_emulate: %04x:%08x\n\r",cs,eip);
+               panic("Math emulation needed in kernel");
+       }
+       first = get_fs_byte((char *)((*&eip)++));
+       second = get_fs_byte((char *)((*&eip)++));
+       printk("%04x:%08x %02x %02x\n\r",cs,eip-2,first,second);
+       current->signal |= 1<<(SIGFPE-1);
+}
+
+void math_error(void)
+{
+       __asm__("fnclex");
+       if (last_task_used_math)
+               last_task_used_math->signal |= 1<<(SIGFPE-1);
+}
index 6788312a644adda2675155934f602682c56f530d..15d839bd0fd6f7332028060d97b3c62abc7daff1 100644 (file)
 
 void show_task(int nr,struct task_struct * p)
 {
+       int i,j = 4096-sizeof(struct task_struct);
+
        printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
-       printk("eip=%04x:%08x\n\r",p->tss.cs&0xffff,p->tss.eip);
+       i=0;
+       while (i<j && !((char *)(p+1))[i])
+               i++;
+       printk("%d (of %d) chars free in kernel stack\n\r",i,j);
 }
 
 void show_stat(void)
@@ -73,16 +78,17 @@ void math_state_restore()
 {
        if (last_task_used_math == current)
                return;
+       __asm__("fwait");
        if (last_task_used_math) {
                __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
        }
+       last_task_used_math=current;
        if (current->used_math) {
                __asm__("frstor %0"::"m" (current->tss.i387));
        } else {
                __asm__("fninit"::);
                current->used_math=1;
        }
-       last_task_used_math=current;
 }
 
 /*
@@ -196,46 +202,28 @@ static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
 static int  mon_timer[4]={0,0,0,0};
 static int moff_timer[4]={0,0,0,0};
 unsigned char current_DOR = 0x0C;
-unsigned char selected = 0;
-struct task_struct * wait_on_floppy_select = NULL;
-
-void floppy_select(unsigned int nr)
-{
-       if (nr>3)
-               printk("floppy_select: nr>3\n\r");
-       cli();
-       while (selected)
-               sleep_on(&wait_on_floppy_select);
-       current_DOR &= 0xFC;
-       current_DOR |= nr;
-       outb(current_DOR,FD_DOR);
-       sti();
-}
-
-void floppy_deselect(unsigned int nr)
-{
-       if (nr != (current_DOR & 3))
-               printk("floppy_deselect: drive not selected\n\r");
-       selected = 0;
-       wake_up(&wait_on_floppy_select);
-}
 
 int ticks_to_floppy_on(unsigned int nr)
 {
-       unsigned char mask = 1<<(nr+4);
+       extern unsigned char selected;
+       unsigned char mask = 0x10 << nr;
 
        if (nr>3)
                panic("floppy_on: nr>3");
        moff_timer[nr]=10000;           /* 100 s = very big :-) */
        cli();                          /* use floppy_off to turn it off */
-       if (!(mask & current_DOR)) {
-               current_DOR |= mask;
-               if (!selected) {
-                       current_DOR &= 0xFC;
-                       current_DOR |= nr;
-               }
-               outb(current_DOR,FD_DOR);
-               mon_timer[nr] = HZ;
+       mask |= current_DOR;
+       if (!selected) {
+               mask &= 0xFC;
+               mask |= nr;
+       }
+       if (mask != current_DOR) {
+               outb(mask,FD_DOR);
+               if ((mask ^ current_DOR) & 0xf0)
+                       mon_timer[nr] = HZ/2;
+               else if (mon_timer[nr] < 2)
+                       mon_timer[nr] = 2;
+               current_DOR = mask;
        }
        sti();
        return mon_timer[nr];
@@ -316,10 +304,18 @@ void add_timer(long jiffies, void (*fn)(void))
 
 void do_timer(long cpl)
 {
+       extern int beepcount;
+       extern void sysbeepstop(void);
+
+       if (beepcount)
+               if (!--beepcount)
+                       sysbeepstop();
+
        if (cpl)
                current->utime++;
        else
                current->stime++;
+
        if (next_timer) {
                next_timer->jiffies--;
                while (next_timer && next_timer->jiffies <= 0) {
@@ -403,6 +399,8 @@ void sched_init(void)
                p->a=p->b=0;
                p++;
        }
+/* Clear NT, so that we won't have troubles with that later on */
+       __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
        ltr(0);
        lldt(0);
        outb_p(0x36,0x43);              /* binary, mode 3, LSB/MSB, ch 0 */
diff --git a/kernel/sched.c~ b/kernel/sched.c~
deleted file mode 100644 (file)
index 19cd2c2..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- *  linux/kernel/sched.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- * 'sched.c' is the main kernel file. It contains scheduling primitives
- * (sleep_on, wakeup, schedule etc) as well as a number of simple system
- * call functions (type getpid(), which just extracts a field from
- * current-task
- */
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/sys.h>
-#include <linux/fdreg.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-
-#include <signal.h>
-
-#define _S(nr) (1<<((nr)-1))
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-
-void show_task(int nr,struct task_struct * p)
-{
-       printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
-       printk("eip=%04x:%08x\n\r",p->tss.cs&0xffff,p->tss.eip);
-}
-
-void show_stat(void)
-{
-       int i;
-
-       for (i=0;i<NR_TASKS;i++)
-               if (task[i])
-                       show_task(i,task[i]);
-}
-
-#define LATCH (1193180/HZ)
-
-extern void mem_use(void);
-
-extern int timer_interrupt(void);
-extern int system_call(void);
-
-union task_union {
-       struct task_struct task;
-       char stack[PAGE_SIZE];
-};
-
-static union task_union init_task = {INIT_TASK,};
-
-long volatile jiffies=0;
-long startup_time=0;
-struct task_struct *current = &(init_task.task);
-struct task_struct *last_task_used_math = NULL;
-
-struct task_struct * task[NR_TASKS] = {&(init_task.task), };
-
-long user_stack [ PAGE_SIZE>>2 ] ;
-
-struct {
-       long * a;
-       short b;
-       } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
-/*
- *  'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task
- */
-void math_state_restore()
-{
-       if (last_task_used_math == current)
-               return;
-       if (last_task_used_math) {
-               __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
-       }
-       if (current->used_math) {
-               __asm__("frstor %0"::"m" (current->tss.i387));
-       } else {
-               __asm__("fninit"::);
-               current->used_math=1;
-       }
-       last_task_used_math=current;
-}
-
-/*
- *  'schedule()' is the scheduler function. This is GOOD CODE! There
- * probably won't be any reason to change this, as it should work well
- * in all circumstances (ie gives IO-bound processes good response etc).
- * The one thing you might take a look at is the signal-handler code here.
- *
- *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other
- * tasks can run. It can not be killed, and it cannot sleep. The 'state'
- * information in task[0] is never used.
- */
-void schedule(void)
-{
-       int i,next,c;
-       struct task_struct ** p;
-
-/* check alarm, wake up any interruptible tasks that have got a signal */
-
-       for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
-               if (*p) {
-                       if ((*p)->alarm && (*p)->alarm < jiffies) {
-                                       (*p)->signal |= (1<<(SIGALRM-1));
-                                       (*p)->alarm = 0;
-                               }
-                       if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
-                       (*p)->state==TASK_INTERRUPTIBLE)
-                               (*p)->state=TASK_RUNNING;
-               }
-
-/* this is the scheduler proper: */
-
-       while (1) {
-               c = -1;
-               next = 0;
-               i = NR_TASKS;
-               p = &task[NR_TASKS];
-               while (--i) {
-                       if (!*--p)
-                               continue;
-                       if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
-                               c = (*p)->counter, next = i;
-               }
-               if (c) break;
-               for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
-                       if (*p)
-                               (*p)->counter = ((*p)->counter >> 1) +
-                                               (*p)->priority;
-       }
-       switch_to(next);
-}
-
-int sys_pause(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       return 0;
-}
-
-void sleep_on(struct task_struct **p)
-{
-       struct task_struct *tmp;
-
-       if (!p)
-               return;
-       if (current == &(init_task.task))
-               panic("task[0] trying to sleep");
-       tmp = *p;
-       *p = current;
-       current->state = TASK_UNINTERRUPTIBLE;
-       schedule();
-       if (tmp)
-               tmp->state=0;
-}
-
-void interruptible_sleep_on(struct task_struct **p)
-{
-       struct task_struct *tmp;
-
-       if (!p)
-               return;
-       if (current == &(init_task.task))
-               panic("task[0] trying to sleep");
-       tmp=*p;
-       *p=current;
-repeat:        current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       if (*p && *p != current) {
-               (**p).state=0;
-               goto repeat;
-       }
-       *p=NULL;
-       if (tmp)
-               tmp->state=0;
-}
-
-void wake_up(struct task_struct **p)
-{
-       if (p && *p) {
-               (**p).state=0;
-               *p=NULL;
-       }
-}
-
-/*
- * OK, here are some floppy things that shouldn't be in the kernel
- * proper. They are here because the floppy needs a timer, and this
- * was the easiest way of doing it.
- */
-static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
-static int  mon_timer[4]={0,0,0,0};
-static int moff_timer[4]={0,0,0,0};
-unsigned char current_DOR = 0x0C;
-unsigned char selected = 0;
-struct task_struct * wait_on_floppy_select = NULL;
-
-void floppy_select(unsigned int nr)
-{
-       if (nr>3)
-               printk("floppy_select: nr>3\n\r");
-       cli();
-       while (selected)
-               sleep_on(&wait_on_floppy_select);
-       current_DOR &= 0xFC;
-       current_DOR |= nr;
-       outb(current_DOR,FD_DOR);
-       sti();
-}
-
-void floppy_deselect(unsigned int nr)
-{
-       if (nr != (current_DOR & 3))
-               printk("floppy_deselect: drive not selected\n\r");
-       selected = 0;
-       wake_up(&wait_on_floppy_select);
-}
-
-int ticks_to_floppy_on(unsigned int nr)
-{
-       unsigned char mask = 1<<(nr+4);
-
-       if (nr>3)
-               panic("floppy_on: nr>3");
-       moff_timer[nr]=10000;           /* 100 s = very big :-) */
-       cli();                          /* use floppy_off to turn it off */
-       if (!(mask & current_DOR)) {
-               current_DOR |= mask;
-               if (!selected) {
-                       current_DOR &= 0xFC;
-                       current_DOR |= nr;
-               }
-               outb(current_DOR,FD_DOR);
-               mon_timer[nr] = HZ;
-       }
-       sti();
-       return mon_timer[nr];
-}
-
-void floppy_on(unsigned int nr)
-{
-       cli();
-       while (ticks_to_floppy_on(nr))
-               sleep_on(nr+wait_motor);
-       sti();
-}
-
-void floppy_off(unsigned int nr)
-{
-       moff_timer[nr]=3*HZ;
-}
-
-void do_floppy_timer(void)
-{
-       int i;
-       unsigned char mask = 0x10;
-
-       for (i=0 ; i<4 ; i++,mask <<= 1) {
-               if (!(mask & current_DOR))
-                       continue;
-               if (mon_timer[i]) {
-                       if (!--mon_timer[i])
-                               wake_up(i+wait_motor);
-               } else if (!moff_timer[i]) {
-                       current_DOR &= ~mask;
-                       outb(current_DOR,FD_DOR);
-               } else
-                       moff_timer[i]--;
-       }
-}
-
-#define TIME_REQUESTS 64
-
-static struct timer_list {
-       long jiffies;
-       void (*fn)();
-       struct timer_list * next;
-} timer_list[TIME_REQUESTS], * next_timer = NULL;
-
-void add_timer(long jiffies, void (*fn)(void))
-{
-       struct timer_list * p;
-
-       if (!fn)
-               return;
-       cli();
-       if (jiffies <= 0)
-               (fn)();
-       else {
-               for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
-                       if (!p->fn)
-                               break;
-               if (p >= timer_list + TIME_REQUESTS)
-                       panic("No more time requests free");
-               p->fn = fn;
-               p->jiffies = jiffies;
-               p->next = next_timer;
-               next_timer = p;
-               while (p->next && p->next->jiffies < p->jiffies) {
-                       p->jiffies -= p->next->jiffies;
-                       fn = p->fn;
-                       p->fn = p->next->fn;
-                       p->next->fn = fn;
-                       jiffies = p->jiffies;
-                       p->jiffies = p->next->jiffies;
-                       p->next->jiffies = jiffies;
-                       p = p->next;
-               }
-       }
-       sti();
-}
-
-void do_timer(long cpl)
-{
-       if (cpl)
-               current->utime++;
-       else
-               current->stime++;
-       if (next_timer) {
-               next_timer->jiffies--;
-               while (next_timer && next_timer->jiffies <= 0) {
-                       void (*fn)(void);
-                       
-                       fn = next_timer->fn;
-                       next_timer->fn = NULL;
-                       next_timer = next_timer->next;
-                       (fn)();
-               }
-       }
-       if (current_DOR & 0xf0)
-               do_floppy_timer();
-       if ((--current->counter)>0) return;
-       current->counter=0;
-       if (!cpl) return;
-       schedule();
-}
-
-int sys_alarm(long seconds)
-{
-       current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
-       return seconds;
-}
-
-int sys_getpid(void)
-{
-       return current->pid;
-}
-
-int sys_getppid(void)
-{
-       return current->father;
-}
-
-int sys_getuid(void)
-{
-       return current->uid;
-}
-
-int sys_geteuid(void)
-{
-       return current->euid;
-}
-
-int sys_getgid(void)
-{
-       return current->gid;
-}
-
-int sys_getegid(void)
-{
-       return current->egid;
-}
-
-int sys_nice(long increment)
-{
-       if (current->priority-increment>0)
-               current->priority -= increment;
-       return 0;
-}
-
-void sched_init(void)
-{
-       int i;
-       struct desc_struct * p;
-
-       if (sizeof(struct sigaction) != 16)
-               panic("Struct sigaction MUST be 16 bytes");
-       set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
-       set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
-       p = gdt+2+FIRST_TSS_ENTRY;
-       for(i=1;i<NR_TASKS;i++) {
-               task[i] = NULL;
-               p->a=p->b=0;
-               p++;
-               p->a=p->b=0;
-               p++;
-       }
-       ltr(0);
-       lldt(0);
-       outb_p(0x36,0x43);              /* binary, mode 3, LSB/MSB, ch 0 */
-       outb_p(LATCH & 0xff , 0x40);    /* LSB */
-       outb(LATCH >> 8 , 0x40);        /* MSB */
-       set_intr_gate(0x20,&timer_interrupt);
-       outb(inb_p(0x21)&~0x01,0x21);
-       set_system_gate(0x80,&system_call);
-}
index 79fb6ca2b64926fd838cd9e3838e761d05ec5f49..055fc200edce943bb8951878d44a552f1848268b 100644 (file)
@@ -84,13 +84,13 @@ void do_signal(long signr,long eax, long ebx, long ecx, long edx,
        long eip, long cs, long eflags,
        unsigned long * esp, long ss)
 {
-       long sa_handler;
+       unsigned long sa_handler;
        long old_eip=eip;
        struct sigaction * sa = current->sigaction + signr - 1;
        int longs;
        unsigned long * tmp_esp;
 
-       sa_handler = (long) sa->sa_handler;
+       sa_handler = (unsigned long) sa->sa_handler;
        if (sa_handler==1)
                return;
        if (!sa_handler) {
diff --git a/kernel/sys.c~ b/kernel/sys.c~
deleted file mode 100644 (file)
index 2007f42..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *  linux/kernel/sys.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-#include <sys/times.h>
-#include <sys/utsname.h>
-
-int sys_ftime()
-{
-       return -ENOSYS;
-}
-
-int sys_break()
-{
-       return -ENOSYS;
-}
-
-int sys_ptrace()
-{
-       return -ENOSYS;
-}
-
-int sys_stty()
-{
-       return -ENOSYS;
-}
-
-int sys_gtty()
-{
-       return -ENOSYS;
-}
-
-int sys_rename()
-{
-       return -ENOSYS;
-}
-
-int sys_prof()
-{
-       return -ENOSYS;
-}
-
-int sys_setgid(int gid)
-{
-       if (current->euid && current->uid)
-               if (current->gid==gid || current->sgid==gid)
-                       current->egid = gid;
-               else
-                       return -EPERM;
-       else
-               current->gid = current->egid = gid;
-       return 0;
-}
-
-int sys_acct()
-{
-       return -ENOSYS;
-}
-
-int sys_phys()
-{
-       return -ENOSYS;
-}
-
-int sys_lock()
-{
-       return -ENOSYS;
-}
-
-int sys_mpx()
-{
-       return -ENOSYS;
-}
-
-int sys_ulimit()
-{
-       return -ENOSYS;
-}
-
-int sys_time(long * tloc)
-{
-       int i;
-
-       i = CURRENT_TIME;
-       if (tloc) {
-               verify_area(tloc,4);
-               put_fs_long(i,(unsigned long *)tloc);
-       }
-       return i;
-}
-
-int sys_setuid(int uid)
-{
-       if (current->euid && current->uid)
-               if (uid==current->uid || current->suid==current->uid)
-                       current->euid=uid;
-               else
-                       return -EPERM;
-       else
-               current->euid=current->uid=uid;
-       return 0;
-}
-
-int sys_stime(long * tptr)
-{
-       if (current->euid && current->uid)
-               return -EPERM;
-       startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
-       return 0;
-}
-
-int sys_times(struct tms * tbuf)
-{
-       if (tbuf) {
-               verify_area(tbuf,sizeof *tbuf);
-               put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
-               put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
-               put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
-               put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
-       }
-       return jiffies;
-}
-
-int sys_brk(unsigned long end_data_seg)
-{
-       if (end_data_seg >= current->end_code &&
-           end_data_seg < current->start_stack - 16384)
-               current->brk = end_data_seg;
-       return current->brk;
-}
-
-/*
- * This needs some heave checking ...
- * I just haven't get the stomach for it. I also don't fully
- * understand sessions/pgrp etc. Let somebody who does explain it.
- */
-int sys_setpgid(int pid, int pgid)
-{
-       int i;
-
-       if (!pid)
-               pid = current->pid;
-       if (!pgid)
-               pgid = current->pid;
-       for (i=0 ; i<NR_TASKS ; i++)
-               if (task[i] && task[i]->pid==pid) {
-                       if (task[i]->leader)
-                               return -EPERM;
-                       if (task[i]->session != current->session)
-                               return -EPERM;
-                       task[i]->pgrp = pgid;
-                       return 0;
-               }
-       return -ESRCH;
-}
-
-int sys_getpgrp(void)
-{
-       return current->pgrp;
-}
-
-int sys_setsid(void)
-{
-       if (current->uid && current->euid)
-               return -EPERM;
-       if (current->leader)
-               return -EPERM;
-       current->leader = 1;
-       current->session = current->pgrp = current->pid;
-       current->tty = -1;
-       return current->pgrp;
-}
-
-int sys_uname(struct utsname * name)
-{
-       static struct utsname thisname = {
-               "linux .0","nodename","release ","version ","machine "
-       };
-       int i;
-
-       if (!name) return -ERROR;
-       verify_area(name,sizeof *name);
-       for(i=0;i<sizeof *name;i++)
-               put_fs_byte(((char *) &thisname)[i],i+(char *) name);
-       return 0;
-}
-
-int sys_umask(int mask)
-{
-       int old = current->umask;
-
-       current->umask = mask & 0777;
-       return (old);
-}
index 5f7cafc4a760f4d835c9f18f2c20ccb1b9da9907..c96826c7a1a898b72e20be3c8606f2904f739168 100644 (file)
@@ -58,7 +58,7 @@ sa_mask = 4
 sa_flags = 8
 sa_restorer = 12
 
-nr_system_calls = 70
+nr_system_calls = 72
 
 /*
  * Ok, I get parallel printer interrupts while using the floppy for some
@@ -66,6 +66,7 @@ nr_system_calls = 70
  */
 .globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
 .globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
+.globl _device_not_available, _coprocessor_error
 
 .align 2
 bad_sys_call:
@@ -126,6 +127,51 @@ ret_from_sys_call:
        pop %ds
        iret
 
+.align 2
+_coprocessor_error:
+       push %ds
+       push %es
+       push %fs
+       pushl %edx
+       pushl %ecx
+       pushl %ebx
+       pushl %eax
+       movl $0x10,%eax
+       mov %ax,%ds
+       mov %ax,%es
+       movl $0x17,%eax
+       mov %ax,%fs
+       pushl $ret_from_sys_call
+       jmp _math_error
+
+.align 2
+_device_not_available:
+       push %ds
+       push %es
+       push %fs
+       pushl %edx
+       pushl %ecx
+       pushl %ebx
+       pushl %eax
+       movl $0x10,%eax
+       mov %ax,%ds
+       mov %ax,%es
+       movl $0x17,%eax
+       mov %ax,%fs
+       pushl $ret_from_sys_call
+       clts                            # clear TS so that we can use math
+       movl %cr0,%eax
+       testl $0x4,%eax                 # EM (math emulation bit)
+       je _math_state_restore
+       pushl %ebp
+       pushl %esi
+       pushl %edi
+       call _math_emulate
+       popl %edi
+       popl %esi
+       popl %ebp
+       ret
+
 .align 2
 _timer_interrupt:
        push %ds                # save ds,es and put kernel data space
@@ -182,17 +228,19 @@ _hd_interrupt:
        movl $0x10,%eax
        mov %ax,%ds
        mov %ax,%es
+       movl $0x17,%eax
        mov %ax,%fs
        movb $0x20,%al
-       outb %al,$0x20          # EOI to interrupt controller #1
+       outb %al,$0xA0          # EOI to interrupt controller #1
        jmp 1f                  # give port chance to breathe
 1:     jmp 1f
-1:     outb %al,$0xA0          # same to controller #2
-       movl _do_hd,%eax
-       testl %eax,%eax
+1:     xorl %edx,%edx
+       xchgl _do_hd,%edx
+       testl %edx,%edx
        jne 1f
-       movl $_unexpected_hd_interrupt,%eax
-1:     call *%eax              # "interesting" way of handling intr.
+       movl $_unexpected_hd_interrupt,%edx
+1:     outb %al,$0x20
+       call *%edx              # "interesting" way of handling intr.
        pop %fs
        pop %es
        pop %ds
@@ -211,10 +259,12 @@ _floppy_interrupt:
        movl $0x10,%eax
        mov %ax,%ds
        mov %ax,%es
+       movl $0x17,%eax
        mov %ax,%fs
        movb $0x20,%al
        outb %al,$0x20          # EOI to interrupt controller #1
-       movl _do_floppy,%eax
+       xorl %eax,%eax
+       xchgl _do_floppy,%eax
        testl %eax,%eax
        jne 1f
        movl $_unexpected_floppy_interrupt,%eax
index bc1ecf39bee3a51a997a4af553950cbcde393cf3..a4a33b57cfd13f5dec04dc06e31884d9d4929639 100644 (file)
@@ -25,7 +25,7 @@ CPP   =gcc -E -nostdinc -I../include
        -c -o $*.o $<
 
 OBJS  = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
-       execve.o wait.o string.o
+       execve.o wait.o string.o malloc.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
@@ -56,6 +56,8 @@ errno.s errno.o : errno.c
 execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h \
   ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
   ../include/utime.h 
+malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h \
+  ../include/asm/system.h 
 open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h \
   ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
   ../include/utime.h ../include/stdarg.h 
diff --git a/lib/malloc.c b/lib/malloc.c
new file mode 100644 (file)
index 0000000..42723a7
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * malloc.c --- a general purpose kernel memory allocator for Linux.
+ * 
+ * Written by Theodore Ts'o (tytso@mit.edu), 11/29/91
+ *
+ * This routine is written to be as fast as possible, so that it
+ * can be called from the interrupt level.
+ *
+ * Limitations: maximum size of memory we can allocate using this routine
+ *     is 4k, the size of a page in Linux.
+ *
+ * The general game plan is that each page (called a bucket) will only hold
+ * objects of a given size.  When all of the object on a page are released,
+ * the page can be returned to the general free pool.  When malloc() is
+ * called, it looks for the smallest bucket size which will fulfill its
+ * request, and allocate a piece of memory from that bucket pool.
+ *
+ * Each bucket has as its control block a bucket descriptor which keeps 
+ * track of how many objects are in use on that page, and the free list
+ * for that page.  Like the buckets themselves, bucket descriptors are
+ * stored on pages requested from get_free_page().  However, unlike buckets,
+ * pages devoted to bucket descriptor pages are never released back to the
+ * system.  Fortunately, a system should probably only need 1 or 2 bucket
+ * descriptor pages, since a page can hold 256 bucket descriptors (which
+ * corresponds to 1 megabyte worth of bucket pages.)  If the kernel is using 
+ * that much allocated memory, it's probably doing something wrong.  :-)
+ *
+ * Note: malloc() and free() both call get_free_page() and free_page()
+ *     in sections of code where interrupts are turned off, to allow
+ *     malloc() and free() to be safely called from an interrupt routine.
+ *     (We will probably need this functionality when networking code,
+ *     particularily things like NFS, is added to Linux.)  However, this
+ *     presumes that get_free_page() and free_page() are interrupt-level
+ *     safe, which they may not be once paging is added.  If this is the
+ *     case, we will need to modify malloc() to keep a few unused pages
+ *     "pre-allocated" so that it can safely draw upon those pages if
+ *     it is called from an interrupt routine.
+ *
+ *     Another concern is that get_free_page() should not sleep; if it 
+ *     does, the code is carefully ordered so as to avoid any race 
+ *     conditions.  The catch is that if malloc() is called re-entrantly, 
+ *     there is a chance that unecessary pages will be grabbed from the 
+ *     system.  Except for the pages for the bucket descriptor page, the 
+ *     extra pages will eventually get released back to the system, though,
+ *     so it isn't all that bad.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/system.h>
+
+struct bucket_desc {   /* 16 bytes */
+       void                    *page;
+       struct bucket_desc      *next;
+       void                    *freeptr;
+       unsigned short          refcnt;
+       unsigned short          bucket_size;
+};
+
+struct _bucket_dir {   /* 8 bytes */
+       int                     size;
+       struct bucket_desc      *chain;
+};
+
+/*
+ * The following is the where we store a pointer to the first bucket
+ * descriptor for a given size.  
+ *
+ * If it turns out that the Linux kernel allocates a lot of objects of a
+ * specific size, then we may want to add that specific size to this list,
+ * since that will allow the memory to be allocated more efficiently.
+ * However, since an entire page must be dedicated to each specific size
+ * on this list, some amount of temperance must be exercised here.
+ *
+ * Note that this list *must* be kept in order.
+ */
+struct _bucket_dir bucket_dir[] = {
+       { 16,   (struct bucket_desc *) 0},
+       { 32,   (struct bucket_desc *) 0},
+       { 64,   (struct bucket_desc *) 0},
+       { 128,  (struct bucket_desc *) 0},
+       { 256,  (struct bucket_desc *) 0},
+       { 512,  (struct bucket_desc *) 0},
+       { 1024, (struct bucket_desc *) 0},
+       { 2048, (struct bucket_desc *) 0},
+       { 4096, (struct bucket_desc *) 0},
+       { 0,    (struct bucket_desc *) 0}};   /* End of list marker */
+
+/*
+ * This contains a linked list of free bucket descriptor blocks
+ */
+struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;
+
+/*
+ * This routine initializes a bucket description page.
+ */
+static inline void init_bucket_desc()
+{
+       struct bucket_desc *bdesc, *first;
+       int     i;
+       
+       first = bdesc = (struct bucket_desc *) get_free_page();
+       if (!bdesc)
+               panic("Out of memory in init_bucket_desc()");
+       for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
+               bdesc->next = bdesc+1;
+               bdesc++;
+       }
+       /*
+        * This is done last, to avoid race conditions in case 
+        * get_free_page() sleeps and this routine gets called again....
+        */
+       bdesc->next = free_bucket_desc;
+       free_bucket_desc = first;
+}
+
+void *malloc(unsigned int len)
+{
+       struct _bucket_dir      *bdir;
+       struct bucket_desc      *bdesc;
+       void                    *retval;
+
+       /*
+        * First we search the bucket_dir to find the right bucket change
+        * for this request.
+        */
+       for (bdir = bucket_dir; bdir->size; bdir++)
+               if (bdir->size >= len)
+                       break;
+       if (!bdir->size) {
+               printk("malloc called with impossibly large argument (%d)\n",
+                       len);
+               panic("malloc: bad arg");
+       }
+       /*
+        * Now we search for a bucket descriptor which has free space
+        */
+       cli();  /* Avoid race conditions */
+       for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) 
+               if (bdesc->freeptr)
+                       break;
+       /*
+        * If we didn't find a bucket with free space, then we'll 
+        * allocate a new one.
+        */
+       if (!bdesc) {
+               char            *cp;
+               int             i;
+
+               if (!free_bucket_desc)  
+                       init_bucket_desc();
+               bdesc = free_bucket_desc;
+               free_bucket_desc = bdesc->next;
+               bdesc->refcnt = 0;
+               bdesc->bucket_size = bdir->size;
+               bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
+               if (!cp)
+                       panic("Out of memory in kernel malloc()");
+               /* Set up the chain of free objects */
+               for (i=PAGE_SIZE/bdir->size; i > 1; i--) {
+                       *((char **) cp) = cp + bdir->size;
+                       cp += bdir->size;
+               }
+               *((char **) cp) = 0;
+               bdesc->next = bdir->chain; /* OK, link it in! */
+               bdir->chain = bdesc;
+       }
+       retval = (void *) bdesc->freeptr;
+       bdesc->freeptr = *((void **) retval);
+       bdesc->refcnt++;
+       sti();  /* OK, we're safe again */
+       return(retval);
+}
+
+/*
+ * Here is the free routine.  If you know the size of the object that you
+ * are freeing, then free_s() will use that information to speed up the
+ * search for the bucket descriptor.
+ * 
+ * We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"
+ */
+void free_s(void *obj, int size)
+{
+       void            *page;
+       struct _bucket_dir      *bdir;
+       struct bucket_desc      *bdesc, *prev;
+
+       /* Calculate what page this object lives in */
+       page = (void *)  ((unsigned long) obj & 0xfffff000);
+       /* Now search the buckets looking for that page */
+       for (bdir = bucket_dir; bdir->size; bdir++) {
+               prev = 0;
+               /* If size is zero then this conditional is always false */
+               if (bdir->size < size)
+                       continue;
+               for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
+                       if (bdesc->page == page) 
+                               goto found;
+                       prev = bdesc;
+               }
+       }
+       panic("Bad address passed to kernel free_s()");
+found:
+       cli(); /* To avoid race conditions */
+       *((void **)obj) = bdesc->freeptr;
+       bdesc->freeptr = obj;
+       bdesc->refcnt--;
+       if (bdesc->refcnt == 0) {
+               /*
+                * We need to make sure that prev is still accurate.  It
+                * may not be, if someone rudely interrupted us....
+                */
+               if ((prev && (prev->next != bdesc)) ||
+                   (!prev && (bdir->chain != bdesc)))
+                       for (prev = bdir->chain; prev; prev = prev->next)
+                               if (prev->next == bdesc)
+                                       break;
+               if (prev)
+                       prev->next = bdesc->next;
+               else {
+                       if (bdir->chain != bdesc)
+                               panic("malloc bucket chains corrupted");
+                       bdir->chain = bdesc->next;
+               }
+               free_page((unsigned long) bdesc->page);
+               bdesc->next = free_bucket_desc;
+               free_bucket_desc = bdesc;
+       }
+       sti();
+       return;
+}
+
index 3f20add82570b49d7c78f43bc7a46385e8c83940..d4317185be31af0c7bcfb33fba5b19dcc159876f 100644 (file)
@@ -33,4 +33,5 @@ dep:
 
 ### Dependencies:
 memory.o : memory.c ../include/signal.h ../include/sys/types.h \
-  ../include/linux/head.h ../include/linux/kernel.h ../include/asm/system.h 
+  ../include/asm/system.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h 
index 66bfa6c3f10db3e4e21fde8b6c06f579a460d27c..a27cd78873c71e2836044e682c7bfca28afb3d45 100644 (file)
@@ -4,13 +4,37 @@
  *  (C) 1991  Linus Torvalds
  */
 
+/*
+ * demand-loading started 01.12.91 - seems it is high on the list of
+ * things wanted, and it should be easy to implement. - Linus
+ */
+
+/*
+ * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
+ * pages started 02.12.91, seems to work. - Linus.
+ *
+ * Tested sharing by executing about 30 /bin/sh: under the old kernel it
+ * would have taken more than the 6M I have free, but it worked well as
+ * far as I could see.
+ *
+ * Also corrected some "invalidate()"s - I wasn't doing enough of them.
+ */
+
 #include <signal.h>
 
+#include <asm/system.h>
+
+#include <linux/sched.h>
 #include <linux/head.h>
 #include <linux/kernel.h>
-#include <asm/system.h>
 
-int do_exit(long code);
+volatile void do_exit(long code);
+
+static inline volatile void oom(void)
+{
+       printk("out of memory\n\r");
+       do_exit(SIGSEGV);
+}
 
 #define invalidate() \
 __asm__("movl %%eax,%%cr3"::"a" (0))
@@ -22,6 +46,9 @@ __asm__("movl %%eax,%%cr3"::"a" (0))
 #define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
 #define USED 100
 
+#define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
+current->start_code + current->end_code)
+
 static long HIGH_MEMORY = 0;
 
 #define copy_page(from,to) \
@@ -62,7 +89,7 @@ return __res;
 void free_page(unsigned long addr)
 {
        if (addr < LOW_MEM) return;
-       if (addr > HIGH_MEMORY)
+       if (addr >= HIGH_MEMORY)
                panic("trying to free nonexistent page");
        addr -= LOW_MEM;
        addr >>= 12;
@@ -173,7 +200,7 @@ unsigned long put_page(unsigned long page,unsigned long address)
 
 /* NOTE !!! This uses the fact that _pg_dir=0 */
 
-       if (page < LOW_MEM || page > HIGH_MEMORY)
+       if (page < LOW_MEM || page >= HIGH_MEMORY)
                printk("Trying to put page %p at %p\n",page,address);
        if (mem_map[(page-LOW_MEM)>>12] != 1)
                printk("mem_map disagrees with %p at %p\n",page,address);
@@ -187,6 +214,7 @@ unsigned long put_page(unsigned long page,unsigned long address)
                page_table = (unsigned long *) tmp;
        }
        page_table[(address>>12) & 0x3ff] = page | 7;
+/* no need for invalidate */
        return page;
 }
 
@@ -197,13 +225,15 @@ void un_wp_page(unsigned long * table_entry)
        old_page = 0xfffff000 & *table_entry;
        if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
                *table_entry |= 2;
+               invalidate();
                return;
        }
        if (!(new_page=get_free_page()))
-               do_exit(SIGSEGV);
+               oom();
        if (old_page >= LOW_MEM)
                mem_map[MAP_NR(old_page)]--;
        *table_entry = new_page | 7;
+       invalidate();
        copy_page(old_page,new_page);
 }      
 
@@ -211,9 +241,17 @@ void un_wp_page(unsigned long * table_entry)
  * This routine handles present pages, when users try to write
  * to a shared page. It is done by copying the page to a new address
  * and decrementing the shared-page counter for the old page.
+ *
+ * If it's in code space we exit with a segment error.
  */
 void do_wp_page(unsigned long error_code,unsigned long address)
 {
+#if 0
+/* we cannot do this yet: the estdio library writes to code space */
+/* stupid, stupid. I really want the libc.a from GNU */
+       if (CODE_SPACE(address))
+               do_exit(SIGSEGV);
+#endif
        un_wp_page((unsigned long *)
                (((address>>10) & 0xffc) + (0xfffff000 &
                *((unsigned long *) ((address>>20) &0xffc)))));
@@ -233,14 +271,129 @@ void write_verify(unsigned long address)
        return;
 }
 
+void get_empty_page(unsigned long address)
+{
+       unsigned long tmp;
+
+       if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
+               free_page(tmp);         /* 0 is ok - ignored */
+               oom();
+       }
+}
+
+/*
+ * try_to_share() checks the page at address "address" in the task "p",
+ * to see if it exists, and if it is clean. If so, share it with the current
+ * task.
+ *
+ * NOTE! This assumes we have checked that p != current, and that they
+ * share the same executable.
+ */
+static int try_to_share(unsigned long address, struct task_struct * p)
+{
+       unsigned long from;
+       unsigned long to;
+       unsigned long from_page;
+       unsigned long to_page;
+       unsigned long phys_addr;
+
+       from_page = to_page = ((address>>20) & 0xffc);
+       from_page += ((p->start_code>>20) & 0xffc);
+       to_page += ((current->start_code>>20) & 0xffc);
+/* is there a page-directory at from? */
+       from = *(unsigned long *) from_page;
+       if (!(from & 1))
+               return 0;
+       from &= 0xfffff000;
+       from_page = from + ((address>>10) & 0xffc);
+       phys_addr = *(unsigned long *) from_page;
+/* is the page clean and present? */
+       if ((phys_addr & 0x41) != 0x01)
+               return 0;
+       phys_addr &= 0xfffff000;
+       if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)
+               return 0;
+       to = *(unsigned long *) to_page;
+       if (!(to & 1))
+               if (to = get_free_page())
+                       *(unsigned long *) to_page = to | 7;
+               else
+                       oom();
+       to &= 0xfffff000;
+       to_page = to + ((address>>10) & 0xffc);
+       if (1 & *(unsigned long *) to_page)
+               panic("try_to_share: to_page already exists");
+/* share them: write-protect */
+       *(unsigned long *) from_page &= ~2;
+       *(unsigned long *) to_page = *(unsigned long *) from_page;
+       invalidate();
+       phys_addr -= LOW_MEM;
+       phys_addr >>= 12;
+       mem_map[phys_addr]++;
+       return 1;
+}
+
+/*
+ * share_page() tries to find a process that could share a page with
+ * the current one. Address is the address of the wanted page relative
+ * to the current data space.
+ *
+ * We first check if it is at all feasible by checking executable->i_count.
+ * It should be >1 if there are other tasks sharing this inode.
+ */
+static int share_page(unsigned long address)
+{
+       struct task_struct ** p;
+
+       if (!current->executable)
+               return 0;
+       if (current->executable->i_count < 2)
+               return 0;
+       for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
+               if (!*p)
+                       continue;
+               if (current == *p)
+                       continue;
+               if ((*p)->executable != current->executable)
+                       continue;
+               if (try_to_share(address,*p))
+                       return 1;
+       }
+       return 0;
+}
+
 void do_no_page(unsigned long error_code,unsigned long address)
 {
+       int nr[4];
        unsigned long tmp;
+       unsigned long page;
+       int block,i;
 
-       if (tmp=get_free_page())
-               if (put_page(tmp,address))
-                       return;
-       do_exit(SIGSEGV);
+       address &= 0xfffff000;
+       tmp = address - current->start_code;
+       if (!current->executable || tmp >= current->end_data) {
+               get_empty_page(address);
+               return;
+       }
+       if (share_page(tmp))
+               return;
+       if (!(page = get_free_page()))
+               oom();
+/* remember that 1 block is used for header */
+       block = 1 + tmp/BLOCK_SIZE;
+       for (i=0 ; i<4 ; block++,i++)
+               nr[i] = bmap(current->executable,block);
+       bread_page(page,current->executable->i_dev,nr);
+       i = tmp + 4096 - current->end_data;
+       tmp = page + 4096;
+       while (i-- > 0) {
+               tmp--;
+               *(char *)tmp = 0;
+       }
+       if (put_page(page,address))
+               return;
+       free_page(page);
+       oom();
 }
 
 void mem_init(long start_mem, long end_mem)
diff --git a/tools/RCS/build.c,v b/tools/RCS/build.c,v
deleted file mode 100644 (file)
index 1215019..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-head     1.2;
-branch   ;
-access   ;
-symbols  ;
-locks    ; strict;
-comment  @ * @;
-
-
-1.2
-date     91.11.20.00.07.29;  author tytso;  state Exp;
-branches ;
-next     1.1;
-
-1.1
-date     91.11.11.14.45.51;  author tytso;  state Exp;
-branches ;
-next     ;
-
-
-desc
-@@
-
-
-1.2
-log
-@Add code to support changing the root device at boot time.
-@
-text
-@/*
- *  linux/tools/build.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: max 510 bytes of 8086 machine code, loads the rest
- * - setup: max 4 sectors of 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-#include <stdio.h>     /* fprintf */
-#include <string.h>
-#include <stdlib.h>    /* contains exit */
-#include <sys/types.h> /* unistd.h needs this */
-#include <sys/stat.h>
-#include <linux/fs.h>
-#include <unistd.h>    /* contains read/write */
-#include <fcntl.h>
-
-#define MINIX_HEADER 32
-#define GCC_HEADER 1024
-
-#define DEFAULT_MAJOR_ROOT 3
-#define DEFAULT_MINOR_ROOT 6
-
-/* max nr of sectors of setup: don't change unless you also change
- * bootsect etc */
-#define SETUP_SECTS 4
-
-#define STRINGIFY(x) #x
-
-void die(char * str)
-{
-       fprintf(stderr,"%s\n",str);
-       exit(1);
-}
-
-void usage(void)
-{
-       die("Usage: build bootsect setup system [> image]");
-}
-
-int main(int argc, char ** argv)
-{
-       int i,c,id;
-       char buf[1024];
-       char major_root, minor_root;
-       struct stat sb;
-
-       if ((argc != 4) && (argc != 5))
-               usage();
-       if (argc == 5) {
-               if (strcmp(argv[4], "FLOPPY")) {
-                       if (stat(argv[4], &sb)) {
-                               perror(argv[4]);
-                               die("Couldn't stat root device.");
-                       }
-                       major_root = MAJOR(sb.st_rdev);
-                       minor_root = MINOR(sb.st_rdev);
-               } else {
-                       major_root = 0;
-                       minor_root = 0;
-               }
-       } else {
-               major_root = DEFAULT_MAJOR_ROOT;
-               minor_root = DEFAULT_MINOR_ROOT;
-       }
-       fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-       if ((major_root != 2) && (major_root != 3) &&
-           (major_root != 0)) {
-               fprintf(stderr, "Illegal root device (major = %d)\n",
-                       major_root);
-               die("Bad root device --- major #");
-       }
-       for (i=0;i<sizeof buf; i++) buf[i]=0;
-       if ((id=open(argv[1],O_RDONLY,0))<0)
-               die("Unable to open 'boot'");
-       if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-               die("Unable to read header of 'boot'");
-       if (((long *) buf)[0]!=0x04100301)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[1]!=MINIX_HEADER)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[3]!=0)
-               die("Illegal data segment in 'boot'");
-       if (((long *) buf)[4]!=0)
-               die("Illegal bss in 'boot'");
-       if (((long *) buf)[5] != 0)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[7] != 0)
-               die("Illegal symbol table in 'boot'");
-       i=read(id,buf,sizeof buf);
-       fprintf(stderr,"Boot sector %d bytes.\n",i);
-       if (i != 512)
-               die("Boot block must be exactly 512 bytes");
-       if ((*(unsigned short *)(buf+510)) != 0xAA55)
-               die("Boot block hasn't got boot flag (0xAA55)");
-       buf[508] = (char) minor_root;
-       buf[509] = (char) major_root;   
-       i=write(1,buf,512);
-       if (i!=512)
-               die("Write call failed");
-       close (id);
-       
-       if ((id=open(argv[2],O_RDONLY,0))<0)
-               die("Unable to open 'setup'");
-       if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-               die("Unable to read header of 'setup'");
-       if (((long *) buf)[0]!=0x04100301)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[1]!=MINIX_HEADER)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[3]!=0)
-               die("Illegal data segment in 'setup'");
-       if (((long *) buf)[4]!=0)
-               die("Illegal bss in 'setup'");
-       if (((long *) buf)[5] != 0)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[7] != 0)
-               die("Illegal symbol table in 'setup'");
-       for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
-               if (write(1,buf,c)!=c)
-                       die("Write call failed");
-       close (id);
-       if (i > SETUP_SECTS*512)
-               die("Setup exceeds " STRINGIFY(SETUP_SECTS)
-                       " sectors - rewrite build/boot/setup");
-       fprintf(stderr,"Setup is %d bytes.\n",i);
-       for (c=0 ; c<sizeof(buf) ; c++)
-               buf[c] = '\0';
-       while (i<SETUP_SECTS*512) {
-               c = SETUP_SECTS*512-i;
-               if (c > sizeof(buf))
-                       c = sizeof(buf);
-               if (write(1,buf,c) != c)
-                       die("Write call failed");
-               i += c;
-       }
-       
-       if ((id=open(argv[3],O_RDONLY,0))<0)
-               die("Unable to open 'system'");
-       if (read(id,buf,GCC_HEADER) != GCC_HEADER)
-               die("Unable to read header of 'system'");
-       if (((long *) buf)[5] != 0)
-               die("Non-GCC header of 'system'");
-       for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
-               if (write(1,buf,c)!=c)
-                       die("Write call failed");
-       close(id);
-       fprintf(stderr,"System is %d bytes.\n",i);
-       return(0);
-}
-@
-
-
-1.1
-log
-@Initial revision
-@
-text
-@d20 1
-d23 2
-d31 3
-d55 2
-d58 1
-a58 1
-       if (argc != 4)
-d60 23
-d106 2
-@
index 2118b2768bf42d29233d9f5d9b40844811cd3c25..69e25d005aa3a340a3d8dfa0564f99bbee207057 100644 (file)
  * the right amount. It also writes some system data to stderr.
  */
 
+/*
+ * Changes by tytso to allow root device specification
+ */
+
 #include <stdio.h>     /* fprintf */
 #include <string.h>
 #include <stdlib.h>    /* contains exit */
@@ -28,6 +32,8 @@
 #define MINIX_HEADER 32
 #define GCC_HEADER 1024
 
+#define SYS_SIZE 0x2000
+
 #define DEFAULT_MAJOR_ROOT 3
 #define DEFAULT_MINOR_ROOT 6
 
@@ -45,7 +51,7 @@ void die(char * str)
 
 void usage(void)
 {
-       die("Usage: build bootsect setup system [> image]");
+       die("Usage: build bootsect setup system [rootdev] [> image]");
 }
 
 int main(int argc, char ** argv)
@@ -156,5 +162,7 @@ int main(int argc, char ** argv)
                        die("Write call failed");
        close(id);
        fprintf(stderr,"System is %d bytes.\n",i);
+       if (i > SYS_SIZE*16)
+               die("System is too big");
        return(0);
 }
diff --git a/tools/build.c.orig b/tools/build.c.orig
deleted file mode 100644 (file)
index bfeac5d..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  linux/tools/build.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: max 510 bytes of 8086 machine code, loads the rest
- * - setup: max 4 sectors of 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-#include <stdio.h>     /* fprintf */
-#include <stdlib.h>    /* contains exit */
-#include <sys/types.h> /* unistd.h needs this */
-#include <unistd.h>    /* contains read/write */
-#include <fcntl.h>
-
-#define MINIX_HEADER 32
-#define GCC_HEADER 1024
-
-/* max nr of sectors of setup: don't change unless you also change
- * bootsect etc */
-#define SETUP_SECTS 4
-
-#define STRINGIFY(x) #x
-
-void die(char * str)
-{
-       fprintf(stderr,"%s\n",str);
-       exit(1);
-}
-
-void usage(void)
-{
-       die("Usage: build bootsect setup system [> image]");
-}
-
-int main(int argc, char ** argv)
-{
-       int i,c,id;
-       char buf[1024];
-
-       if (argc != 4)
-               usage();
-       for (i=0;i<sizeof buf; i++) buf[i]=0;
-       if ((id=open(argv[1],O_RDONLY,0))<0)
-               die("Unable to open 'boot'");
-       if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-               die("Unable to read header of 'boot'");
-       if (((long *) buf)[0]!=0x04100301)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[1]!=MINIX_HEADER)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[3]!=0)
-               die("Illegal data segment in 'boot'");
-       if (((long *) buf)[4]!=0)
-               die("Illegal bss in 'boot'");
-       if (((long *) buf)[5] != 0)
-               die("Non-Minix header of 'boot'");
-       if (((long *) buf)[7] != 0)
-               die("Illegal symbol table in 'boot'");
-       i=read(id,buf,sizeof buf);
-       fprintf(stderr,"Boot sector %d bytes.\n",i);
-       if (i != 512)
-               die("Boot block must be exactly 512 bytes");
-       if ((*(unsigned short *)(buf+510)) != 0xAA55)
-               die("Boot block hasn't got boot flag (0xAA55)");
-       i=write(1,buf,512);
-       if (i!=512)
-               die("Write call failed");
-       close (id);
-       
-       if ((id=open(argv[2],O_RDONLY,0))<0)
-               die("Unable to open 'setup'");
-       if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-               die("Unable to read header of 'setup'");
-       if (((long *) buf)[0]!=0x04100301)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[1]!=MINIX_HEADER)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[3]!=0)
-               die("Illegal data segment in 'setup'");
-       if (((long *) buf)[4]!=0)
-               die("Illegal bss in 'setup'");
-       if (((long *) buf)[5] != 0)
-               die("Non-Minix header of 'setup'");
-       if (((long *) buf)[7] != 0)
-               die("Illegal symbol table in 'setup'");
-       for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
-               if (write(1,buf,c)!=c)
-                       die("Write call failed");
-       close (id);
-       if (i > SETUP_SECTS*512)
-               die("Setup exceeds " STRINGIFY(SETUP_SECTS)
-                       " sectors - rewrite build/boot/setup");
-       fprintf(stderr,"Setup is %d bytes.\n",i);
-       for (c=0 ; c<sizeof(buf) ; c++)
-               buf[c] = '\0';
-       while (i<SETUP_SECTS*512) {
-               c = SETUP_SECTS*512-i;
-               if (c > sizeof(buf))
-                       c = sizeof(buf);
-               if (write(1,buf,c) != c)
-                       die("Write call failed");
-               i += c;
-       }
-       
-       if ((id=open(argv[3],O_RDONLY,0))<0)
-               die("Unable to open 'system'");
-       if (read(id,buf,GCC_HEADER) != GCC_HEADER)
-               die("Unable to read header of 'system'");
-       if (((long *) buf)[5] != 0)
-               die("Non-GCC header of 'system'");
-       for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
-               if (write(1,buf,c)!=c)
-                       die("Write call failed");
-       close(id);
-       fprintf(stderr,"System is %d bytes.\n",i);
-       return(0);
-}