]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.99.6 (February 21, 1993) 0.99.6
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:09 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:09 +0000 (15:09 -0500)
Merge a lot of duplicated special file handling into fs/devices.c, and
make drivers register their major numbers properly.

VFS layer gets fsync virtual function.

Compressed image boot, with the kernel loaded into high memory..

[original announcement below]

I'm starting soon to run out of patchlevel numbers for 0.99, but I made
a new release anyway (and long-time linux hackers remember my less than
completely logical numbering: when I run out of numbers I'll start using
alphabetical characters and other fun characters to indicate new
versions :-)

0.99pl6 is mainly a syncronization release: it fixes a few bugs and
changes the behaviour of 'vhangup()' to be more standard.  The vhangup()
changes will break some init/login stuff that depended on the earlier
incorrect behaviour - not everybody may want to use pl6 until you are
sure your init/login will work happily with it.  Better do these things
before 1.0 than to break it later.

Patchlevel 6 also changes the vfs functions for special devices as well
as adding a 'fsync' field to the inode-operations structure.  Thus
ext2fs and xfs need updating.  Remy and Xia? The special file and fifo
handling code is no longer supposed to be in the fs-dependent layer, but
is handled by the vfs routines, as it's the same for all "normal"
filesystems.

Ok, here are the actual changes/features of pl6:
- the kernel can be loaded in gzipped format and de-compressed at
  startup beyond the 1MB mark.  Good for bootable rootdisks.  Patches
  mainly by Hannu Savolainen.
- I finally enabled NMI's everywhere (except at the bootup sequence),
  so if you have memory errors, they will hopefully now result in
  kernel messages ("NMI received..")
- the device registration code for special devices.  Special files are
  now registered with a special "register_[chr|blk]dev()" function.
- consolidated fifo/special dev handling
- vhangup patches.  Note that these may break init/login badly, at
  least if you are using poeigl-1.7.  Be careful that you don't get
  totally locked out of your machine.
- the procfs NULL-dereferencing bugfix (michaelkjohnson)
- literal next character handling (very losely based on a patch I
  received: I essentially rewrote it with final fixes by jrs).
- fpu-emu bugfixes by Bill Metzenthen - fixes the "internal error 112"
  bug as well as a sign bug with zero.
- fdomain driver fixes
- various other minor fixes (wrongly replying to bad ip messages etc)

I'm still not sure about the 387 error detection code: I have had a
couple of messages that would suggest that some early clone 387's have
problems with math exceptions in protected mode.  With the new (as of
99pl5) test at startup this can lead to problems at boot-time.  Please
mail me directly if you seem to have problems with this (it should be
obvious in pl6 due to debugging messages at startup).

            Linus

87 files changed:
Makefile
boot/setup.S
fs/Makefile
fs/devices.c [new file with mode: 0644]
fs/ext/Makefile
fs/ext/blkdev.c [deleted file]
fs/ext/chrdev.c [deleted file]
fs/ext/dir.c
fs/ext/fifo.c [deleted file]
fs/ext/file.c
fs/ext/inode.c
fs/ext/namei.c
fs/fifo.c
fs/inode.c
fs/isofs/Makefile
fs/isofs/blkdev.c [deleted file]
fs/isofs/chrdev.c [deleted file]
fs/isofs/dir.c
fs/isofs/fifo.c [deleted file]
fs/isofs/file.c
fs/isofs/inode.c
fs/minix/Makefile
fs/minix/blkdev.c [deleted file]
fs/minix/chrdev.c [deleted file]
fs/minix/dir.c
fs/minix/fifo.c [deleted file]
fs/minix/file.c
fs/minix/inode.c
fs/minix/namei.c
fs/msdos/dir.c
fs/msdos/file.c
fs/nfs/Makefile
fs/nfs/blkdev.c [deleted file]
fs/nfs/chrdev.c [deleted file]
fs/nfs/dir.c
fs/nfs/fifo.c [deleted file]
fs/nfs/file.c
fs/open.c
fs/pipe.c
fs/proc/array.c
fs/proc/base.c
fs/proc/fd.c
fs/proc/kmsg.c
fs/proc/mem.c
fs/proc/root.c
fs/super.c
include/linux/dirent.h
include/linux/fd.h
include/linux/fs.h
include/linux/sched.h
include/linux/tty.h
init/main.c
kernel/FPU-emu/Makefile
kernel/FPU-emu/fpu_trig.c
kernel/FPU-emu/reg_add_sub.c
kernel/FPU-emu/version.h
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/scsi/fdomain.c
kernel/blk_drv/scsi/sd.c
kernel/blk_drv/scsi/sr.c
kernel/blk_drv/scsi/st.c
kernel/blk_drv/scsi/wd7000.c
kernel/chr_drv/console.c
kernel/chr_drv/keyboard.c
kernel/chr_drv/lp.c
kernel/chr_drv/mem.c
kernel/chr_drv/mouse.c
kernel/chr_drv/serial.c
kernel/chr_drv/tty_io.c
mm/memory.c
net/tcp/dev.c
net/tcp/ip.c
tools/build.c
zBoot/Makefile [new file with mode: 0644]
zBoot/crypt.h [new file with mode: 0644]
zBoot/gzip.h [new file with mode: 0644]
zBoot/head.S [new file with mode: 0644]
zBoot/inflate.c [new file with mode: 0644]
zBoot/lzw.h [new file with mode: 0644]
zBoot/misc.c [new file with mode: 0644]
zBoot/piggyback.c [new file with mode: 0644]
zBoot/unzip.c [new file with mode: 0644]
zBoot/xtract.c [new file with mode: 0644]

index 0ef7fabccc4892b44d699bed11c3c94a23718c45..6aa6b996a3b3abe366e1031f5a47f74b841b94dd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -147,17 +147,14 @@ tools/./version.h: tools/version.h
 
 tools/version.h: $(CONFIGURE) Makefile
        @./makever.sh
-       @echo \#define UTS_RELEASE \"0.99.pl5-`cat .version`\" > tools/version.h
+       @echo \#define UTS_RELEASE \"0.99.pl6-`cat .version`\" > tools/version.h
        @echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
 
 Image: $(CONFIGURE) boot/bootsect boot/setup tools/system tools/build
-       cp tools/system system.tmp
-       $(STRIP) system.tmp
-       tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
-       rm system.tmp
+       tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
        sync
 
 disk: Image
@@ -200,6 +197,33 @@ boot/bootsect:     boot/bootsect.s
        $(AS86) -o boot/bootsect.o boot/bootsect.s
        $(LD86) -s -o boot/bootsect boot/bootsect.o
 
+zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
+       cd zBoot;$(MAKE)
+
+zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build
+       cp zBoot/zSystem system.tmp
+       $(STRIP) system.tmp
+       tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > zImage
+       rm system.tmp
+       sync
+
+zdisk: zImage
+       dd bs=8192 if=zImage of=/dev/fd0
+
+zlilo: $(CONFIGURE) zImage
+       cat zImage > /vmlinuz
+       /etc/lilo/install
+
+
+tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
+       $(LD) $(LDFLAGS) -T 100000 -M boot/head.o init/main.o tools/version.o \
+               $(ARCHIVES) \
+               $(FILESYSTEMS) \
+               $(DRIVERS) \
+               $(MATH) \
+               $(LIBS) \
+               -o tools/zSystem > zSystem.map
+
 fs: dummy
        $(MAKE) linuxsubdirs SUBDIRS=fs
 
@@ -210,10 +234,11 @@ kernel: dummy
        $(MAKE) linuxsubdirs SUBDIRS=kernel
 
 clean:
+       rm -f zImage zSystem.map tools/zSystem
        rm -f Image System.map core boot/bootsect boot/setup \
                boot/bootsect.s boot/setup.s boot/head.s init/main.s
        rm -f init/*.o tools/system tools/build boot/*.o tools/*.o
-       for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done
+       for i in zBoot $(SUBDIRS); do (cd $$i && $(MAKE) clean); done
 
 backup: clean
        cd .. && tar cf - linux | compress - > backup.Z
index b8db58fdb85dc2f9b723ba588de5718f03b4987f..83f310162af3a7e1ed2cb7f8e567907fd1771511 100644 (file)
@@ -146,6 +146,8 @@ no_psmouse:
 ! now we want to move to protected mode ...
 
        cli                     ! no interrupts allowed !
+       mov     al,#0x80        ! disable NMI for the bootup sequence
+       out     #0x70,al
 
 ! first we move the system to it's rightful place
 
index 3d93208a6f4e1fd1477f2a1aefe9b2025e85eebe..8a32ef89c1c4e65dec8b404a5681a471487c0dbf 100644 (file)
@@ -35,7 +35,7 @@ endif
 .s.o:
        $(AS) -o $*.o $<
 
-OBJS=  open.o read_write.o inode.o file_table.o buffer.o super.o \
+OBJS=  open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
        block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
        select.o fifo.o locks.o filesystems.o
 
diff --git a/fs/devices.c b/fs/devices.c
new file mode 100644 (file)
index 0000000..b3bb1c5
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  linux/fs/devices.c
+ *
+ * (C) 1993 Matthias Urlichs -- collected common code and tables.
+ * 
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/ext_fs.h>
+#include <linux/tty.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
+
+struct file_operations * chrdev_fops[MAX_CHRDEV] = {
+       NULL,
+};
+
+struct file_operations * blkdev_fops[MAX_BLKDEV] = {
+       NULL,
+};
+
+int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
+{
+       if (major >= MAX_CHRDEV)
+               return -EINVAL;
+       if (chrdev_fops[major])
+               return -EBUSY;
+       chrdev_fops[major] = fops;
+       return 0;
+}
+
+int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
+{
+       if (major >= MAX_BLKDEV)
+               return -EINVAL;
+       if (blkdev_fops[major])
+               return -EBUSY;
+       blkdev_fops[major] = fops;
+       return 0;
+}
+
+/*
+ * Called every time a block special file is opened
+ */
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+       int i;
+
+       i = MAJOR(inode->i_rdev);
+       if (i >= MAX_BLKDEV || !blkdev_fops[i])
+               return -ENODEV;
+       filp->f_op = blkdev_fops[i];
+       if (filp->f_op->open)
+               return filp->f_op->open(inode,filp);
+       return 0;
+}      
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+struct file_operations def_blk_fops = {
+       NULL,           /* lseek */
+       NULL,           /* read */
+       NULL,           /* write */
+       NULL,           /* readdir */
+       NULL,           /* select */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       blkdev_open,    /* open */
+       NULL,           /* release */
+};
+
+struct inode_operations blkdev_inode_operations = {
+       &def_blk_fops,          /* default file operations */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
+
+/*
+ * Called every time a character special file is opened
+ */
+int chrdev_open(struct inode * inode, struct file * filp)
+{
+       int i;
+
+       i = MAJOR(inode->i_rdev);
+       if (i >= MAX_CHRDEV || !chrdev_fops[i])
+               return -ENODEV;
+       filp->f_op = chrdev_fops[i];
+       if (filp->f_op->open)
+               return filp->f_op->open(inode,filp);
+       return 0;
+}
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+struct file_operations def_chr_fops = {
+       NULL,           /* lseek */
+       NULL,           /* read */
+       NULL,           /* write */
+       NULL,           /* readdir */
+       NULL,           /* select */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       chrdev_open,    /* open */
+       NULL,           /* release */
+};
+
+struct inode_operations chrdev_inode_operations = {
+       &def_chr_fops,          /* default file operations */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
index 205c05fc7eef3611ac3b27180cf7a9acb2f6380c..4d241db7f0b27c8ebd3e3d44d5d6e23d9a251c55 100644 (file)
@@ -15,7 +15,7 @@
        $(AS) -o $*.o $<
 
 OBJS=  freelists.o truncate.o namei.o inode.o \
-       file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+       file.o dir.o symlink.o 
 
 ext.o: $(OBJS)
        $(LD) -r -o ext.o $(OBJS)
diff --git a/fs/ext/blkdev.c b/fs/ext/blkdev.c
deleted file mode 100644 (file)
index 2f96b8e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  linux/fs/ext/blkdev.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/blkdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Called every time an ext block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_BLKDEV || !blkdev_fops[i])
-               return -ENODEV;
-       filp->f_op = blkdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}      
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       blkdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations ext_blkdev_inode_operations = {
-       &def_blk_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
diff --git a/fs/ext/chrdev.c b/fs/ext/chrdev.c
deleted file mode 100644 (file)
index 360be86..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  linux/fs/ext/chrdev.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/chrdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Called every time an ext character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_CHRDEV || !chrdev_fops[i])
-               return -ENODEV;
-       filp->f_op = chrdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       chrdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations ext_chrdev_inode_operations = {
-       &def_chr_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
-
index b10152c2a56e7c54aa93707a74797da99b875415..da09fb41f1d8bb221206872f4edd5d1d121bea8a 100644 (file)
@@ -36,7 +36,8 @@ static struct file_operations ext_dir_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* fsync */
 };
 
 /*
diff --git a/fs/ext/fifo.c b/fs/ext/fifo.c
deleted file mode 100644 (file)
index a1b04e1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove.
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations ext_fifo_inode_operations = {
-       &def_fifo_fops,         /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
index ad5024544928efb9f0ee5e4cc459946ee42a29cb..804e6fb8535e8b36779b75e6f4089fe9661ba057 100644 (file)
@@ -47,7 +47,8 @@ static struct file_operations ext_file_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open is needed */
-       NULL                    /* release */
+       NULL,                   /* release */
+       NULL                    /* fsync */
 };
 
 struct inode_operations ext_file_inode_operations = {
index 383700263f963b67d78e4df47d691ee0afdc6c79..33942a1aff05da1d5f3355f6f3b11b9c6295c7a2 100644 (file)
@@ -372,11 +372,11 @@ void ext_read_inode(struct inode * inode)
        else if (S_ISLNK(inode->i_mode))
                inode->i_op = &ext_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &ext_chrdev_inode_operations;
+               inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &ext_blkdev_inode_operations;
+               inode->i_op = &blkdev_inode_operations;
        else if (S_ISFIFO(inode->i_mode)) {
-               inode->i_op = &ext_fifo_inode_operations;
+               inode->i_op = &fifo_inode_operations;
                inode->i_pipe = 1;
                PIPE_BASE(*inode) = NULL;
                PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
index bfb0171919f2e8325e13d8f778a332c7aaa6f7a6..1421b54c09eb6f22f93d480d192528e2dc56fa71 100644 (file)
@@ -369,11 +369,11 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
        else if (S_ISLNK(inode->i_mode))
                inode->i_op = &ext_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &ext_chrdev_inode_operations;
+               inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &ext_blkdev_inode_operations;
+               inode->i_op = &blkdev_inode_operations;
        else if (S_ISFIFO(inode->i_mode)) {
-               inode->i_op = &ext_fifo_inode_operations;
+               inode->i_op = &fifo_inode_operations;
                inode->i_pipe = 1;
                PIPE_BASE(*inode) = NULL;
                PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
index 3918251ffcd370ee83bb0fe489f3f3baeb74acf2..3ca5fc3ea053041c48e87946bc75302d1a82db08 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -112,5 +112,24 @@ struct file_operations def_fifo_fops = {
        NULL,
        NULL,
        fifo_open,              /* will set read or write pipe_fops */
+       NULL,
        NULL
 };
+
+struct inode_operations fifo_inode_operations = {
+       &def_fifo_fops,         /* default file operations */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
index 276513a57387e2fef47daae7d9766130948bdabf..b83c789bc4494fd63794e25baf9a095998935501 100644 (file)
@@ -177,6 +177,8 @@ void sync_inodes(dev_t dev)
        struct inode * inode;
 
        for(inode = 0+inode_table ; inode < NR_INODE+inode_table ; inode++) {
+               if (dev && inode->i_dev != dev)
+                       continue;
                wait_on_inode(inode);
                if (inode->i_dirt)
                        write_inode(inode);
index 06fffff20624cfc5fba6585e5141562862b1abaf..1417145f5700031bca295b8572ce5f8128d5958d 100644 (file)
@@ -14,8 +14,7 @@
 .s.o:
        $(AS) -o $*.o $<
 
-OBJS=  namei.o inode.o file.o dir.o util.o rock.o symlink.o \
-       fifo.o blkdev.o chrdev.o
+OBJS=  namei.o inode.o file.o dir.o util.o rock.o symlink.o
 
 isofs.o: $(OBJS)
        $(LD) -r -o isofs.o $(OBJS)
diff --git a/fs/isofs/blkdev.c b/fs/isofs/blkdev.c
deleted file mode 100644 (file)
index ce1b791..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  linux/fs/isofs/blkdev.c
- *
- *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  isofs blkdev handling code.  This is only used with the Rock Ridge
- *  extensions to iso9660
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a isofs block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_BLKDEV || !blkdev_fops[i])
-               return -ENODEV;
-       filp->f_op = blkdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}      
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       blkdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations isofs_blkdev_inode_operations = {
-       &def_blk_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       isofs_bmap,             /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
diff --git a/fs/isofs/chrdev.c b/fs/isofs/chrdev.c
deleted file mode 100644 (file)
index e584b48..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  linux/fs/isofs/chrdev.c
- *
- *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  isofs chrdev handling code.  This is only used with the Rock Ridge
- *  extensions to iso9660
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a isofs character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_CHRDEV || !chrdev_fops[i])
-               return -ENODEV;
-       filp->f_op = chrdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       chrdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations isofs_chrdev_inode_operations = {
-       &def_chr_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       isofs_bmap,             /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
-
index 99943f6f6a29c51a15f460cd02ec52f34b5f6b9f..fd906db042ccedc23426f7636803323dc826ae74 100644 (file)
@@ -29,7 +29,8 @@ static struct file_operations isofs_dir_operations = {
        NULL,                   /* select - default */
        NULL,                   /* ioctl - default */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* fsync */
 };
 
 /*
diff --git a/fs/isofs/fifo.c b/fs/isofs/fifo.c
deleted file mode 100644 (file)
index da03133..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/iso_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations isofs_fifo_inode_operations = {
-       &def_fifo_fops,         /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
index effca2d74aae8ae11b4b291e097cf88026cde88a..223e7d0c483117b3a7afae16ce6b84228bb4b345 100644 (file)
@@ -43,7 +43,8 @@ static struct file_operations isofs_file_operations = {
        NULL,                   /* select - default */
        NULL,                   /* ioctl - default */
        NULL,                   /* no special open is needed */
-       NULL                    /* release */
+       NULL,                   /* release */
+       NULL                    /* fsync */
 };
 
 struct inode_operations isofs_file_inode_operations = {
index 39b00fabe4f9bf4904e875b5a451c7c4f40935fb..233146ef4bacd2d2e034313ac564cc450f44e5bf 100644 (file)
@@ -412,11 +412,11 @@ void isofs_read_inode(struct inode * inode)
        else if (S_ISLNK(inode->i_mode))
                inode->i_op = &isofs_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &isofs_chrdev_inode_operations;
+               inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &isofs_blkdev_inode_operations;
+               inode->i_op = &blkdev_inode_operations;
        else if (S_ISFIFO(inode->i_mode)) {
-               inode->i_op = &isofs_fifo_inode_operations;
+               inode->i_op = &fifo_inode_operations;
                inode->i_pipe = 1;
                PIPE_BASE(*inode) = NULL;
                PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
index aac524291bd4727d11e776992088c4b036e4fd9b..80109a0acae601bde33fee5d4673186ed4230d92 100644 (file)
@@ -15,7 +15,7 @@
        $(AS) -o $*.o $<
 
 OBJS=  bitmap.o truncate.o namei.o inode.o \
-       file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+       file.o dir.o symlink.o 
 
 minix.o: $(OBJS)
        $(LD) -r -o minix.o $(OBJS)
diff --git a/fs/minix/blkdev.c b/fs/minix/blkdev.c
deleted file mode 100644 (file)
index 2e4f03a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  linux/fs/minix/blkdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_BLKDEV || !blkdev_fops[i])
-               return -ENODEV;
-       filp->f_op = blkdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}      
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       blkdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations minix_blkdev_inode_operations = {
-       &def_blk_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
diff --git a/fs/minix/chrdev.c b/fs/minix/chrdev.c
deleted file mode 100644 (file)
index 622e745..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  linux/fs/minix/chrdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_CHRDEV || !chrdev_fops[i])
-               return -ENODEV;
-       filp->f_op = chrdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       chrdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations minix_chrdev_inode_operations = {
-       &def_chr_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
-
index 2a162bbd15ae2c820e0f355f93b5c8502f14c218..b2535ba2fa3320f6d3901dc42f65f2dd1c3bcaad 100644 (file)
@@ -29,7 +29,8 @@ static struct file_operations minix_dir_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* default fsync */
 };
 
 /*
diff --git a/fs/minix/fifo.c b/fs/minix/fifo.c
deleted file mode 100644 (file)
index 5da93b0..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations minix_fifo_inode_operations = {
-       &def_fifo_fops,         /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
index 026a884f0ccf0ee761ffc5d178f053bf00ceb853..6f70ac610f7b1369a7b8f45051efe016a7f4bf92 100644 (file)
@@ -41,7 +41,8 @@ static struct file_operations minix_file_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open is needed */
-       NULL                    /* release */
+       NULL,                   /* release */
+       NULL                    /* fsync */
 };
 
 struct inode_operations minix_file_inode_operations = {
index 32cfd7757f68974fd46f574db916f8ee6313270c..76d4bc4195f4845c4fa2e390267af87862cd553d 100644 (file)
@@ -345,11 +345,11 @@ void minix_read_inode(struct inode * inode)
        else if (S_ISLNK(inode->i_mode))
                inode->i_op = &minix_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &minix_chrdev_inode_operations;
+               inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &minix_blkdev_inode_operations;
+               inode->i_op = &blkdev_inode_operations;
        else if (S_ISFIFO(inode->i_mode)) {
-               inode->i_op = &minix_fifo_inode_operations;
+               inode->i_op = &fifo_inode_operations;
                inode->i_pipe = 1;
                PIPE_BASE(*inode) = NULL;
                PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
@@ -373,8 +373,11 @@ void minix_write_inode(struct inode * inode)
        }
        block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
                (ino-1)/MINIX_INODES_PER_BLOCK;
-       if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
-               panic("unable to read i-node block");
+       if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
+               printk("unable to read i-node block\n");
+               inode->i_dirt = 0;
+               return;
+       }
        raw_inode = ((struct minix_inode *)bh->b_data) +
                (ino-1)%MINIX_INODES_PER_BLOCK;
        raw_inode->i_mode = inode->i_mode;
index c2ba87f1e7a789647fe7df49cd5f0472e7cad1b2..5af220e11abc18bb137a548dcb169efdba8e10f3 100644 (file)
@@ -261,11 +261,11 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
        else if (S_ISLNK(inode->i_mode))
                inode->i_op = &minix_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &minix_chrdev_inode_operations;
+               inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &minix_blkdev_inode_operations;
+               inode->i_op = &blkdev_inode_operations;
        else if (S_ISFIFO(inode->i_mode)) {
-               inode->i_op = &minix_fifo_inode_operations;
+               inode->i_op = &fifo_inode_operations;
                inode->i_pipe = 1;
                PIPE_BASE(*inode) = NULL;
                PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
index caf5b43faa057795c63ca80ff55b557bd7d2d1df..12a5a45fcca6de3f8cfbe192e3028956ca7b338b 100644 (file)
@@ -31,7 +31,8 @@ static struct file_operations msdos_dir_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* fsync */
 };
 
 struct inode_operations msdos_dir_inode_operations = {
index 1406028c8612d88e891942daf1cab8e07998a855..ec446fb0f3d7aed29ae38659cc73c3d4d3d863ef 100644 (file)
@@ -34,7 +34,8 @@ static struct file_operations msdos_file_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open is needed */
-       NULL                    /* release */
+       NULL,                   /* release */
+       NULL                    /* fsync */
 };
 
 struct inode_operations msdos_file_inode_operations = {
index f422bfa804f2e421c430f445fd3de2645843b18f..f4fdd2f4572e2dfb993fed28d4ea352ce7b6bfd1 100644 (file)
@@ -15,7 +15,7 @@
        $(AS) -o $*.o $<
 
 OBJS=  proc.o sock.o inode.o file.o dir.o \
-       symlink.o blkdev.o chrdev.o fifo.o
+       symlink.o 
 
 nfs.o: $(OBJS)
        $(LD) -r -o nfs.o $(OBJS)
diff --git a/fs/nfs/blkdev.c b/fs/nfs/blkdev.c
deleted file mode 100644 (file)
index 3b7c956..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  linux/fs/nfs/blkdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a nfs block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_BLKDEV || !blkdev_fops[i])
-               return -ENODEV;
-       filp->f_op = blkdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}      
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       blkdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations nfs_blkdev_inode_operations = {
-       &def_blk_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
diff --git a/fs/nfs/chrdev.c b/fs/nfs/chrdev.c
deleted file mode 100644 (file)
index 844094d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  linux/fs/nfs/chrdev.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a nfs character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
-       int i;
-
-       i = MAJOR(inode->i_rdev);
-       if (i >= MAX_CHRDEV || !chrdev_fops[i])
-               return -ENODEV;
-       filp->f_op = chrdev_fops[i];
-       if (filp->f_op->open)
-               return filp->f_op->open(inode,filp);
-       return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* select */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       chrdev_open,    /* open */
-       NULL,           /* release */
-};
-
-struct inode_operations nfs_chrdev_inode_operations = {
-       &def_chr_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
-
index f1a33044426938f4f55b7a74f1ce3fbb03e8918f..0ea79ad144f75c4456b08d3ae731d0f11a93b804 100644 (file)
@@ -46,7 +46,8 @@ static struct file_operations nfs_dir_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* fsync */
 };
 
 struct inode_operations nfs_dir_inode_operations = {
@@ -627,11 +628,11 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
                else if (S_ISLNK(inode->i_mode))
                        inode->i_op = &nfs_symlink_inode_operations;
                else if (S_ISCHR(inode->i_mode))
-                       inode->i_op = &nfs_chrdev_inode_operations;
+                       inode->i_op = &chrdev_inode_operations;
                else if (S_ISBLK(inode->i_mode))
-                       inode->i_op = &nfs_blkdev_inode_operations;
+                       inode->i_op = &blkdev_inode_operations;
                else if (S_ISFIFO(inode->i_mode)) {
-                       inode->i_op = &nfs_fifo_inode_operations;
+                       inode->i_op = &fifo_inode_operations;
                        inode->i_pipe = 1;
                        PIPE_BASE(*inode) = NULL;
                        PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
diff --git a/fs/nfs/fifo.c b/fs/nfs/fifo.c
deleted file mode 100644 (file)
index 635b9b6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/nfs_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations nfs_fifo_inode_operations = {
-       &def_fifo_fops,         /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
index d3d4c6701e0cf95d7a922e024a277ad207ab0150..cbf27b367754bf9ab158769f1337d9fe846cddd5 100644 (file)
@@ -29,7 +29,8 @@ static struct file_operations nfs_file_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open is needed */
-       NULL                    /* release */
+       NULL,                   /* release */
+       NULL                    /* fsync */
 };
 
 struct inode_operations nfs_file_inode_operations = {
index 9aa632fbb27faa6824bf55d598234b88943ede80..ebd7d9a6c9683c172dea4b52d4cbe77b324f2a5f 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 
 extern void fcntl_remove_locks(struct task_struct *, struct file *);
 
-struct file_operations * chrdev_fops[MAX_CHRDEV] = {
-       NULL,
-};
-
-struct file_operations * blkdev_fops[MAX_BLKDEV] = {
-       NULL,
-};
-
 int sys_ustat(int dev, struct ustat * ubuf)
 {
        return -ENOSYS;
@@ -452,102 +444,19 @@ int sys_close(unsigned int fd)
 }
 
 /*
- * This routine is used by vhangup.  It send's sigkill to everything
- * waiting on a particular wait_queue.  It assumes root privledges.
- * We don't want to destroy the wait queue here, because the caller
- * should call wake_up immediately after calling kill_wait.
- */
-static void kill_wait(struct wait_queue **q, int sig)
-{
-       struct wait_queue *next;
-       struct wait_queue *tmp;
-       struct task_struct *p;
-
-       if (!q || !(next = *q))
-               return;
-       do { 
-               tmp = next;
-               next = tmp->next;
-               if ((p = tmp->task) != NULL)
-                       send_sig (sig, p , 1);
-       } while (next && next != *q);
-}
-
-/*
- * This routine looks through all the process's and closes any
- * references to the current processes tty.  To avoid problems with
- * process sleeping on an inode which has already been iput, anyprocess
- * which is sleeping on the tty is sent a sigkill (It's probably a rogue
- * process.)  Also no process should ever have /dev/console as it's
- * controlling tty, or have it open for reading.  So we don't have to
- * worry about messing with all the daemons abilities to write messages
- * to the console.  (Besides they should be using syslog.)
+ * This routine simulates a hangup on the tty, to arrange that users
+ * are given clean terminals at login time.
  */
 int sys_vhangup(void)
 {
-       int j;
-       struct task_struct ** process;
-       struct file *filep;
-       struct inode *inode;
        struct tty_struct *tty;
-       extern int kill_pg (int pgrp, int sig, int priv);
 
        if (!suser())
                return -EPERM;
        /* See if there is a controlling tty. */
        if (current->tty < 0)
                return 0;
-       /* send the SIGHUP signal. */
-       tty = TTY_TABLE(current->tty);
-       if (tty && tty->pgrp > 0)
-               kill_pg(tty->pgrp, SIGHUP, 0);
-
-       for (process = task + 0; process < task + NR_TASKS; process++) {
-               for (j = 0; j < NR_OPEN; j++) {
-                       if (!*process)
-                               break;
-                       if (!(filep = (*process)->filp[j]))
-                               continue;
-                       if (!(inode = filep->f_inode))
-                               continue;
-                       if (!S_ISCHR(inode->i_mode))
-                               continue;
-                       if ((MAJOR(inode->i_rdev) == 5 ||
-                            MAJOR(inode->i_rdev) == 4 ) &&
-                           (MAJOR(filep->f_rdev) == 4 &&
-                            MINOR(filep->f_rdev) == MINOR (current->tty))) {
-                 /* so now we have found something to close.  We
-                    need to kill every process waiting on the
-                    inode. */
-                               (*process)->filp[j] = NULL;
-                               kill_wait (&inode->i_wait, SIGKILL);
-
-                 /* now make sure they are awake before we close the
-                    file. */
-
-                               wake_up (&inode->i_wait);
-
-                 /* finally close the file. */
-
-                               FD_CLR(j, &(*process)->close_on_exec);
-                               close_fp (filep);
-                       }
-               }
-       /* can't let them keep a reference to it around.
-          But we can't touch current->tty until after the
-          loop is complete. */
-
-               if (*process && (*process)->tty == current->tty && *process != current) {
-                       (*process)->tty = -1;
-               }
-       }
-   /* need to do tty->session = 0 */
        tty = TTY_TABLE(MINOR(current->tty));
-       if (tty) {
-               tty->session = 0;
-               tty->pgrp = -1;
-               current->tty = -1;
-       }
+       tty_hangup(tty);
        return 0;
 }
-
index 6ac34c1c47df19d0b28aa68454f2019459a0b399..ac8b9ebc4125a19f1a6343e0cc23a5773b41eb64 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -179,7 +179,8 @@ struct file_operations read_pipe_fops = {
        pipe_ioctl,
        NULL,           /* no mmap on pipes.. surprise */
        NULL,           /* no special open code */
-       pipe_read_release
+       pipe_read_release,
+       NULL
 };
 
 struct file_operations write_pipe_fops = {
@@ -191,7 +192,8 @@ struct file_operations write_pipe_fops = {
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* no special open code */
-       pipe_write_release
+       pipe_write_release,
+       NULL
 };
 
 struct file_operations rdwr_pipe_fops = {
@@ -203,7 +205,8 @@ struct file_operations rdwr_pipe_fops = {
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* no special open code */
-       pipe_rdwr_release
+       pipe_rdwr_release,
+       NULL
 };
 
 int sys_pipe(unsigned long * fildes)
index b3ed0b97cdd30aecc002ebf2d5745280246430f1..e9e6cf27aa28a09ba989e345ac41aac31530d02c 100644 (file)
@@ -181,7 +181,7 @@ static int get_stat(int pid, char * buffer)
 {
        struct task_struct ** p = get_task(pid);
        unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
-       int i;
+       int i,tty_pgrp;
        char state;
 
        if (!p || !*p)
@@ -198,6 +198,11 @@ static int get_stat(int pid, char * buffer)
                default: sigcatch |= bit;
                } bit <<= 1;
        }
+       tty_pgrp = (*p)->tty;
+       if (tty_pgrp > 0 && tty_table[tty_pgrp])
+               tty_pgrp = tty_table[tty_pgrp]->pgrp;
+       else
+               tty_pgrp = -1;
        return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
 %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
 %d %d %d %u\n",
@@ -208,8 +213,7 @@ static int get_stat(int pid, char * buffer)
                (*p)->pgrp,
                (*p)->session,
                (*p)->tty,
-               ((*p)->tty == -1) ? -1 :
-                      tty_table[(*p)->tty]->pgrp,
+               tty_pgrp,
                (*p)->flags,
                (*p)->min_flt,
                (*p)->cmin_flt,
@@ -354,7 +358,8 @@ static struct file_operations proc_array_operations = {
        NULL,           /* array_ioctl */
        NULL,           /* mmap */
        NULL,           /* no special open code */
-       NULL            /* no special release code */
+       NULL,           /* no special release code */
+       NULL            /* can't fsync */
 };
 
 struct inode_operations proc_array_inode_operations = {
index 487b925c138e6f5a10b481f39f55ca07b8c3489e..51009b660ead0172fac799c9a883c4ddd5c72a36 100644 (file)
@@ -25,7 +25,8 @@ static struct file_operations proc_base_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* can't fsync */
 };
 
 /*
index e353ba25e2bd1ec9ce5d992ae687ca70218f4eb2..25f7b46cb67b70711fc37f152d43509341ed6655 100644 (file)
@@ -25,7 +25,8 @@ static struct file_operations proc_fd_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* can't fsync */
 };
 
 /*
index 8f29d369d4075d513884fd29ccc47208a3a85fae..3ef339f6de6bad52b57e9a6fec24a0a7bf5425df 100644 (file)
@@ -54,7 +54,8 @@ static struct file_operations proc_kmsg_operations = {
        NULL,           /* kmsg_ioctl */
        NULL,           /* mmap */
        kmsg_open,
-       kmsg_release
+       kmsg_release,
+       NULL            /* can't fsync */
 };
 
 struct inode_operations proc_kmsg_inode_operations = {
index 1068f040361942e773427f5ed092e5a61c38f580..368e28fff8a850a308325568192ac68b422e1305 100644 (file)
@@ -149,7 +149,8 @@ static struct file_operations proc_mem_operations = {
        NULL,           /* mem_ioctl */
        NULL,           /* mmap */
        NULL,           /* no special open code */
-       NULL            /* no special release code */
+       NULL,           /* no special release code */
+       NULL            /* can't fsync */
 };
 
 struct inode_operations proc_mem_inode_operations = {
index 3dbec2dae91304072be09865cef9f8488eb459ff..aa07cf75044d50f3b703f9c229c37c5990115add 100644 (file)
@@ -25,7 +25,8 @@ static struct file_operations proc_root_operations = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open code */
-       NULL                    /* no special release code */
+       NULL,                   /* no special release code */
+       NULL                    /* no fsync */
 };
 
 /*
index a5acab0a1680836f1a8ff1c4410c6414d970b338..f5dd73ca75d9563c17bb8ce2fa77c34b94ad35dc 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 extern struct file_system_type file_systems[];
+extern struct file_operations * blkdev_fops[];
 
 extern void wait_for_keypress(void);
 extern void fcntl_init_locks(void);
@@ -67,6 +68,8 @@ void sync_supers(dev_t dev)
        for (sb = super_block + 0 ; sb < super_block + NR_SUPER ; sb++) {
                if (!sb->s_dev)
                        continue;
+               if (dev && sb->s_dev != dev)
+                       continue;
                wait_on_super(sb);
                if (!sb->s_dev || !sb->s_dirt)
                        continue;
index 01d16c8aa1050f3f2fae2dcc5305883e0b91bf1e..219faf1cb765963110030e4b15fb2924e0f01012 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_DIRENT_H
 #define _LINUX_DIRENT_H
 
+#include <linux/limits.h>
+
 struct dirent {
        long            d_ino;
        off_t           d_off;
index 4828db0ddfefe012c920fd37261420a2cd3d572d..12332f3e31d40202e27fcd6b89773f38a66fe115 100644 (file)
@@ -11,6 +11,9 @@
 #define        FDFMTTRK 7 /* format the specified track */
 #define FDFMTEND 8 /* end formatting a disk */
 #define FDSETEMSGTRESH 10      /* set fdc error reporting treshold */
+#define FDFLUSH  11 /* flush buffers for media; either for verifying media, or for
+                       handling a media change without closing the file
+                      descriptor */
 
 #define FD_FILL_BYTE 0xF6 /* format fill byte */
 
index ebcdae4346f799fc06d7772430f871a3a5a43af5..24904ac64dc09c40cdbc7e4f433e9a1d0915bb6e 100644 (file)
@@ -109,7 +109,7 @@ extern unsigned long inode_init(unsigned long start, unsigned long end);
  *
  * Exception: MS_RDONLY is always applied to the entire file system.
  */
-#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY))
 #define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID)
 #define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
 #define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
@@ -260,6 +260,7 @@ struct file_operations {
        int (*mmap) (void);
        int (*open) (struct inode *, struct file *);
        void (*release) (struct inode *, struct file *);
+       int (*fsync) (struct inode *, struct file *);
 };
 
 struct inode_operations {
@@ -296,8 +297,17 @@ struct file_system_type {
        int requires_dev;
 };
 
-extern struct file_operations * chrdev_fops[MAX_CHRDEV];
-extern struct file_operations * blkdev_fops[MAX_BLKDEV];
+extern int register_blkdev(unsigned int, const char *, struct file_operations *);
+extern int blkdev_open(struct inode * inode, struct file * filp);
+extern struct file_operations def_blk_fops;
+extern struct inode_operations blkdev_inode_operations;
+
+extern int register_chrdev(unsigned int, const char *, struct file_operations *);
+extern int chrdev_open(struct inode * inode, struct file * filp);
+extern struct file_operations def_chr_fops;
+extern struct inode_operations chrdev_inode_operations;
+
+extern struct inode_operations fifo_inode_operations;
 
 extern struct file_system_type *get_fs_type(char *name);
 
index e3a08357ce677f0bc1e91e0999e194aaf659f109..460dd72c66dba78eccdf2e29ea150acaf33399d5 100644 (file)
@@ -217,7 +217,7 @@ struct task_struct {
 
 /*
  *  INIT_TASK is used to set up the first task table, touch at
- * your own risk!. Base=0, limit=0x9ffff (=640kB)
+ * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
 #define INIT_TASK \
 /* state etc */        { 0,15,15, \
@@ -244,8 +244,8 @@ struct task_struct {
 /* cloe */     {{ 0, }}, \
                { \
                        {0,0}, \
-/* ldt */              {0x9f,0xc0c0fa00}, \
-                       {0x9f,0xc0c0f200}, \
+/* ldt */              {0x1ff,0xc0c0fa00}, \
+                       {0x1ff,0xc0c0f200}, \
                }, \
 /*tss*/        {0,sizeof(init_kernel_stack) + (long) &init_kernel_stack, \
         0x10,0,0,0,0,(long) &swapper_pg_dir,\
index 55066a4ff13662012e1e1532c1fbb14a7bcce02e..767c34797d9c558856cdb192524c975df4ee3595 100644 (file)
@@ -138,6 +138,7 @@ extern int get_tty_queue(struct tty_queue * queue);
 #define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
 #define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
 #define SUSPEND_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
+#define LNEXT_CHAR(tty)        ((tty)->termios->c_cc[VLNEXT])
 
 #define _L_FLAG(tty,f) ((tty)->termios->c_lflag & f)
 #define _I_FLAG(tty,f) ((tty)->termios->c_iflag & f)
@@ -188,7 +189,7 @@ struct tty_struct {
        struct termios *termios;
        int pgrp;
        int session;
-       unsigned char stopped:1, status_changed:1, packet:1;
+       unsigned char stopped:1, status_changed:1, packet:1, lnext:1;
        unsigned char ctrl_status;
        short line;
        int disc;
index 803ab09bdce38d58c06b283f53f888582f2a3300..f8ac1afcfca16a0dc82e9ec5a32a0baf286f62dd 100644 (file)
@@ -220,8 +220,13 @@ void start_kernel(void)
        if (memory_end > 16*1024*1024)
                memory_end = 16*1024*1024;
 #endif
-       memory_start = 1024*1024;
-       low_memory_start = (unsigned long) &end;
+       if ((unsigned long)&end >= (1024*1024)) {
+               memory_start = (unsigned long) &end;
+               low_memory_start = 4096;
+       } else {
+               memory_start = 1024*1024;
+               low_memory_start = (unsigned long) &end;
+       }
        low_memory_start += 0xfff;
        low_memory_start &= 0xfffff000;
        memory_start = paging_init(memory_start,memory_end);
@@ -260,11 +265,14 @@ void start_kernel(void)
         */
        if (hard_math) {
                unsigned short control_word;
+
+               printk("Checking for 387 error mechanism ...");
                __asm__("fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
                control_word &= 0xffc0;
                __asm__("fldcw %0 ; fwait"::"m" (*&control_word));
                outb_p(inb_p(0x21) | (1 << 2), 0x21);
                __asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
+               printk(" ok, using %s.\n",ignore_irq13?"exception 16":"irq13");
        }
        move_to_user_mode();
        if (!fork())            /* we count on this going ok */
index 8ae26fbf2d235e9634ae2c04cc7cd18be69a0b1c..2a1e34ced9fcae7400ea2cf75a09948d72ac6e77 100644 (file)
@@ -37,7 +37,7 @@ math.a: $(OBJS)
        sync
 
 clean:
-       rm -f core *.o *.a *.s *~
+       rm -f core *.o *.a *.s
 
 dep:
        $(CPP) -M *.c *.S > .depend
index 0def16732ef279af2d86631db2bdf54e41cec224..27e80c56215b1506ebf8f0127e778cc52d70ec29 100644 (file)
@@ -79,8 +79,10 @@ static void single_arg_error(void)
          /* Convert to a QNaN */
          FPU_st0_ptr->sigh |= 0x40000000;
        }
+      break;              /* return with a NaN in st(0) */
     case TW_Empty:
-      stack_underflow();
+      stack_underflow();  /* Puts a QNaN in st(0) */
+      break;
 #ifdef PARANOID
     default:
       EXCEPTION(EX_INTERNAL|0x0112);
index 6167fe615b6fa49451bebe2eee6bf4bfdde54ee4..e1e22835d9ed4878e90c29b62b36f1b855485b8c 100644 (file)
@@ -17,7 +17,8 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
-
+#include "control_w.h"
+#include "fpu_system.h"
 
 
 void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
@@ -41,28 +42,55 @@ void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
        {
          diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
          if (!diff)
-           diff = a->sigl > b->sigl;
+           {
+             diff = a->sigl > b->sigl;
+             if (!diff)
+               diff = -(a->sigl < b->sigl);
+           }
        }
       
       if (diff > 0)
        {
          reg_u_sub(a, b, dest);
          dest->sign = a->sign;
-         return;
+       }
+      else if ( diff == 0 )
+       {
+         reg_move(&CONST_Z, dest);
+         /* sign depends upon rounding mode */
+         dest->sign = ((control_word & CW_RC) != RC_DOWN)
+           ? SIGN_POS : SIGN_NEG;
        }
       else
        {
          reg_u_sub(b, a, dest);
          dest->sign = b->sign;
-         return;
        }
+      return;
     }
   else
     {
       if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
        { real_2op_NaN(a, b, dest); return; }
       else if (a->tag == TW_Zero)
-       { reg_move(b, dest); return; }
+       {
+         if (b->tag == TW_Zero)
+           {
+             char different_signs = a->sign ^ b->sign;
+             /* Both are zero, result will be zero. */
+             reg_move(a, dest);
+             if (different_signs)
+               {
+                 /* Signs are different. */
+                 /* Sign of answer depends upon rounding mode. */
+                 dest->sign = ((control_word & CW_RC) != RC_DOWN)
+                   ? SIGN_POS : SIGN_NEG;
+               }
+           }
+         else
+           reg_move(b, dest);
+         return;
+       }
       else if (b->tag == TW_Zero)
        { reg_move(a, dest); return; }
       else if (a->tag == TW_Infinity)
@@ -97,7 +125,11 @@ void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
        {
          diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
          if (!diff)
-           diff = a->sigl > b->sigl;
+           {
+             diff = a->sigl > b->sigl;
+             if (!diff)
+               diff = -(a->sigl < b->sigl);
+           }
        }
       
       switch (a->sign*2 + b->sign)
@@ -109,6 +141,13 @@ void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
              reg_u_sub(a, b, dest);
              dest->sign = a->sign;
            }
+         else if ( diff == 0 )
+           {
+             reg_move(&CONST_Z, dest);
+             /* sign depends upon rounding mode */
+             dest->sign = ((control_word & CW_RC) != RC_DOWN)
+               ? SIGN_POS : SIGN_NEG;
+           }
          else
            {
              reg_u_sub(b, a, dest);
@@ -130,7 +169,23 @@ void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
       if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
        { real_2op_NaN(a, b, dest); return; }
       else if (b->tag == TW_Zero)
-       { reg_move(a, dest); return; }
+       { 
+         if (a->tag == TW_Zero)
+           {
+             char same_signs = !(a->sign ^ b->sign);
+             /* Both are zero, result will be zero. */
+             reg_move(a, dest); /* Answer for different signs. */
+             if (same_signs)
+               {
+                 /* Sign depends upon rounding mode */
+                 dest->sign = ((control_word & CW_RC) != RC_DOWN)
+                   ? SIGN_POS : SIGN_NEG;
+               }
+           }
+         else
+           reg_move(a, dest);
+         return;
+       }
       else if (a->tag == TW_Zero)
        {
          reg_move(b, dest);
index cccf3282a029fb6eb70f9e0a7dfa310bde97be55..26c52df7a92a6c9cb8969b066852fd591af829d1 100644 (file)
@@ -8,5 +8,5 @@
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
-#define FPU_VERSION "wm-FPU-emu version BETA 1.0"
+#define FPU_VERSION "wm-FPU-emu version BETA 1.1"
 
index dbd9718b0721fc77277dab77cc32783ca0a44c09..1fb05b829aba15c076affaaa4fa887425fecf87f 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef _BLK_H
 #define _BLK_H
 
-#define NR_BLK_DEV     12
+#include <linux/fs.h>
+
 /*
  * NR_REQUEST is the number of entries in the request-queue.
  * NOTE that writes may use only the low 2/3 of these: reads
@@ -62,12 +63,12 @@ struct sec_size {
 #define SECTOR_MASK ((1 << (BLOCK_SIZE_BITS - 9)) -1)
 #define SUBSECTOR(block) ((block) & SECTOR_MASK)
 
-extern struct sec_size * blk_sec[NR_BLK_DEV];
-extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
+extern struct sec_size * blk_sec[MAX_BLKDEV];
+extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
 extern struct request request[NR_REQUEST];
 extern struct wait_queue * wait_for_request;
 
-extern int * blk_size[NR_BLK_DEV];
+extern int * blk_size[MAX_BLKDEV];
 
 extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
 extern int is_read_only(int dev);
index e8dd20fe8d9e938e35b2f33d1c1babcbe43a1f30..382b837b8ea0289568ae060bf1ad78a3a3921766 100644 (file)
@@ -1091,6 +1091,14 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        format_status = FORMAT_NONE;
                        wake_up(&format_done);
                        return okay ? 0 : -EIO;
+               case FDFLUSH:
+                       if (!permission(inode, 2))
+                               return -EPERM;
+                       cli();
+                       fake_change |= 1 << (drive & 3);
+                       sti();
+                       check_disk_change(inode->i_rdev);
+                       return 0;
        }
        if (!suser())
                return -EPERM;
@@ -1140,7 +1148,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 }
 
 #define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
+outb_p(addr,0x70); \
 inb_p(0x71); \
 })
 
@@ -1258,9 +1266,12 @@ static struct sigaction floppy_sigaction = {
 void floppy_init(void)
 {
        outb(current_DOR,FD_DOR);
+       if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+               printk("Unable to get major %d for floppy\n",MAJOR_NR);
+               return;
+       }
        blk_size[MAJOR_NR] = floppy_sizes;
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       blkdev_fops[MAJOR_NR] = &floppy_fops;
        timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
        timer_active &= ~(1 << FLOPPY_TIMER);
        config_types();
index fa0cac7ec074089c5802c5c910abff5f8b79b4e8..632eae8841fcf3754092f158b5c298d41854f761 100644 (file)
@@ -43,7 +43,7 @@ static int revalidate_hddisk(int, int);
 
 static inline unsigned char CMOS_READ(unsigned char addr)
 {
-       outb_p(0x80|addr,0x70);
+       outb_p(addr,0x70);
        return inb_p(0x71);
 }
 
@@ -684,8 +684,11 @@ static struct file_operations hd_fops = {
 
 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
 {
+       if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+               printk("Unable to get major %d for harddisk\n",MAJOR_NR);
+               return mem_start;
+       }
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       blkdev_fops[MAJOR_NR] = &hd_fops;
        read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
        hd_gendisk.next = gendisk_head;
        gendisk_head = &hd_gendisk;
index 51759d2dceb3ad8d631f815ac61c9dae7ce03668..99d09bedc7fabb48e1216f16587855aa2a07c95e 100644 (file)
@@ -31,13 +31,13 @@ struct wait_queue * wait_for_request = NULL;
 
 /* This specifies how many sectors to read ahead on the disk.  */
 
-int read_ahead[NR_BLK_DEV] = {0, };
+int read_ahead[MAX_BLKDEV] = {0, };
 
 /* blk_dev_struct is:
  *     do_request-address
  *     next-request
  */
-struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
+struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
        { NULL, NULL },         /* no_dev */
        { NULL, NULL },         /* dev mem */
        { NULL, NULL },         /* dev fd */
@@ -57,11 +57,11 @@ struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
  *
  * if (!blk_size[MAJOR]) then no minor size checking is done.
  */
-int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
+int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
 
 /* RO fail safe mechanism */
 
-static long ro_bits[NR_BLK_DEV][8];
+static long ro_bits[MAX_BLKDEV][8];
 
 int is_read_only(int dev)
 {
@@ -69,7 +69,7 @@ int is_read_only(int dev)
 
        major = MAJOR(dev);
        minor = MINOR(dev);
-       if (major < 0 || major >= NR_BLK_DEV) return 0;
+       if (major < 0 || major >= MAX_BLKDEV) return 0;
        return ro_bits[major][minor >> 5] & (1 << (minor & 31));
 }
 
@@ -79,7 +79,7 @@ void set_device_ro(int dev,int flag)
 
        major = MAJOR(dev);
        minor = MINOR(dev);
-       if (major < 0 || major >= NR_BLK_DEV) return;
+       if (major < 0 || major >= MAX_BLKDEV) return;
        if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
        else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
 }
@@ -222,7 +222,7 @@ void ll_rw_page(int rw, int dev, int page, char * buffer)
        struct request * req;
        unsigned int major = MAJOR(dev);
 
-       if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
+       if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
                printk("Trying to read nonexistent block-device %04x (%d)\n",dev,page*8);
                return;
        }
@@ -289,7 +289,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
          }
        };
 
-       if ((major=MAJOR(bh[0]->b_dev)) >= NR_BLK_DEV ||
+       if ((major=MAJOR(bh[0]->b_dev)) >= MAX_BLKDEV ||
        !(blk_dev[major].request_fn)) {
                printk("ll_rw_block: Trying to read nonexistent block-device %04x (%d)\n",bh[0]->b_dev,bh[0]->b_blocknr);
                for (i=0;i<nr; i++)
@@ -332,7 +332,7 @@ void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
        struct request * req;
        unsigned int major = MAJOR(dev);
 
-       if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
+       if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
                printk("ll_rw_swap_file: trying to swap nonexistent block-device\n\r");
                return;
        }
index 3bdcf5dd1c26e85b19fe80c652db79f8055447a8..a1518278d670e282acceae5fd1def4abd5a7064f 100644 (file)
@@ -67,8 +67,11 @@ long rd_init(long mem_start, int length)
        int     i;
        char    *cp;
 
+       if (register_blkdev(MAJOR_NR,"rd",&rd_fops)) {
+               printk("Unable to get major %d for ramdisk\n",MAJOR_NR);
+               return 0;
+       }
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       blkdev_fops[MAJOR_NR] = &rd_fops;
        rd_start = (char *) mem_start;
        rd_length = length;
        cp = rd_start;
index 35d7b60a4cba89c0e37186804b2862ec7216d1d1..e9a74dbd4b6dcabb26a2d44b001cdd2b23b706f4 100644 (file)
@@ -1,6 +1,6 @@
 /* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
  * Created: Sun May  3 18:53:19 1992 by faith
- * Revised: Sun Jan 10 01:23:29 1993 by root
+ * Revised: Thu Feb 18 21:02:12 1993 by faith@cs.unc.edu
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993 Rickard E. Faith
  *
 #include <asm/system.h>
 #include <linux/errno.h>
 
-#define VERSION          "3.3" /* Change with each revision */
+#define VERSION          "3.5" /* Change with each revision */
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -169,7 +169,6 @@ static int               this_host = 0;
 static int               can_queue = QUEUE;
 
 static volatile int      in_command = 0;
-static volatile int      in_interrupt_code = 0;
 static Scsi_Cmnd         *current_SC = NULL;
 
 enum { non_queueing   = 0x01,
@@ -646,7 +645,6 @@ void my_done( int error )
 {
    if (in_command) {
       in_command = 0;
-      in_interrupt_code = 0;
       outb( 0x00, Interrupt_Cntl_port );
       fdomain_make_bus_idle();
       current_SC->result = error;
@@ -664,14 +662,14 @@ void fdomain_16x0_intr( int unused )
    unsigned data_count;
 
    sti();
-
-   if (in_interrupt_code)
-        panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
-   else
-        ++in_interrupt_code;
    
    outb( 0x00, Interrupt_Cntl_port );
 
+   /* We usually have one spurious interrupt after each command.  Ignore it. */
+   if (!in_command || !current_SC) {   /* Spurious interrupt */
+      return;
+   }
+
    if (current_SC->SCp.phase & aborted) {
 #if EVERY_ACCESS
       if (current_SC->SCp.phase & (in_other || disconnect))
@@ -693,12 +691,6 @@ void fdomain_16x0_intr( int unused )
       return;
    }
 
-   /* We usually have one spurious interrupt after each command.  Ignore it. */
-   if (!in_command) {          /* Spurious interrupt */
-      in_interrupt_code = 0;
-      return;
-   }
-
 #if RESELECTION
    if (current_SC->SCp.phase & disconnect) {
       printk( " RECON %x ", inb( SCSI_Data_NoACK_port ) );
@@ -735,7 +727,6 @@ void fdomain_16x0_intr( int unused )
       /* Stop arbitration (also set FIFO for output and enable parity) */
       outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 
-      in_interrupt_code = 0;
       return;
    } else if (current_SC->SCp.phase & in_selection) {
       status = inb( SCSI_Status_port );
@@ -756,7 +747,6 @@ void fdomain_16x0_intr( int unused )
        }
       }
       current_SC->SCp.phase = in_other;
-      in_interrupt_code = 0;
       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 #if RESELECTION
       outb( 0x88, SCSI_Cntl_port );
@@ -979,7 +969,6 @@ void fdomain_16x0_intr( int unused )
 #endif
       
    } else {
-      in_interrupt_code = 0;
       if (current_SC->SCp.phase & disconnect) {
         outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
         outb( 0x00, SCSI_Cntl_port );
@@ -1239,9 +1228,8 @@ int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
 #endif
 
 #if DEBUG_ABORT
-   printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+   printk( "Phase = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
     current_SC->SCp.phase,
-    in_interrupt_code,
     current_SC->target,
     *(unsigned char *)current_SC->cmnd,
     current_SC->use_sg,
index ca3c935a3092583a217fe40c747b13dbc23e49dd..1481795c1a7523bc5296f516d2e6cab10a95cbd3 100644 (file)
@@ -761,7 +761,10 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
 {
        int i;
 
-       blkdev_fops[MAJOR_NR] = &sd_fops; /* to get sd_open in table */
+       if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) {
+               printk("Unable to get major %d for SCSI disk\n",MAJOR_NR);
+               return memory_start;
+       }
        if (MAX_SD == 0) return memory_start;
 
        sd_sizes = (int *) memory_start;
index 63a750901c66f73d67e7da49bd3eefff1583a1c2..5b483fcfa230261570d91995a4783e37d6cb74f4 100644 (file)
@@ -601,7 +601,10 @@ unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
 {
        int i;
 
-       blkdev_fops[MAJOR_NR] = &sr_fops; 
+       if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) {
+               printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
+               return memory_start;
+       }
        if(MAX_SR == 0) return memory_start;
 
        sr_sizes = (int *) memory_start;
index 703c75c81f7f7ecab5afe44725143304f49d2e03..ec8f77d39cc648bd03ab5b9dd280e9065f7bf9be 100644 (file)
@@ -1224,7 +1224,10 @@ unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
 {
   int i;
 
-  chrdev_fops[MAJOR_NR] = &st_fops;
+  if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
+    printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
+    return mem_start;
+  }
   if (NR_ST == 0) return mem_start;
 
 #ifdef DEBUG
index 704fc82666d0f4920d28b7f44d069feec380b998..db402ad89e213c3433344048c2e5bb1d148b115a 100644 (file)
@@ -506,24 +506,7 @@ void wd7000_revision(void)
 }
 
 
-static const char *wd_bases[] = {
-                                (char *)0xde000,
-                                (char *)0xdc000,
-                                (char *)0xda000,
-                                (char *)0xd8000,
-                                (char *)0xd6000,
-                                (char *)0xd4000,
-                                (char *)0xd2000,
-                                (char *)0xd0000,
-                                (char *)0xce000,
-                                (char *)0xcc000,
-                                (char *)0xca000,
-                                (char *)0xc8000,
-                                (char *)0xc6000,
-                                (char *)0xc4000,
-                                (char *)0xc2000,
-                                (char *)0xc0000
-                               };
+static const char *wd_bases[] = {(char *)0xce000};
 typedef struct {
     char * signature;
     unsigned offset;
index cfd4a519ab08f85780bc8ddd9511271f64679b86..c722e84e77337cab4af0ee8cc0af9d2a19cbe578 100644 (file)
@@ -226,8 +226,8 @@ static char * translations[] = {
        "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
        "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
        "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
-/* IBM grapgics: minimal translations (CR, LF, LL and ESC) */
-       "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
+/* IBM grapgics: minimal translations (CR, LF, LL, SO, SI and ESC) */
+       "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\000\000"
        "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
        "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
        "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
index c44e57b022609a61bc9537987682584c94f904f3..803491f8360e51f855a38f46eb7b728903e187e2 100644 (file)
@@ -154,7 +154,7 @@ static void put_queue(int ch)
        struct tty_queue *qp;
        unsigned long new_head;
 
-       wake_up_interruptible(&keypress_wait);
+       wake_up(&keypress_wait);
        if (!tty)
                return;
        qp = &tty->read_q;
index 2faccb75432bff91abdc83bb9798bc1e55be9cce..f7bcf210fa0c84cd6bcd28bfe1722999bd9aa0f9 100644 (file)
@@ -233,7 +233,8 @@ long lp_init(long kmem_start)
        unsigned int testvalue = 0;
        int count = 0;
 
-       chrdev_fops[6] = &lp_fops;
+       if (register_chrdev(6,"lp",&lp_fops))
+               printk("unable to get major 6 for line printer\n");
        /* take on all known port values */
        for (offset = 0; offset < LP_NO; offset++) {
                /* write to port & read back to check */
index 967efe0ee165262df50844bd0fa9edde774bee09..186e83002c702588e8d991a9fd8145acfa761258 100644 (file)
@@ -336,7 +336,8 @@ static struct file_operations memory_fops = {
 
 long chr_dev_init(long mem_start, long mem_end)
 {
-       chrdev_fops[1] = &memory_fops;
+       if (register_chrdev(1,"mem",&memory_fops))
+               printk("unable to get major 1 for memory devs\n");
        mem_start = tty_init(mem_start);
        mem_start = lp_init(mem_start);
        mem_start = mouse_init(mem_start);
index a67c56710c3d84a872ec1d4c6007bb1b1ec37f70..9a03f09e76614667f9a077efe261b2ae5cbc443d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/mouse.h>
 #include <linux/config.h>
+#include <linux/kernel.h>
 
 /*
  * note that you can remove any or all of the drivers by undefining
@@ -90,6 +91,7 @@ unsigned long mouse_init(unsigned long kmem_start)
 #ifdef CONFIG_ATIXL_BUSMOUSE
        kmem_start = atixl_busmouse_init(kmem_start);
 #endif
-       chrdev_fops[10] = &mouse_fops;
+       if (register_chrdev(10,"mouse",&mouse_fops))
+               printk("unable to get major 10 for mouse devices\n");
        return kmem_start;
 }
index 7da8ca6aebc5483ff6f2b6014e91ccbb652a48e2..c6af7c636f9d81a6b33112d5b4200b0414e05780 100644 (file)
@@ -524,7 +524,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        if (info->blocked_open) {
                shutdown(info);
                startup(info);
-               wake_up_interruptible(&info->open_wait);
                return;
        }
        if (info->flags & ASYNC_INITIALIZED) {
@@ -737,7 +736,8 @@ static int set_serial_info(struct async_struct * info,
        }
        
        info->baud_base = new.baud_base;
-       info->flags = new.flags & ASYNC_FLAGS;
+       info->flags = ((info->flags & ~ASYNC_FLAGS) |
+                       (new.flags & ASYNC_FLAGS));
        info->custom_divisor = new.custom_divisor;
        info->type = new.type;
        
@@ -1275,7 +1275,7 @@ long rs_init(long kmem_start)
                init(info);
                if (info->type == PORT_UNKNOWN)
                        continue;
-               printk("ttyS%d%s at 0x%04x (irq = %d)", info->line, 
+               printk("tty%02d%s at 0x%04x (irq = %d)", info->line, 
                       (info->flags & ASYNC_FOURPORT) ? " FourPort" : "",
                       info->port, info->irq);
                switch (info->type) {
index 4a919258420fa5e193895a0d992bacf99131e838..ed8f18face2cb083ec5fd2e575348d21839f4e6b 100644 (file)
@@ -213,6 +213,7 @@ static struct file_operations hung_up_tty_fops = {
 void tty_hangup(struct tty_struct * tty)
 {
        struct file * filp;
+       struct task_struct **p;
        int dev;
 
        if (!tty)
@@ -233,6 +234,12 @@ void tty_hangup(struct tty_struct * tty)
        wake_up_interruptible(&tty->write_q.proc_list);
        if (tty->session > 0)
                kill_sl(tty->session,SIGHUP,1);
+       tty->session = 0;
+       tty->pgrp = -1;
+       for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
+               if ((*p) && (*p)->tty == tty->line)
+                       (*p)->tty = -1;
+       }
 }
 
 void tty_unhangup(struct file *filp)
@@ -463,9 +470,10 @@ void copy_to_cooked(struct tty_struct * tty)
                        c=13;
                if (I_UCLC(tty))
                        c=tolower(c);
-               if (L_CANON(tty)) {
-                       if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==KILL_CHAR(tty))) {
+               if (c == __DISABLED_CHAR)
+                       tty->lnext = 1;
+               if (L_CANON(tty) && !tty->lnext) {
+                       if (c == KILL_CHAR(tty)) {
                                /* deal with killing the input line */
                                while(!(EMPTY(&tty->secondary) ||
                                        (c=LAST(&tty->secondary))==10 ||
@@ -485,8 +493,7 @@ void copy_to_cooked(struct tty_struct * tty)
                                }
                                continue;
                        }
-                       if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==ERASE_CHAR(tty))) {
+                       if (c == ERASE_CHAR(tty)) {
                                if (EMPTY(&tty->secondary) ||
                                   (c=LAST(&tty->secondary))==10 ||
                                   ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
@@ -505,39 +512,42 @@ void copy_to_cooked(struct tty_struct * tty)
                                DEC(tty->secondary.head);
                                continue;
                        }
+                       if (c == LNEXT_CHAR(tty)) {
+                               tty->lnext = 1;
+                               if (L_ECHO(tty)) {
+                                       put_tty_queue('^',&tty->write_q);
+                                       put_tty_queue(8,&tty->write_q);
+                               }
+                               continue;
+                       }
                }
-               if (I_IXON(tty)) {
-                       if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==STOP_CHAR(tty))) {
+               if (I_IXON(tty) && !tty->lnext) {
+                       if (c == STOP_CHAR(tty)) {
                                tty->status_changed = 1;
                                tty->ctrl_status |= TIOCPKT_STOP;
                                tty->stopped=1;
                                continue;
                        }
                        if (((I_IXANY(tty)) && tty->stopped) ||
-                           ((START_CHAR(tty) != __DISABLED_CHAR) &&
-                            (c==START_CHAR(tty)))) {
+                           (c == START_CHAR(tty))) {
                                tty->status_changed = 1;
                                tty->ctrl_status |= TIOCPKT_START;
                                tty->stopped=0;
                                continue;
                        }
                }
-               if (L_ISIG(tty)) {
-                       if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==INTR_CHAR(tty))) {
+               if (L_ISIG(tty) && !tty->lnext) {
+                       if (c == INTR_CHAR(tty)) {
                                kill_pg(tty->pgrp, SIGINT, 1);
                                flush_input(tty);
                                continue;
                        }
-                       if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==QUIT_CHAR(tty))) {
+                       if (c == QUIT_CHAR(tty)) {
                                kill_pg(tty->pgrp, SIGQUIT, 1);
                                flush_input(tty);
                                continue;
                        }
-                       if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
-                           (c==SUSPEND_CHAR(tty))) {
+                       if (c == SUSPEND_CHAR(tty)) {
                                if (!is_orphaned_pgrp(tty->pgrp))
                                        kill_pg(tty->pgrp, SIGTSTP, 1);
                                continue;
@@ -553,9 +563,15 @@ void copy_to_cooked(struct tty_struct * tty)
                        if (c<32 && L_ECHOCTL(tty)) {
                                put_tty_queue('^',&tty->write_q);
                                put_tty_queue(c+64, &tty->write_q);
+                               if (EOF_CHAR(tty) != __DISABLED_CHAR &&
+                                   c==EOF_CHAR(tty) && !tty->lnext) {
+                                       put_tty_queue(8,&tty->write_q);
+                                       put_tty_queue(8,&tty->write_q);
+                               }
                        } else
                                put_tty_queue(c, &tty->write_q);
                }
+               tty->lnext = 0;
                put_tty_queue(c, &tty->secondary);
        }
        TTY_WRITE_FLUSH(tty);
@@ -644,6 +660,10 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
        }
        add_wait_queue(&tty->secondary.proc_list, &wait);
        while (nr>0) {
+               if (hung_up(file)) {
+                       file->f_flags &= ~O_NONBLOCK;
+                       break;  /* force read() to return 0 */
+               }
                TTY_READ_FLUSH(tty);
                if (tty->link)
                        TTY_WRITE_FLUSH(tty->link);
@@ -680,8 +700,6 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
                        TTY_WRITE_FLUSH(tty->link);
                if (!EMPTY(&tty->secondary))
                        continue;
-               if (hung_up(file))
-                       break;
                current->state = TASK_INTERRUPTIBLE;
                if (EMPTY(&tty->secondary))
                        schedule();
@@ -819,7 +837,8 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
        tty = TTY_TABLE(dev);
        if (!tty || (tty->flags & (1 << TTY_IO_ERROR)))
                return -EIO;
-       if (MINOR(inode->i_rdev) && (tty->pgrp > 0) &&
+       if ((inode->i_rdev != 0x0400) && /* don't stop on /dev/console */
+           (tty->pgrp > 0) &&
            (current->tty == dev) &&
            (tty->pgrp != current->pgrp))
                if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
@@ -1391,9 +1410,10 @@ long tty_init(long kmem_start)
 
        if (sizeof(struct tty_struct) > 4096)
                panic("size of tty structure > 4096!");
-       
-       chrdev_fops[4] = &tty_fops;
-       chrdev_fops[5] = &tty_fops;
+       if (register_chrdev(4,"tty",&tty_fops))
+               panic("unable to get major 4 for tty device");
+       if (register_chrdev(5,"tty",&tty_fops))
+               panic("unable to get major 5 for tty device");
        for (i=0 ; i< MAX_TTYS ; i++) {
                tty_table[i] =  0;
                tty_termios[i] = 0;
index bde475bb0a0ecd410a32076e39a8820d15e6dfa9..c9b973a6f3d27ca8db5a950c49a0b0b42139f822 100644 (file)
@@ -917,6 +917,7 @@ void mem_init(unsigned long start_low_mem,
        int datapages = 0;
        unsigned long tmp;
        unsigned short * p;
+       extern int etext;
 
        cli();
        end_mem &= 0xfffff000;
@@ -946,10 +947,10 @@ void mem_init(unsigned long start_low_mem,
        nr_free_pages = 0;
        for (tmp = 0 ; tmp < end_mem ; tmp += 4096) {
                if (mem_map[MAP_NR(tmp)]) {
-                       if (tmp < 0xA0000)
-                               codepages++;
-                       else if (tmp < 0x100000)
+                       if (tmp >= 0xA0000 && tmp < 0x100000)
                                reservedpages++;
+                       else if (tmp < (unsigned long) &etext)
+                               codepages++;
                        else
                                datapages++;
                        continue;
@@ -959,7 +960,7 @@ void mem_init(unsigned long start_low_mem,
                nr_free_pages++;
        }
        tmp = nr_free_pages << PAGE_SHIFT;
-       printk("Memory: %dk/%dk available (%dk kernel, %dk reserved, %dk data)\n",
+       printk("Memory: %dk/%dk available (%dk kernel code, %dk reserved, %dk data)\n",
                tmp >> 10,
                end_mem >> 10,
                codepages << 2,
index 438cfd624e2bb2317f31d454823ed0d304ad3fd1..90ce81f67f2d5b818222e4b2eeb51da5cc7af056 100644 (file)
@@ -481,6 +481,8 @@ dev_tint( struct device *dev)
          sti();
          /* this will send it through the process again. */
          dev->queue_xmit (skb, dev, -i-1);
+         if (dev->tbusy)
+               return;
        }
     }
 }
index e83b865420a22460a0157254fad586a480b93e44..584765ab88d1fe672452d8feaff86e864691505a 100644 (file)
@@ -834,7 +834,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        PRINTK(("\nIP: *** datagram routing not yet implemented ***\n"));
        PRINTK(("    SRC = %s   ", in_ntoa(iph->saddr)));
        PRINTK(("    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
-        icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
+/*      icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev); */
 
        skb->sk = NULL;
        kfree_skb(skb, 0);
index 8dd7ccf1affc1b11d0e5b23be1e6e852533600f0..86ba0c3eca95e39383ac5c3f5c00c8536f432934 100644 (file)
@@ -29,6 +29,7 @@
 #include <unistd.h>    /* contains read/write */
 #include <fcntl.h>
 #include <linux/config.h>
+#include <linux/a.out.h>
 
 #define MINIX_HEADER 32
 #define GCC_HEADER 1024
@@ -83,8 +84,9 @@ void usage(void)
 
 int main(int argc, char ** argv)
 {
-       int i,c,id;
+       int i,c,id, sz;
        char buf[1024];
+       struct exec *ex = (struct exec *)buf;
        char major_root, minor_root;
        struct stat sb;
 
@@ -116,9 +118,9 @@ int main(int argc, char ** argv)
                die("Non-Minix header of 'boot'");
        if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
                die("Non-Minix header of 'boot'");
-       if (((long *) buf)[3]!=0)
+       if (((long *) buf)[3] != 0)
                die("Illegal data segment in 'boot'");
-       if (((long *) buf)[4]!=0)
+       if (((long *) buf)[4] != 0)
                die("Illegal bss in 'boot'");
        if (((long *) buf)[5] != 0)
                die("Non-Minix header of 'boot'");
@@ -145,9 +147,9 @@ int main(int argc, char ** argv)
                die("Non-Minix header of 'setup'");
        if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
                die("Non-Minix header of 'setup'");
-       if (((long *) buf)[3]!=0)
+       if (((long *) buf)[3] != 0)
                die("Illegal data segment in 'setup'");
-       if (((long *) buf)[4]!=0)
+       if (((long *) buf)[4] != 0)
                die("Illegal bss in 'setup'");
        if (((long *) buf)[5] != 0)
                die("Non-Minix header of 'setup'");
@@ -156,6 +158,8 @@ int main(int argc, char ** argv)
        for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
                if (write(1,buf,c)!=c)
                        die("Write call failed");
+       if (c != 0)
+               die("read-error on 'setup'");
        close (id);
        if (i > SETUP_SECTS*512)
                die("Setup exceeds " STRINGIFY(SETUP_SECTS)
@@ -176,14 +180,28 @@ int main(int argc, char ** argv)
                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)
+       if (N_MAGIC(*ex) != ZMAGIC)
                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);
-       if (i > SYS_SIZE*16)
+       sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
+       fprintf(stderr,"System is %d bytes.\n", sz);
+       if (sz > SYS_SIZE*16)
                die("System is too big");
+       while (sz > 0) {
+               int l, n;
+
+               l = sz;
+               if (l > sizeof(buf))
+                       l = sizeof(buf);
+               if ((n=read(id, buf, l)) != l) {
+                       if (n == -1) 
+                               perror(argv[1]);
+                       else
+                               fprintf(stderr, "Unexpected EOF\n");
+                       die("Can't read 'system'");
+               }
+               write(1, buf, l);
+               sz -= l;
+       }
+       close(id);
        return(0);
 }
diff --git a/zBoot/Makefile b/zBoot/Makefile
new file mode 100644 (file)
index 0000000..35081f8
--- /dev/null
@@ -0,0 +1,36 @@
+
+HEAD = head.o
+SYSTEM = ../tools/zSystem
+#LD = gcc
+#TEST = -DTEST_DRIVER
+
+zOBJECTS = $(HEAD) inflate.o unzip.o misc.o
+
+CFLAGS = -O6 -DSTDC_HEADERS $(TEST)
+
+.c.s:
+       $(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+       $(AS) -c -o $*.o $<
+.c.o:
+       $(CC) $(CFLAGS) -c -o $*.o $<
+
+
+all:   zSystem
+
+zSystem:       piggy.o $(zOBJECTS)
+               $(LD) $(LDFLAGS) -o zSystem $(zOBJECTS) piggy.o
+
+head.o:        head.s
+
+head.s: head.S ../include/linux/tasks.h
+       $(CPP) -traditional head.S -o head.s
+
+piggy.s:       $(SYSTEM) xtract piggyback
+               ./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.s
+
+$(SYSTEM):
+               cd ..;make tools/zSystem
+
+clean:
+       -rm -f *.o *.s zSystem core piggy.* xtract piggyback
diff --git a/zBoot/crypt.h b/zBoot/crypt.h
new file mode 100644 (file)
index 0000000..f4aac50
--- /dev/null
@@ -0,0 +1,12 @@
+/* crypt.h (dummy version) -- do not perform encrytion
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+#  undef CRYPT      /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN  12  /* length of encryption random header */
+
+#define zencode
+#define zdecode
diff --git a/zBoot/gzip.h b/zBoot/gzip.h
new file mode 100644 (file)
index 0000000..2f738b9
--- /dev/null
@@ -0,0 +1,284 @@
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if defined(__STDC__) || defined(PROTO)
+#  define OF(args)  args
+#else
+#  define OF(args)  ()
+#endif
+
+#ifdef __STDC__
+   typedef void *voidp;
+#else
+   typedef char *voidp;
+#endif
+
+/* I don't like nested includes, but the string functions are used too often */
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#  include <string.h>
+#  define memzero(s, n)     memset ((s), 0, (n))
+#else
+#  include <strings.h>
+#  define strchr            index 
+#  define strrchr           rindex
+#  define memcpy(d, s, n)   bcopy((s), (d), (n)) 
+#  define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 
+#  define memzero(s, n)     bzero((s), (n))
+#endif
+
+#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+#  include <memory.h>
+#endif
+
+#ifndef RETSIGTYPE
+#  define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+/* Return codes from gzip */
+#define OK      0
+#define ERROR   1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED     0
+#define COMPRESSED 1
+#define PACKED     2
+/* methods 3 to 7 reserved */
+#define DEFLATED   8
+extern int method;         /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlayed between
+ * the various modules:
+ * deflate:  prev+head   window      d_buf  l_buf  outbuf
+ * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
+ * inflate:              window             inbuf
+ * unpack:               window             inbuf
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef        INBUFSIZ
+#  define INBUFSIZ  0x8000  /* input buffer size */
+#endif
+#define INBUF_EXTRA  64     /* required by unlzw() */
+
+#ifndef        OUTBUFSIZ
+#  define OUTBUFSIZ  16384  /* output buffer size */
+#endif
+#define OUTBUF_EXTRA 2048   /* required by unlzw() */
+
+#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+
+#ifdef DYN_ALLOC
+#  define EXTERN(type, array)  extern type * near array
+#  define DECLARE(type, array, size)  type * near array
+#  define ALLOC(type, array, size) { \
+      array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
+      if (array == NULL) error("insufficient memory"); \
+   }
+#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+#  define EXTERN(type, array)  extern type array[]
+#  define DECLARE(type, array, size)  type array[size]
+#  define ALLOC(type, array, size)
+#  define FREE(array)
+#endif
+
+EXTERN(uch, inbuf);          /* input buffer */
+EXTERN(uch, outbuf);         /* output buffer */
+EXTERN(ush, d_buf);          /* buffer for distances, see trees.c */
+EXTERN(uch, window);         /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+#  define tab_prefix prev    /* hash link (see deflate.c) */
+#  define head (prev+WSIZE)  /* hash head (see deflate.c) */
+   EXTERN(ush, tab_prefix);  /* prefix code (see unlzw.c) */
+#else
+#  define tab_prefix0 prev
+#  define head tab_prefix1
+   EXTERN(ush, tab_prefix0); /* prefix for even codes */
+   EXTERN(ush, tab_prefix1); /* prefix for odd  codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr;  /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in;   /* number of input bytes */
+extern long bytes_out;  /* number of output bytes */
+extern long overhead;   /* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int  ifd;        /* input file descriptor */
+extern int  ofd;        /* output file descriptor */
+extern char ifname[];   /* input filename or "stdin" */
+extern char ofname[];   /* output filename or "stdout" */
+
+extern ulg time_stamp;  /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+extern int exit_code;   /* program exit code */
+
+typedef int file_t;     /* Do not use stdio */
+#define NO_FILE  (-1)   /* in memory compression */
+
+
+#define        GZIP_MAGIC     "\037\213" /* Magic header for gzip files, 1F 8B */
+#define        OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define        PKZIP_MAGIC  "PK\003\004" /* Magic header for pkzip files */
+#define        PACK_MAGIC     "\037\036" /* Magic header for packed files */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+/* internal file attribute */
+#define UNKNOWN (-1)
+#define BINARY  0
+#define ASCII   1
+
+#ifndef WSIZE
+#  define WSIZE 0x8000     /* window size--must be a power of two, and */
+#endif                     /*  at least 32K for zip's deflate method */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt;        /* flag to turn on decryption */
+extern int save_orig_name; /* set if original name must be saved */
+extern int verbose;        /* be verbose (-v) */
+extern int level;          /* compression level */
+extern int test;           /* check .z file integrity */
+extern int to_stdout;      /* output to stdout (-c) */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* put_byte is used for the compressed output, put_char for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_char.
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+   flush_outbuf();}
+#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+   flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+    outbuf[outcnt++] = (uch) ((w) & 0xff); \
+    outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+  } else { \
+    put_byte((uch)((w) & 0xff)); \
+    put_byte((uch)((ush)(w) >> 8)); \
+  } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+    put_short((n) & 0xffff); \
+    put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable()    0  /* force sequential output */
+#define translate_eol 0  /* no option -a yet */
+
+#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    /* force to lower case */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+       /* in zip.c: */
+extern void zip    OF((int in, int out));
+extern int file_read  OF((char *buf,  unsigned size));
+
+       /* in unzip.c */
+extern void unzip        OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+       /* in unpack.c */
+extern void unpack        OF((int in, int out));
+
+       /* in gzip.c */
+RETSIGTYPE abort_gzip   OF((void));
+
+        /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg  deflate OF((void));
+
+        /* in trees.c */
+void ct_init     OF((ush *attr, int *method));
+int  ct_tally    OF((int dist, int lc));
+ulg  flush_block OF((char *buf, ulg stored_len, int eof));
+
+        /* in bits.c */
+void     bi_init    OF((file_t zipfile));
+void     send_bits  OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void     bi_windup  OF((void));
+void     copy_block OF((char *buf, unsigned len, int header));
+extern   int (*read_buf) OF((char *buf, unsigned size));
+
+       /* in util.c: */
+extern ulg  updcrc        OF((uch *s, unsigned n));
+extern void clear_bufs    OF((void));
+extern int  fill_inbuf    OF((void));
+extern void flush_outbuf  OF((void));
+extern void flush_window  OF((void));
+extern char *strlwr       OF((char *s));
+extern char *basename     OF((char *fname));
+extern char *add_envopt   OF((int *argcp, char ***argvp, char *env));
+extern void error         OF((char *m));
+extern void warn          OF((char *a, char *b));
+extern void read_error    OF((void));
+extern void write_error   OF((void));
+extern void display_ratio OF((long num, long den));
+extern voidp xmalloc      OF((unsigned int size));
+
+       /* in inflate.c */
+extern int inflate OF((void));
diff --git a/zBoot/head.S b/zBoot/head.S
new file mode 100644 (file)
index 0000000..eb27b2b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  linux/boot/head.s
+ *
+ *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
+ */
+
+/*
+ *  head.s contains the 32-bit startup code.
+ *
+ * NOTE!!! Startup happens at absolute address 0x00000000, which is also where
+ * the page directory will exist. The startup code will be overwritten by
+ * the page directory.
+ */
+.text
+
+startup_32:
+       cld
+       cli
+       movl $0x10,%eax
+       mov %ax,%ds
+       mov %ax,%es
+       mov %ax,%fs
+       mov %ax,%gs
+       lss _stack_start,%esp
+       xorl %eax,%eax
+1:     incl %eax               # check that A20 really IS enabled
+       movl %eax,0x000000      # loop forever if it isn't
+       cmpl %eax,0x100000
+       je 1b
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+       pushl $0
+       popfl
+       call _decompress_kernel
+       ljmp $0x08, $0x100000
diff --git a/zBoot/inflate.c b/zBoot/inflate.c
new file mode 100644 (file)
index 0000000..b261914
--- /dev/null
@@ -0,0 +1,995 @@
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+   [The history has been moved to the file ChangeLog.]
+ */
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor deals with some chunk of data at a time, and
+   decides which method to use on a chunk-by-chunk basis.  A chunk might
+   typically be 32K or 64K.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data is compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data is preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block codes up smaller that way (usually for quite small
+   chunks), otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block, and so
+   can code it much better than the pre-determined fixed codes.
+   The Huffman codes themselves are decoded using a mutli-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
+#endif
+
+/* #include "tailor.h" */
+#include "gzip.h"
+#define slide window
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#  include <sys/types.h>
+#  include <stdlib.h>
+#endif
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft {
+  uch e;                /* number of extra bits or operation */
+  uch b;                /* number of bits in this code or subcode */
+  union {
+    ush n;              /* literal, length base, or distance base */
+    struct huft *t;     /* pointer to next level of table */
+  } v;
+};
+
+
+/* Function prototypes */
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+                   struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+/* unsigned wp;             current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = {    /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = {         /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static ush cpdext[] = {         /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+   
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the begining of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes becuase fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+ulg bb;                         /* bit buffer */
+unsigned bk;                    /* bits in bit buffer */
+
+ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+  uch cc;
+#  define NEXTBYTE() \
+     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+#  define NEXTBYTE()  (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+int lbits = 9;          /* bits in base literal/length lookup table */
+int dbits = 6;          /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16         /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+
+unsigned hufts;         /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
+unsigned n;             /* number of codes (assumed <= N_MAX) */
+unsigned s;             /* number of simple-valued codes (0..s-1) */
+ush *d;                 /* list of base values for non-simple codes */
+ush *e;                 /* list of extra bits for non-simple codes */
+struct huft **t;        /* result: starting table */
+int *m;                 /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  unsigned f;                   /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register unsigned i;          /* counter, current code */
+  register unsigned j;          /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  register unsigned *p;         /* pointer into c[], b[], or v[] */
+  register struct huft *q;      /* points to current table */
+  struct huft r;                /* table entry for structure assignment */
+  struct huft *u[BMAX];         /* table stack */
+  unsigned v[N_MAX];            /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  unsigned *xp;                 /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  unsigned z;                   /* number of entries in current table */
+
+DEBG("huft1 ");
+
+  /* Generate counts for each bit length */
+  memzero(c, sizeof(c));
+  p = b;  i = n;
+  do {
+    Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 
+           n-i, *p));
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (struct huft *)NULL;
+    *m = 0;
+    return 0;
+  }
+
+DEBG("huft2 ");
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)l > i)
+    l = i;
+  *m = l;
+
+DEBG("huft3 ");
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                 /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+DEBG("huft4 ");
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+DEBG("huft5 ");
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+
+DEBG("h6 ");
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+DEBG("h6a ");
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+DEBG("h6b ");
+    a = c[k];
+    while (a--)
+    {
+DEBG("h6b1 ");
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+DEBG1("1 ");
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+DEBG1("2 ");
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          while (++j < z)       /* try smaller tables up to z bits */
+          {
+            if ((f <<= 1) <= *++xp)
+              break;            /* enough codes to use up j bits */
+            f -= *xp;           /* else deduct codes from patterns */
+          }
+        }
+DEBG1("3 ");
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+            (struct huft *)NULL)
+        {
+DEBG1("31 ");
+         error("malloc failed\n");
+          if (h)
+            huft_free(u[0]);
+          return 3;             /* not enough memory */
+        }
+DEBG1("4 ");
+        hufts += z + 1;         /* track memory usage */
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->v.t)) = (struct huft *)NULL;
+        u[h] = ++q;             /* table starts after link */
+
+DEBG1("5 ");
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l;         /* bits to dump before this table */
+          r.e = (uch)(16 + j);  /* bits in this table */
+          r.v.t = q;            /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+DEBG1("6 ");
+      }
+DEBG("h6c ");
+
+      /* set up table entry in r */
+      r.b = (uch)(k - w);
+      if (p >= v + n)
+        r.e = 99;               /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.e = (uch)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
+        r.v.n = *p++;           /* simple code is just the value */
+      }
+      else
+      {
+        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
+        r.v.n = d[*p++ - s];
+      }
+DEBG("h6d ");
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+DEBG("h6e ");
+    }
+DEBG("h6f ");
+  }
+
+DEBG("huft7 ");
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t;         /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *)NULL)
+  {
+    q = (--p)->v.t;
+    free(p);
+    p = q;
+  } 
+  return 0;
+}
+
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td;   /* literal/length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  for (;;)                      /* do until end of block */
+  {
+    NEEDBITS((unsigned)bl)
+    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+      do {
+        if (e == 99)
+          return 1;
+        DUMPBITS(t->b)
+        e -= 16;
+        NEEDBITS(e)
+      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      slide[w++] = (uch)t->v.n;
+      Tracevv((stderr, "%c", slide[w-1]));
+      if (w == WSIZE)
+      {
+        flush_output(w);
+        w = 0;
+      }
+    }
+    else                        /* it's an EOB or a length */
+    {
+      /* exit if end of block */
+      if (e == 15)
+        break;
+
+      /* get length of block to copy */
+      NEEDBITS(e)
+      n = t->v.n + ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e);
+
+      /* decode distance of block to copy */
+      NEEDBITS((unsigned)bd)
+      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+      Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+      /* do the copy */
+      do {
+        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+        if (w - d >= e)         /* (this test assumes unsigned comparison) */
+        {
+          memcpy(slide + w, slide + d, e);
+          w += e;
+          d += e;
+        }
+        else                      /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+          do {
+            slide[w++] = slide[d++];
+           Tracevv((stderr, "%c", slide[w-1]));
+          } while (--e);
+        if (w == WSIZE)
+        {
+          flush_output(w);
+          w = 0;
+        }
+      } while (n);
+    }
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  /* done */
+  return 0;
+}
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+  unsigned n;           /* number of bytes in block */
+  unsigned w;           /* current window position */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<stor");
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+
+  /* go to byte boundary */
+  n = k & 7;
+  DUMPBITS(n);
+
+
+  /* get the length and its complement */
+  NEEDBITS(16)
+  n = ((unsigned)b & 0xffff);
+  DUMPBITS(16)
+  NEEDBITS(16)
+  if (n != (unsigned)((~b) & 0xffff))
+    return 1;                   /* error in compressed data */
+  DUMPBITS(16)
+
+
+  /* read and output the compressed data */
+  while (n--)
+  {
+    NEEDBITS(8)
+    slide[w++] = (uch)b;
+    if (w == WSIZE)
+    {
+      flush_output(w);
+      w = 0;
+    }
+    DUMPBITS(8)
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+  int i;                /* temporary variable */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned l[288];      /* length list for huft_build */
+
+DEBG("<fix");
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)          /* make a complete, but wrong code set */
+    l[i] = 8;
+  bl = 7;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+    return i;
+
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+  {
+    huft_free(tl);
+
+    DEBG(">");
+    return i;
+  }
+
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+  return 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+  int i;                /* temporary variables */
+  unsigned j;
+  unsigned l;           /* last length */
+  unsigned m;           /* mask for bit lengths table */
+  unsigned n;           /* number of lengths to get */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned nb;          /* number of bit length codes */
+  unsigned nl;          /* number of literal/length codes */
+  unsigned nd;          /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+  unsigned ll[288+32];  /* literal/length and distance code lengths */
+#else
+  unsigned ll[286+30];  /* literal/length and distance code lengths */
+#endif
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<dyn");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in table lengths */
+  NEEDBITS(5)
+  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
+  DUMPBITS(5)
+  NEEDBITS(5)
+  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
+  DUMPBITS(5)
+  NEEDBITS(4)
+  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
+  DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+  if (nl > 288 || nd > 32)
+#else
+  if (nl > 286 || nd > 30)
+#endif
+    return 1;                   /* bad lengths */
+
+DEBG("dyn1 ");
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+  {
+    NEEDBITS(3)
+    ll[border[j]] = (unsigned)b & 7;
+    DUMPBITS(3)
+  }
+  for (; j < 19; j++)
+    ll[border[j]] = 0;
+
+DEBG("dyn2 ");
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+  {
+    if (i == 1)
+      huft_free(tl);
+    return i;                   /* incomplete code set */
+  }
+
+DEBG("dyn3 ");
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned)i < n)
+  {
+    NEEDBITS((unsigned)bl)
+    j = (td = tl + ((unsigned)b & m))->b;
+    DUMPBITS(j)
+    j = td->v.n;
+    if (j < 16)                 /* length of code in bits (0..15) */
+      ll[i++] = l = j;          /* save last length in l */
+    else if (j == 16)           /* repeat last length 3 to 6 times */
+    {
+      NEEDBITS(2)
+      j = 3 + ((unsigned)b & 3);
+      DUMPBITS(2)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = l;
+    }
+    else if (j == 17)           /* 3 to 10 zero length codes */
+    {
+      NEEDBITS(3)
+      j = 3 + ((unsigned)b & 7);
+      DUMPBITS(3)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+    else                        /* j == 18: 11 to 138 zero length codes */
+    {
+      NEEDBITS(7)
+      j = 11 + ((unsigned)b & 0x7f);
+      DUMPBITS(7)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+  }
+
+DEBG("dyn4 ");
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+DEBG("dyn5 ");
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+DEBG("dyn5a ");
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+  {
+DEBG("dyn5b ");
+    if (i == 1) {
+      error(" incomplete literal tree\n");
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+DEBG("dyn5c ");
+  bd = dbits;
+  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+  {
+DEBG("dyn5d ");
+    if (i == 1) {
+      error(" incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+      i = 0;
+    }
+#else
+      huft_free(td);
+    }
+    huft_free(tl);
+    return i;                   /* incomplete code set */
+#endif
+  }
+
+DEBG("dyn6 ");
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+DEBG("dyn7 ");
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+int inflate_block(e)
+int *e;                 /* last block flag */
+/* decompress an inflated block */
+{
+  unsigned t;           /* block type */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+  DEBG("<blk");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in last block bit */
+  NEEDBITS(1)
+  *e = (int)b & 1;
+  DUMPBITS(1)
+
+
+  /* read in block type */
+  NEEDBITS(2)
+  t = (unsigned)b & 3;
+  DUMPBITS(2)
+
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+  /* inflate that block type */
+  if (t == 2)
+    return inflate_dynamic();
+  if (t == 0)
+    return inflate_stored();
+  if (t == 1)
+    return inflate_fixed();
+
+  DEBG(">");
+
+  /* bad block type */
+  return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+  unsigned h;           /* maximum struct huft's malloc'ed */
+
+
+  /* initialize window, bit buffer */
+  wp = 0;
+  bk = 0;
+  bb = 0;
+
+
+  /* decompress until the last block */
+  h = 0;
+  do {
+    hufts = 0;
+    if ((r = inflate_block(&e)) != 0)
+      return r;
+    if (hufts > h)
+      h = hufts;
+  } while (!e);
+
+  /* Undo too much lookahead. The next read will be byte aligned so we
+   * can discard unused bits in the last meaningful byte.
+   */
+  while (bk >= 8) {
+    bk -= 8;
+    inptr--;
+  }
+
+  /* flush out slide */
+  flush_output(wp);
+
+
+  /* return success */
+#ifdef DEBUG
+  fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+  return 0;
+}
diff --git a/zBoot/lzw.h b/zBoot/lzw.h
new file mode 100644 (file)
index 0000000..b1901f7
--- /dev/null
@@ -0,0 +1,42 @@
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+#  include "gzip.h"
+#endif
+
+#ifndef BITS
+#  define BITS 16
+#endif
+#define INIT_BITS 9              /* Initial number of bits per code */
+
+#define        LZW_MAGIC  "\037\235"   /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK    0x1f /* Mask for 'number of compresssion bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE  0x80
+/* Block compresssion: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define        CLEAR  256       /* flush the dictionary */
+#define FIRST  (CLEAR+1) /* first free entry */
+
+extern int maxbits;      /* max bits per code for LZW */
+extern int block_mode;   /* block compress mode -C compatible with 2.0 */
+
+extern void lzw    OF((int in, int out));
+extern void unlzw  OF((int in, int out));
diff --git a/zBoot/misc.c b/zBoot/misc.c
new file mode 100644 (file)
index 0000000..d641ba4
--- /dev/null
@@ -0,0 +1,417 @@
+#include "gzip.h"
+#include "lzw.h"
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+       unsigned char  orig_x;
+       unsigned char  orig_y;
+       unsigned char  unused1[2];
+       unsigned short orig_video_page;
+       unsigned char  orig_video_mode;
+       unsigned char  orig_video_cols;
+       unsigned short orig_video_ega_ax;
+       unsigned short orig_video_ega_bx;
+       unsigned short orig_video_ega_cx;
+       unsigned char  orig_video_lines;
+};
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define EXT_MEM_K (*(unsigned short *)0x90002)
+#define DRIVE_INFO (*(struct drive_info *)0x90080)
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
+#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
+#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
+#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
+
+#define EOF -1
+
+DECLARE(uch, inbuf, INBUFSIZ);
+DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+DECLARE(uch, window, WSIZE);
+
+unsigned outcnt;
+unsigned insize;
+unsigned inptr;
+
+extern char input_data[];
+extern int input_len;
+
+int input_ptr;
+
+int method, exit_code, part_nb, last_member;
+int test = 0;
+int force = 0;
+int verbose = 1;
+long bytes_in, bytes_out;
+
+char *output_data;
+unsigned long output_ptr;
+
+extern int end;
+long free_mem_ptr = (long)&end;
+
+int to_stdout = 0;
+int hard_math = 0;
+
+void (*work)(int inf, int outf);
+
+char *vidmem = (char *)0xb8000;
+int vidp = 0;
+int lines, cols;
+
+void *malloc(int size)
+{
+       void *p;
+
+       if (size <0) error("Malloc error\n");
+       if (free_mem_ptr <= 0) error("Memory error\n");
+
+       free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
+
+       p = (void *)free_mem_ptr;
+
+       free_mem_ptr += size;
+
+       if (free_mem_ptr >= (640*1024)) error("\nOut of memory\n");
+
+       if (p == NULL) error("malloc = NULL\n");
+       return p;
+}
+
+void free(void *where)
+{      /* Don't care */
+}
+
+int printk(char *s)
+{
+       int i,n;
+       n = strlen(s);
+       if (!n) n = 10;
+
+       for (i=0;i<n;i++)
+       if (s[i] == '\n')
+       {
+                vidp = ((vidp / (cols*2)) + 1) * cols * 2;
+       } else {
+               vidmem[vidp] = s[i]; 
+               vidp = vidp + 2;
+       }
+
+       return 1;
+}
+
+__ptr_t memset(__ptr_t s, int c, size_t n)
+{
+       int i;
+       char *ss = (char*)s;
+
+       for (i=0;i<n;i++) ss[i] = c;
+}
+
+__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
+                           size_t __n)
+{
+       int i;
+       char *d = (char *)__dest, *s = (char *)__src;
+
+       for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+extern ulg crc_32_tab[];   /* crc table, defined below */
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register.  If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+ulg updcrc(s, n)
+    uch *s;                 /* pointer to bytes to pump through */
+    unsigned n;             /* number of bytes in s[] */
+{
+    register ulg c;         /* temporary variable */
+
+    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+    if (s == NULL) {
+       c = 0xffffffffL;
+    } else {
+       c = crc;
+       while (n--) {
+           c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+       }
+    }
+    crc = c;
+    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+    outcnt = 0;
+    insize = inptr = 0;
+    bytes_in = bytes_out = 0L;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+int fill_inbuf()
+{
+    int len, i;
+
+    /* Read as much as possible */
+    insize = 0;
+    do {
+       len = INBUFSIZ-insize;
+       if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
+        if (len == 0 || len == EOF) break;
+
+        for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
+       insize += len;
+       input_ptr += len;
+    } while (insize < INBUFSIZ);
+
+    if (insize == 0) {
+       error("unable to fill buffer\n");
+    }
+    bytes_in += (ulg)insize;
+    inptr = 1;
+    return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+    if (outcnt == 0) return;
+    updcrc(window, outcnt);
+
+    memcpy(&output_data[output_ptr], (char *)window, outcnt);
+
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by makecrc.c)
+ */
+ulg crc_32_tab[] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+
+void error(char *x)
+{
+       printk(x);
+       printk(" -- System halted");
+
+       while(1);       /* Halt */
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack [STACK_SIZE];
+
+struct {
+       long * a;
+       short b;
+       } stack_start = { & user_stack [STACK_SIZE] , 0x10 };
+
+void decompress_kernel()
+{
+       vidp = 0;
+       vidmem[0] = '0';
+
+       lines = SCREEN_INFO.orig_video_lines;
+       cols = SCREEN_INFO.orig_video_cols;
+
+       if (EXT_MEM_K < 2048) error("At least 2M of memory required by Turbo Ignition\n");
+
+       output_data = (char *)1048576;  /* Points to 1M */
+       output_ptr = 0;
+
+       exit_code = 0;
+       test = 0;
+       input_ptr = 0;
+       part_nb = 0;
+
+       clear_bufs();
+
+       printk("Uncompressing Linux: check - ");
+
+       method = get_method(0);
+
+       printk("work - ");
+
+       work(0, 0);
+
+       printk("done.\n\n");
+
+       printk("Now booting the kernel\n");
+}
+
+/* ========================================================================
+ * Check the magic number of the input file and update ofname if an
+ * original name was given and to_stdout is not set.
+ * Return the compression method, -1 for error, -2 for warning.
+ * Set inptr to the offset of the next byte to be processed.
+ * This function may be called repeatedly for an input file consisting
+ * of several contiguous gzip'ed members.
+ * IN assertions: there is at least one remaining compressed member.
+ *   If the member is a zip file, it must be the only one.
+ */
+local int get_method(in)
+    int in;        /* input file descriptor */
+{
+    uch flags;
+    char magic[2]; /* magic header */
+
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
+
+    method = -1;                 /* unknown yet */
+    part_nb++;                   /* number of parts in gzip file */
+    last_member = 0;
+    /* assume multiple members in gzip file except for record oriented I/O */
+
+    if (memcmp(magic, GZIP_MAGIC, 2) == 0
+        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+
+       work = unzip;
+       method = (int)get_byte();
+       flags  = (uch)get_byte();
+       if ((flags & ENCRYPTED) != 0) {
+           error("Input is encrypted -- too secret\n");
+           exit_code = ERROR;
+           return -1;
+       }
+       if ((flags & CONTINUATION) != 0) {
+              error("Input is a a multi-part gzip file\n");
+           exit_code = ERROR;
+           if (force <= 1) return -1;
+       }
+       if ((flags & RESERVED) != 0) {
+           error("Input has invalid flags\n");
+           exit_code = ERROR;
+           if (force <= 1) return -1;
+       }
+       (ulg)get_byte();        /* Get timestamp */
+       ((ulg)get_byte()) << 8;
+       ((ulg)get_byte()) << 16;
+       ((ulg)get_byte()) << 24;
+
+       (void)get_byte();  /* Ignore extra flags for the moment */
+       (void)get_byte();  /* Ignore OS type for the moment */
+
+       if ((flags & CONTINUATION) != 0) {
+           unsigned part = (unsigned)get_byte();
+           part |= ((unsigned)get_byte())<<8;
+           if (verbose) {
+               error("Input is not part number 1\n");
+           }
+       }
+       if ((flags & EXTRA_FIELD) != 0) {
+           unsigned len = (unsigned)get_byte();
+           len |= ((unsigned)get_byte())<<8;
+           while (len--) (void)get_byte();
+       }
+
+       /* Get original file name if it was truncated */
+       if ((flags & ORIG_NAME) != 0) {
+           if (to_stdout || part_nb > 1) {
+               /* Discard the old name */
+               while (get_byte() != 0) /* null */ ;
+           } else {
+           } /* to_stdout */
+       } /* orig_name */
+
+       /* Discard file comment if any */
+       if ((flags & COMMENT) != 0) {
+           while (get_byte() != 0) /* null */ ;
+       }
+
+    } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
+           && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {
+       /* To simplify the code, we support a zip file when alone only.
+         * We are thus guaranteed that the entire local header fits in inbuf.
+         */
+        inptr = 0;
+       work = unzip;
+       if (check_zipfile(in) == -1) return -1;
+       /* check_zipfile may get ofname from the local header */
+       last_member = 1;
+
+    } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
+       error("packed input");
+    } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
+       error("compressed input");
+       last_member = 1;
+    }
+    if (method == -1) {
+       error("Corrupted input\n");
+       if (exit_code != ERROR) exit_code = part_nb == 1 ? ERROR : WARNING;
+       return part_nb == 1 ? -1 : -2;
+    }
+    return method;
+}
diff --git a/zBoot/piggyback.c b/zBoot/piggyback.c
new file mode 100644 (file)
index 0000000..907cb9b
--- /dev/null
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+       int c, n=0, len=0;
+
+       printf( 
+               ".globl _input_data\n"
+               ".data\n"
+               "_input_data:\n");
+
+       while ((c=getchar()) != EOF)
+       {
+               len++;
+               if (!n) printf("\n.byte "); else printf(",");
+               printf("%d", c);
+               n = (n+1) & 0x1f;
+       }
+
+       printf("\n\n");
+
+       fprintf(stderr, "Compressed size %d.\n", len);
+
+
+       printf( ".globl _input_len\n"
+               ".align 2\n"
+               "_input_len:\n"
+               "\t.long %d\n", len);
+
+       exit(0);
+
+}
diff --git a/zBoot/unzip.c b/zBoot/unzip.c
new file mode 100644 (file)
index 0000000..d752b5e
--- /dev/null
@@ -0,0 +1,178 @@
+/* unzip.c -- decompress files in gzip or pkzip format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The code in this file is derived from the file funzip.c written
+ * and put in the public domain by Mark Adler.
+ */
+
+/*
+   This version can extract files in gzip or pkzip format.
+   For the latter, only the first entry is extracted, and it has to be
+   either deflated or stored.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
+#endif
+
+/* #include "tailor.h" */
+#include "gzip.h"
+#include "crypt.h"
+
+#include <stdio.h>
+
+/* PKZIP header definitions */
+#define LOCSIG 0x04034b50L      /* four-byte lead-in (lsb first) */
+#define LOCFLG 6                /* offset of bit flag */
+#define  CRPFLG 1               /*  bit for encrypted entry */
+#define  EXTFLG 8               /*  bit for extended local header */
+#define LOCHOW 8                /* offset of compression method */
+#define LOCTIM 10               /* file mod time (for decryption) */
+#define LOCCRC 14               /* offset of crc */
+#define LOCSIZ 18               /* offset of compressed size */
+#define LOCLEN 22               /* offset of uncompressed length */
+#define LOCFIL 26               /* offset of file name field length */
+#define LOCEXT 28               /* offset of extra field length */
+#define LOCHDR 30               /* size of local header, including sig */
+#define EXTHDR 16               /* size of extended local header, inc sig */
+
+
+/* Globals */
+
+int decrypt;      /* flag to turn on decryption */
+char *key;        /* not used--needed to link crypt.c */
+int pkzip = 0;    /* set for a pkzip file */
+int extended = 0; /* set if extended local header */
+
+/* ===========================================================================
+ * Check zip file and advance inptr to the start of the compressed data.
+ * Get ofname from the local header if necessary.
+ */
+int check_zipfile(in)
+    int in;   /* input file descriptors */
+{
+    uch *h = inbuf + inptr; /* first local header */
+
+    /* ifd = in; */
+
+    /* Check validity of local header, and skip name and extra fields */
+    inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+
+    if (inptr > insize || LG(h) != LOCSIG) {
+       error("input not a zip file or empty");
+    }
+    method = h[LOCHOW];
+    if (method != STORED && method != DEFLATED) {
+       error("first entry not deflated or stored--can't extract");
+    }
+
+    /* If entry encrypted, decrypt and validate encryption header */
+    if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
+       error("encrypted file, not yet supported.\n");
+       exit_code = ERROR;
+       return -1;
+    }
+
+    /* Save flags for unzip() */
+    extended = (h[LOCFLG] & EXTFLG) != 0;
+    pkzip = 1;
+
+    /* Get ofname and time stamp from local header (to be done) */
+    return 0;
+}
+
+/* ===========================================================================
+ * Unzip in to out.  This routine works on both gzip and pkzip files.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ *   the compressed data, from offsets inptr to insize-1 included.
+ *   The magic header has already been checked. The output buffer is cleared.
+ */
+void unzip(in, out)
+    int in, out;   /* input and output file descriptors */
+{
+    ulg orig_crc = 0;       /* original crc */
+    ulg orig_len = 0;       /* original uncompressed length */
+    int n;
+    uch buf[EXTHDR];        /* extended local header */
+
+    /* ifd = in;
+    ofd = out; */
+
+    updcrc(NULL, 0);           /* initialize crc */
+
+    if (pkzip && !extended) {  /* crc and length at the end otherwise */
+       orig_crc = LG(inbuf + LOCCRC);
+       orig_len = LG(inbuf + LOCLEN);
+    }
+
+    /* Decompress */
+    if (method == DEFLATED)  {
+
+       int res = inflate();
+
+       if (res == 3) {
+           error("out of memory");
+       } else if (res != 0) {
+           error("invalid compressed data--format violated");
+       }
+
+    } else if (pkzip && method == STORED) {
+
+       register ulg n = LG(inbuf + LOCLEN);
+
+       if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
+
+           error("invalid compressed data--length mismatch");
+       }
+       while (n--) {
+           uch c = (uch)get_byte();
+#ifdef CRYPT
+           if (decrypt) zdecode(c);
+#endif
+           if (!test) put_char(c);
+       }
+    } else {
+       error("internal error, invalid method");
+    }
+
+    /* Get the crc and original length */
+    if (!pkzip) {
+        /* crc32  (see algorithm.doc)
+        * uncompressed input size modulo 2^32
+         */
+       for (n = 0; n < 8; n++) {
+           buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+       }
+       orig_crc = LG(buf);
+       orig_len = LG(buf+4);
+
+    } else if (extended) {  /* If extended header, check it */
+       /* signature - 4bytes: 0x50 0x4b 0x07 0x08
+        * CRC-32 value
+         * compressed size 4-bytes
+         * uncompressed size 4-bytes
+        */
+       for (n = 0; n < EXTHDR; n++) {
+           buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+       }
+       orig_crc = LG(buf+4);
+       orig_len = LG(buf+12);
+    }
+
+    /* Validate decompression */
+    if (orig_crc != updcrc(outbuf, 0)) {
+       error("invalid compressed data--crc error");
+    }
+    if (orig_len != bytes_out) {
+       error("invalid compressed data--length error");
+    }
+
+    /* Check if there are more entries in a pkzip file */
+    if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
+           error("zip file has more than one entry");
+    }
+    extended = pkzip = 0; /* for next file */
+}
diff --git a/zBoot/xtract.c b/zBoot/xtract.c
new file mode 100644 (file)
index 0000000..40f3af1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  linux/tools/build.c
+ *
+ *  Copyright (C) 1991, 1992  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.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ */
+
+#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 <sys/sysmacros.h>
+#include <unistd.h>    /* contains read/write */
+#include <fcntl.h>
+#include <a.out.h>
+#include <linux/config.h>
+
+#define GCC_HEADER 1024
+
+#define STRINGIFY(x) #x
+
+void die(char * str)
+{
+       fprintf(stderr,"%s\n",str);
+       exit(1);
+}
+
+void usage(void)
+{
+       die("Usage: xtract system [ | gzip | piggyback > piggy.s]");
+}
+
+int main(int argc, char ** argv)
+{
+       int i,c,id, sz;
+       char buf[1024];
+       char major_root, minor_root;
+       struct stat sb;
+
+       struct exec *ex = (struct exec *)buf;
+
+       if (argc  != 2)
+               usage();
+       
+       if ((id=open(argv[1],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 (N_MAGIC(*ex) != ZMAGIC)
+               die("Non-GCC header of 'system'");
+
+       sz = N_SYMOFF(*ex) - GCC_HEADER + 4;    /* +4 to get the same result than tools/build */
+
+       fprintf(stderr, "System size is %d\n", sz);
+
+       while (sz)
+       {
+               int l, n;
+
+               l = sz;
+               if (l > sizeof(buf)) l = sizeof(buf);
+
+               if ((n=read(id, buf, l)) !=l)
+               {
+                       if (n == -1) 
+                          perror(argv[1]);
+                       else
+                          fprintf(stderr, "Unexpected EOF\n");
+
+                       die("Can't read system");
+               }
+
+               write(1, buf, l);
+               sz -= l;
+       }
+
+       close(id);
+       return(0);
+}