diff -u --recursive --new-file v1.3.34/linux/Documentation/networking/z8530drv.txt linux/Documentation/networking/z8530drv.txt
--- v1.3.34/linux/Documentation/networking/z8530drv.txt	Sat Sep  9 15:26:51 1995
+++ linux/Documentation/networking/z8530drv.txt	Sat Oct 14 10:55:16 1995
@@ -1,5 +1,5 @@
-// 950824: note -- I will upload the new version 1.9 to ftp.ucsd.edu
-//         as soon as possible... 
+// 950913: note -- I will upload the new version 1.9a to ftp.ucsd.edu
+//         as soon as possible...
 //
 // ******
 // ****** The driver has a  n e w  MAJOR number (34) now! ******
@@ -7,15 +7,25 @@
 //
 // please remake /dev/sc*:
 //
-// mknod /dev/sc1 c 34 0
-// mknod /dev/sc2 c 34 1
-// mknod /dev/sc3 c 34 2
-// mknod /dev/sc4 c 34 3
+// mknod /dev/scc0 c 34 0
+// mknod /dev/scc1 c 34 1
+// mknod /dev/scc2 c 34 2
+// mknod /dev/scc3 c 34 3
 //
 // (and so on...)
 //
+// If you want to use the old device naming scheme use:
+//
+// ln -f /dev/scc0 /dev/sc1
+// ln -f /dev/scc1 /dev/sc2
+// ln -f /dev/scc2 /dev/sc3
+// ln -f /dev/scc3 /dev/sc4
+//
+// (you get the idea...)
+//
 // -dl1bke-
 
+
 This is a subset of the documentation. To use this driver you MUST have the
 full package from:
 
@@ -252,11 +262,11 @@
 delivered with this package. Change it to your needs:
 
 Each channel definition is divided into three sections. An
-example for /dev/sc1:
+example for /dev/scc0:
 
 # DEVICE
 
-device /dev/sc1		# the device for the following params
+device /dev/scc0		# the device for the following params
 
 # MODEM
 
@@ -318,10 +328,10 @@
 # NOTE: Interfacename and the device must be the same!!
 # Usage: attach asy 0 0 slip|vjslip|ax25ui|ax25i|nrs|kissui <label> 0 <mtu> <speed> [ip_addr]
 #
-attach asy 0 0 kissi sc1 256 256 1200    # Attach SCC channel 1 in 1200 baud
-attach asy 0 0 kissi sc2 256 256 1200    # Attach SCC channel 2 in 1200 baud
-attach asy 0 0 kissui sc3 256 256 38400  # Attach SCC channel 3 in 38400 baud
-attach asy 0 0 kissui sc4 256 256 9600   # Attach SCC channel 4 in 9600 baud
+attach asy 0 0 kissi scc0 256 256 1200    # Attach SCC channel 1 in 1200 baud
+attach asy 0 0 kissi scc1 256 256 1200    # Attach SCC channel 2 in 1200 baud
+attach asy 0 0 kissui scc2 256 256 38400  # Attach SCC channel 3 in 38400 baud
+attach asy 0 0 kissui scc3 256 256 9600   # Attach SCC channel 4 in 9600 baud
 #                ^
 #                 for WAMPES 921229 use here: ax25
 #
@@ -331,10 +341,10 @@
 ############################################
 # JNOS device attach
 #
-#attach asy sc1 0 ax25 sc1 256 256 1200
-#attach asy sc2 0 ax25 sc2 256 256 1200
-#attach asy sc3 0 ax25 sc3 256 256 300
-#attach asy sc4 0 ax25 sc4 256 256 4800
+#attach asy scc0 0 ax25 scc0 256 256 1200
+#attach asy scc1 0 ax25 scc1 256 256 1200
+#attach asy scc2 0 ax25 scc2 256 256 300
+#attach asy scc3 0 ax25 scc3 256 256 4800
 #
 #
 
@@ -361,7 +371,7 @@
 Once a SCC channel has been attached, the parameter settings and 
 some statistic information can be shown using the param program:
 
-dl1bke-u:~$ sccstat /dev/sc1
+dl1bke-u:~$ sccstat /dev/scc0
 
 Parameters:
 
@@ -462,7 +472,7 @@
 speed:
      The baudrate on this channel in bits/sec
 
-     Example: sccparam /dev/sc4 speed 9600
+     Example: sccparam /dev/scc3 speed 9600
 
 txdelay:
      The delay (in units of 10ms) after keying of the 
@@ -474,7 +484,7 @@
      transmitter is ready for data.
      A normal value of this parameter is 30-36.
 
-     Example: sccparam /dev/sc1 txd 20
+     Example: sccparam /dev/scc0 txd 20
 
 persist:
      This is the probability that the transmitter will be keyed 
@@ -483,14 +493,14 @@
      should be somewhere near 50-60, and should be lowered when 
      the channel is used more heavily.
 
-     Example: sccparam /dev/sc3 persist 20
+     Example: sccparam /dev/scc2 persist 20
 
 slottime:
      This is the time between samples of the channel. It is 
      expressed in units of 10ms.  About 200-300 ms (value 20-30) 
      seems to be a good value.
 
-     Example: sccparam /dev/sc1 slot 20
+     Example: sccparam /dev/scc0 slot 20
 
 tail:
      The time the transmitter will remain keyed after the last 
@@ -501,7 +511,7 @@
      sufficient, e.g. 40ms at 1200 baud. (value 4)
      The value of this parameter is in 10ms units.
 
-     Example: sccparam /dev/sc3 4
+     Example: sccparam /dev/scc2 4
 
 full:
      The full-duplex mode switch. This can be one of the folowing 
@@ -517,7 +527,7 @@
           sent in that case, until a timeout (parameter 10) 
           occurs.
 
-     Example: sccparam /dev/sc1 fulldup off
+     Example: sccparam /dev/scc0 fulldup off
 
 wait:
      The initial waittime before any transmit attempt, after the 
@@ -526,7 +536,7 @@
      set to 0 for maximum performance.
      The value of this parameter is in 10ms units. 
 
-     Example: sccparam /dev/sc2 wait 4
+     Example: sccparam /dev/scc1 wait 4
 
 maxkey:
      The maximal time the transmitter will be keyed to send 
@@ -540,13 +550,13 @@
      The value 0 as well as "off" will disable this feature, 
      and allow infinite transmission time. 
 
-     Example: sccparam /dev/sc1 maxk 20
+     Example: sccparam /dev/scc0 maxk 20
 
 min:
      This is the time the transmitter will be switched off when 
      the maximum transmission time is exceeded.
 
-     Example: sccparam /dev/sc4 min 10
+     Example: sccparam /dev/scc3 min 10
 
 idle
      This parameter specifies the maximum idle time in fullduplex 
@@ -555,7 +565,7 @@
      has same result as the fullduplex mode 1. This parameter
      can be disabled.
 
-     Example: sccparam /dev/sc3 idle off	# transmit forever
+     Example: sccparam /dev/scc2 idle off	# transmit forever
 
 maxdefer
      This is the maximum time (in seconds) to wait for a free channel
@@ -563,14 +573,14 @@
      IMMEDIATLY. If you love to get trouble with other users you
      should set this to a very low value ;-)
 
-     Example: sccparam /dev/sc1 maxdefer 240	# 2 minutes
+     Example: sccparam /dev/scc0 maxdefer 240	# 2 minutes
 
 
 txoff:
      When this parameter has the value 0, the transmission of packets
      is enable. Otherwise it is disabled.
 
-     Example: sccparam /dev/sc3 txoff on
+     Example: sccparam /dev/scc2 txoff on
 
 group:
      It is possible to build special radio equipment to use more than 
@@ -610,56 +620,21 @@
      use a software dcd instead of the real one... Useful for a very
      slow squelch.
 
-     Example: sccparam /dev/sc1 soft on
+     Example: sccparam /dev/scc0 soft on
 
 
 slip:
      use slip encoding instead of kiss
 
-     Example: sccparam /dev/sc2 slip on
+     Example: sccparam /dev/scc1 slip on
 
 
 
 2. Problems
 ===========
 
-We are poking around in somebody else's code, so everything may change
-from one patchlevel to another... If the patches fail, try the
-following:
-
-2.1 /linux/drivers/char/Makefile
-================================
-
-Add "scc.o" to the definition of OBJS and "scc.c" to SRCS
-
-
-2.2 /linux/include/linux/tty_driver.h
-=====================================
-
-add the following DEFINE:
-
-#define TTY_DRIVER_TYPE_SCC 0x0005
-
-
-2.3 /linux/drivers/char/tty_io.c
-================================
-
-in tty_init() add the line
-
-	kmem_start=scc_init(kmem_start);
-
-just before "return kmem_start".
-
-2.4 /linux/arch/i386/config.in
-==============================
-
-somewhere in that file add:
-
-	comment 'Z8530 SCC driver for Amateur Packet Radio'
-	bool 'KISS emulator for Z8530 based HDLC cards' CONFIG_SCC y
-	comment ''
-  
 
+[..]
 
 2.5 Other problems
 ==================
@@ -697,78 +672,15 @@
 - NET's speed itself.
 
 
-Kernel panics (based on excerpts from /linux/README)
-
-
-- if a bug results in a message like
-
-	unable to handle kernel paging request at address C0000010
-	Oops: 0002
-	EIP:   0010:XXXXXXXX
-	eax: xxxxxxxx   ebx: xxxxxxxx   ecx: xxxxxxxx   edx: xxxxxxxx
-	esi: xxxxxxxx   edi: xxxxxxxx   ebp: xxxxxxxx
-	ds: xxxx  es: xxxx  fs: xxxx  gs: xxxx
-	Pid: xx, process nr: xx
-	xx xx xx xx xx xx xx xx xx xx
-
-  or similar kernel debugging information on your screen or in your
-  system log, please duplicate it *exactly*.  The dump may look
-  incomprehensible to you, but it does contain information that may
-  help debugging the problem.  The text above the dump is also
-  important: it tells something about why the kernel dumped code (in
-  the above example it's due to a bad kernel pointer)
-
-- in debugging dumps like the above, please look up what the EIP value 
-  means.  The hex value as such doesn't help me or anybody else very much: 
-  it will depend on your particular kernel setup.  What you should do is 
-  take the hex value from the EIP line (ignore the "0010:"), and look it up 
-  in the kernel namelist to see which kernel function contains the offending 
-  address.
-
-  To find out the kernel function name, you'll need to 
-
-         less /linux/System.map
-
-  This will give you a list of kernel addresses sorted in ascending
-  order, from which it is simple to find the function that contains the
-  offending address.  Note that the address given by the kernel
-  debugging messages will not necessarily match exactly with the
-  function addresses (in fact, that is very unlikely), so you can't
-  just 'grep' the list: the list will, however, give you the starting
-  point of each kernel function, so by looking for the function that
-  has a starting address lower than the one you are searching for but
-  is followed by a function with a higher address you will find the one
-  you want.  In fact, it may be [IS!] a good idea to include a bit of
-  "context" in your problem report, giving a few lines around the
-  interesting one. 
-
-  I included a small program which does this for you. Just call
-
-         grep_eip /linux/System.map address
-
-  for example: grep_eip /linux/System.map 182f98
-
-- alternately, you can use gdb on a running kernel. (read-only; i.e. you
-  cannot change values or set break points.) To do this, first compile the
-  kernel with -g; edit arch/i386/Makefile appropriately, then do a "make
-  clean". You'll also need to enable CONFIG_PROC_FS (via "make config").
-
-  After you've rebooted with the new kernel, do "gdb vmlinux /proc/kcore".
-  You can now use all the usual gdb commands. The command to look up the
-  point where your system crashed is "l *0xXXXXXXXX". (Replace the XXXes
-  with the EIP value.)
-
-  gdb'ing a non-running kernel currently fails because gdb (wrongly)
-  disregards the starting offset for which the kernel is compiled.
-
-
+Kernel panics: please read to /linux/README and find out if it
+really occured within the scc driver.
 
 If you can't solve a problem, send me
 
 - a description of the problem,
 - information on your hardware (computer system, scc board, modem)
 - your kernel version
-- the output of sccstat /dev/sc# ("#" is the No. of the channel)
+- the output of sccstat /dev/scc# ("#" is the No. of the channel)
 - the settings of "speed", "clock" and "mode" for that channel
   in /etc/z8530drv.rc
 - your scc_config.h
@@ -779,79 +691,9 @@
 The 1.2.* series should run reliable. This driver perhaps NOT!
 The 1.3.* kernel series is for alpha tests again... you get the idea!
 
-------------
-
-Example scc_config.h
-
-#include <linux/scc.h>
-
-/********* CONFIGURATION PARAMATERES; PLEASE CHANGE THIS TO YOUR OWN SITUATION **********/
-
-/* SCC hardware parameters */
-
-/* use the following board types: 
- *
- *	PA0HZP		OptoSCC (PA0HZP)
- *	EAGLE         	EAGLE
- *	PC100         	PC100 
- *	PRIMUS        	PRIMUS-PC (DG9BL)
- *	DRSI          	DRSI PC*Packet
- *	BAYCOM        	BayCom (U)SCC
- *	
- */
-
-int     Nchips	     = 2	; /* number of chips */
-io_port Vector_Latch = 0	; /* addr. of INTACK-Latch (0 for poll mode) */
-int     Ivec	     = 7	; /* interrupt vector */
-long    Clock	     = 4915200	; /* frequency of the scc clock */
-char	Board	     = BAYCOM	; /* what type of SCC card do you use? */
-int	Option	     = 0	; /* command for extra hardware */
-io_port Special_Port = 0	; /* port address for special hardware */
-				  /* (for EAGLE, PC100, PRIMUS, DRSI) */
-
-			/*      ^  never remove the semicolon !! */
-			
 
-
-/* 			Channel    A      B	    Chip	*/
-/*			         ============	  ========	*/
-/* Control ports:						*/
-
-io_port SCC_ctrl[MAXSCC * 2] = 	{0x304, 0x305,  /* ...one... 	*/
-				 0x306, 0x307,  /* ...two...	*/
-				     0,     0,  /* ...three...	*/
-				     0,     0}; /* ...four...	*/
-
-/* Data ports:							*/
-
-io_port SCC_data[MAXSCC * 2] =  {0x300, 0x301,	/* ...one...	*/
-				 0x302, 0x303,	/* ...two...	*/
-				     0,     0,	/* ...three...	*/
-				     0,     0};	/* ...four...	*/
-
-
-/* set to '1' if you have and want ESCC chip (8580/85180/85280) support */
-
-/*					      Chip	*/
-/*				            ========   	*/
-int SCC_Enhanced[MAXSCC] =	{0,	/* ...one...	*/
-				 0,  	/* ...two...	*/
-				 0,  	/* ...three...	*/
-				 0};	/* ...four...	*/
-
-/* some useful #defines. You might need them or not */
-
-#define VERBOSE_BOOTMSG 1
-#undef  SCC_DELAY		/* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY		/* slow it even a bit more down */
-#undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
-
-
-/* The external clocking, nrz and fullduplex divider configuration is gone */
-/* you can set these parameters in /etc/z8530drv.rc and initialize the  */
-/* driver with sccinit */
-
----------
+3. DRSI Boards
+==============
 
 I still can't test the DRSI board, but this configuration derived from
 the PE1CHL SCC driver configuration should work:
@@ -933,9 +775,6 @@
 #undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
 
 
-
-
-
 *****************
 
 You  m u s t  use "clock dpll" in /etc/z8530drv.rc for operation, 
@@ -944,9 +783,16 @@
 *****************
 (mni tnx to Mike Bilow)
 
- 
-...an many thanks to Linus Torvalds and Alan Cox for including the driver
-   in the LinuX standard distribution...
+
+4. Thor RLC100
+==============
+
+Mysteriously this board seems not to work with the driver. Anyone
+got it up-and-running?
+
+
+Many thanks to Linus Torvalds and Alan Cox for including the driver
+in the LinuX standard distribution and their support.
 
 Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
 		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
diff -u --recursive --new-file v1.3.34/linux/MAGIC linux/MAGIC
--- v1.3.34/linux/MAGIC	Tue Jan 10 10:07:09 1995
+++ linux/MAGIC	Sat Oct 14 10:58:47 1995
@@ -50,6 +50,7 @@
 Ioctl	Include File	Comments
 ========================================================
 0x00	fd.h
+0x01	random.h	subcodes starting at 0x080000
 0x03	hdreg.h
 0x06	lp.h
 0x12	fs.h
diff -u --recursive --new-file v1.3.34/linux/Makefile linux/Makefile
--- v1.3.34/linux/Makefile	Fri Oct 13 14:44:31 1995
+++ linux/Makefile	Sun Oct 15 19:00:12 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 34
+SUBLEVEL = 35
 
 ARCH = i386
 
@@ -134,6 +134,10 @@
 oldconfig: symlinks
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
 
+xconfig: symlinks
+	( cd scripts ; make kconfig.tk)
+	./scripts/kconfig.tk
+
 config: symlinks
 	$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
 
@@ -243,6 +247,7 @@
 	rm -f drivers/scsi/aic7xxx_asm drivers/scsi/aic7xxx_seq.h
 	rm -f drivers/char/uni_hash.tbl drivers/char/conmakehash
 	rm -f .version .config* config.in config.old
+	rm -f scripts/tkparse scripts/kconfig.tk
 	rm -f include/asm
 	rm -f .depend `find . -name .depend -print`
 	rm -f .hdepend
diff -u --recursive --new-file v1.3.34/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.3.34/linux/arch/alpha/config.in	Fri Oct 13 14:44:32 1995
+++ linux/arch/alpha/config.in	Mon Oct 16 07:57:28 1995
@@ -2,7 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
+mainmenu_option next_comment
 comment 'General setup'
 
 if [ "`uname`" != "Linux" ]; then
@@ -63,6 +65,7 @@
 bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS n
 
 if [ "$CONFIG_NET" = "y" ]; then
+mainmenu_option next_comment
 comment 'Networking options'
 bool 'TCP/IP networking' CONFIG_INET y
 if [ "$CONFIG_INET" = "y" ]; then
@@ -94,6 +97,7 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'SCSI support'
 
 tristate 'SCSI support' CONFIG_SCSI y
@@ -115,6 +119,7 @@
 
 bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN n
 
+mainmenu_option next_comment
 comment 'SCSI low-level drivers'
 
 dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n $CONFIG_SCSI
@@ -144,6 +149,7 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 
+mainmenu_option next_comment
 comment 'Network device support'
 
 bool 'Network device support' CONFIG_NETDEVICES y
@@ -237,6 +243,7 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
 bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI n
@@ -262,6 +269,7 @@
   bool 'Experimental Sanyo H94A CDROM support' CONFIG_SJCD n
 fi
 
+mainmenu_option next_comment
 comment 'Filesystems'
 
 tristate 'Standard (minix) fs support' CONFIG_MINIX_FS y
@@ -281,6 +289,7 @@
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
 tristate 'SMB filesystem (to mount WfW shares etc..) support' CONFIG_SMB_FS n
 
+mainmenu_option next_comment
 comment 'character devices'
 
 bool 'Cyclades async mux support' CONFIG_CYCLADES n
@@ -314,10 +323,12 @@
   int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
 fi
 
+mainmenu_option next_comment
 comment 'Sound'
 
 bool 'Sound card support' CONFIG_SOUND n
 
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
diff -u --recursive --new-file v1.3.34/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v1.3.34/linux/arch/alpha/kernel/irq.c	Tue Oct 10 18:46:30 1995
+++ linux/arch/alpha/kernel/irq.c	Mon Oct 16 12:45:30 1995
@@ -17,6 +17,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/random.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -322,10 +323,8 @@
 
 	kstat.interrupts[irq]++;
 	action = irq_action + irq;
-#ifdef CONFIG_RANDOM
 	if (action->flags & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
-#endif
 	/* quick interrupts get executed with no extra overhead */
 	if (action->flags & SA_INTERRUPT) {
 		action->handler(irq, regs);
diff -u --recursive --new-file v1.3.34/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.34/linux/arch/i386/config.in	Fri Oct 13 14:44:32 1995
+++ linux/arch/i386/config.in	Mon Oct 16 15:23:25 1995
@@ -2,7 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+mainmenu_name "Linux Kernel Configuration"
 
+mainmenu_option next_comment
 comment 'General setup'
 
 bool 'Kernel math emulation' CONFIG_MATH_EMULATION n
@@ -42,10 +44,12 @@
 #fi
 bool 'SMP Kernel (experimental - gcc2.5.8 only: see Documentation/SMP.txt)' CONFIG_SMP n
 
+mainmenu_option next_comment
 comment 'Loadable module support'
 bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS n
 
 if [ "$CONFIG_NET" = "y" ]; then
+mainmenu_option next_comment
 comment 'Networking options'
 bool 'TCP/IP networking' CONFIG_INET y
 if [ "$CONFIG_INET" = "y" ]; then
@@ -81,6 +85,7 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'SCSI support'
 
 tristate 'SCSI support' CONFIG_SCSI n
@@ -102,6 +107,7 @@
 
 bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN n
 
+mainmenu_option next_comment
 comment 'SCSI low-level drivers'
 
 dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n $CONFIG_SCSI
@@ -132,6 +138,7 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 
+mainmenu_option next_comment
 comment 'Network device support'
 
 bool 'Network device support' CONFIG_NETDEVICES y
@@ -225,6 +232,7 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
 bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI n
@@ -247,9 +255,10 @@
   tristate 'Goldstar R420 CDROM support' CONFIG_GSCD n
   tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206 n
   tristate 'Experimental Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD n
-  bool 'Experimental Sanyo H94A CDROM support' CONFIG_SJCD n
+  tristate 'Experimental Sanyo H94A CDROM support' CONFIG_SJCD n
 fi
 
+mainmenu_option next_comment
 comment 'Filesystems'
 
 tristate 'Standard (minix) fs support' CONFIG_MINIX_FS y
@@ -269,6 +278,7 @@
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
 tristate 'SMB filesystem (to mount WfW shares etc..) support' CONFIG_SMB_FS n
 
+mainmenu_option next_comment
 comment 'character devices'
 
 bool 'Cyclades async mux support' CONFIG_CYCLADES n
@@ -302,10 +312,12 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'Sound'
 
 tristate 'Sound card support' CONFIG_SOUND n
 
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
diff -u --recursive --new-file v1.3.34/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v1.3.34/linux/arch/i386/kernel/irq.c	Wed Oct  4 14:14:28 1995
+++ linux/arch/i386/kernel/irq.c	Sat Oct 14 10:58:47 1995
@@ -214,10 +214,8 @@
 #endif
 
 	kstat.interrupts[irq]++;
-#ifdef CONFIG_RANDOM
 	if (action->flags & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
-#endif
 	action->handler(irq, regs);
 }
 
@@ -236,10 +234,8 @@
 #endif
 
 	kstat.interrupts[irq]++;
-#ifdef CONFIG_RANDOM
 	if (action->flags & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
-#endif
 	action->handler(irq, NULL);
 }
 
@@ -258,6 +254,8 @@
 		return -EBUSY;
 	if (!handler)
 		return -EINVAL;
+	if (irqflags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
 	save_flags(flags);
 	cli();
 	action->handler = handler;
diff -u --recursive --new-file v1.3.34/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v1.3.34/linux/arch/sparc/config.in	Tue Aug  8 12:31:33 1995
+++ linux/arch/sparc/config.in	Sun Oct 15 18:57:01 1995
@@ -8,10 +8,12 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+mainmenu_name 'Sparc Linux Kernel Configuration'
 
 echo "#define CONFIG_SPARCDEVS 1" >> $CONFIG_H
 echo "CONFIG_SPARCDEVS=y" >> $CONFIG
 
+mainmenu_option next_comment
 comment 'Sparc Kernel setup'
 
 bool 'Sun floppy controller support' CONFIG_BLK_DEV_SUNFD n
@@ -21,6 +23,7 @@
 bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
 
 if [ "$CONFIG_NET" = "y" ]; then
+mainmenu_option next_comment
 comment 'Networking options'
 bool 'TCP/IP networking' CONFIG_INET y
 if [ "$CONFIG_INET" "=" "y" ]; then
@@ -38,6 +41,7 @@
 #bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
 fi
 
+mainmenu_option next_comment
 comment 'SCSI support'
 
 bool 'SCSI support?' CONFIG_SCSI n
@@ -64,6 +68,7 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 
+mainmenu_option next_comment
 comment 'Network device support'
 
 bool 'Network device support?' CONFIG_NETDEVICES y
@@ -86,6 +91,7 @@
 fi
 fi
 
+mainmenu_option next_comment
 comment 'Filesystems'
 
 bool 'Standard (minix) fs support' CONFIG_MINIX_FS n
@@ -106,6 +112,7 @@
 bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
 
 
+mainmenu_option next_comment
 comment 'character devices'
 
 bool 'Zilog serial support' CONFIG_SUN_ZS n
@@ -114,6 +121,7 @@
 
 bool 'Sun Audio support' CONFIG_SUN_AUDIO n
 
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
 bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
diff -u --recursive --new-file v1.3.34/linux/drivers/Makefile linux/drivers/Makefile
--- v1.3.34/linux/drivers/Makefile	Fri Oct 13 14:44:32 1995
+++ linux/drivers/Makefile	Sun Oct 15 18:54:26 1995
@@ -15,8 +15,11 @@
 SUB_DIRS += pci
 endif
 
+# If CONFIG_SCSI is set, the core of scsi support will be added to the kernel,
+# but some of the low-level things may also be modules.
 ifeq ($(CONFIG_SCSI),y)
 SUB_DIRS += scsi
+MOD_SUB_DIRS += scsi
 else
   ifeq ($(CONFIG_SCSI),m)
   MOD_SUB_DIRS += scsi
diff -u --recursive --new-file v1.3.34/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v1.3.34/linux/drivers/block/Makefile	Thu Sep  7 17:17:16 1995
+++ linux/drivers/block/Makefile	Mon Oct 16 15:23:25 1995
@@ -114,10 +114,10 @@
 
 ifeq ($(CONFIG_SJCD),y)
 L_OBJS += sjcd.o
-#else
-#  ifeq ($(CONFIG_SJCD),m)
-#  M_OBJS += sjcd.o
-#  endif
+else
+  ifeq ($(CONFIG_SJCD),m)
+  M_OBJS += sjcd.o
+  endif
 endif #CONFIG_SJCD
 
 ifeq ($(CONFIG_BLK_DEV_HD),y)
diff -u --recursive --new-file v1.3.34/linux/drivers/block/README.aztcd linux/drivers/block/README.aztcd
--- v1.3.34/linux/drivers/block/README.aztcd	Sun Sep  3 12:26:50 1995
+++ linux/drivers/block/README.aztcd	Sun Oct 15 20:02:23 1995
@@ -1,4 +1,4 @@
-$Id: README.aztcd,v 1.70 1995/08/19 16:21:05 root Exp root $
+$Id: README.aztcd,v 1.80 1995/10/11 19:37:49 root Exp root $
                        Readme-File README.aztcd
    for Aztech CD-ROM CDA268-01A, ORCHID CD-3110, OKANO/WEARNES CDD110 
                           CD-ROM  Driver 
@@ -15,6 +15,7 @@
       THE STANDARD-KERNEL 1.2.x NOW ALSO SUPPORTS IDE-CDROM-DRIVES, SEE THE
       HARDDISK (!) SECTION OF make config, WHEN COMPILING A NEW KERNEL!!!
 ----------------------------------------------------------------------------
+
 Contents of this file:
                          1.  NOTE
                          2.  INSTALLATION
diff -u --recursive --new-file v1.3.34/linux/drivers/block/README.sjcd linux/drivers/block/README.sjcd
--- v1.3.34/linux/drivers/block/README.sjcd	Tue Jul 18 16:28:56 1995
+++ linux/drivers/block/README.sjcd	Mon Oct 16 15:23:25 1995
@@ -6,7 +6,7 @@
 				Once started, training can not be stopped...
 						(StarWars)
 
-This is the README for the sjcd cdrom driver, version 1.3.
+This is the README for the sjcd cdrom driver, version 1.5.
 
 This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
 cdrom drive. It will grow as the questions arise. ;-)
@@ -21,8 +21,8 @@
 a warm reboot to boot Linux somehow doesn't work, at least not
 on Eric's machine (IPC P90), with the version of the ISP16
 card he has (there appear to be at least two versions: Eric's card with
-no jumpered IDE support and Vadim's version with a jumper to enable
-IDE support).
+no jumpered IDE support and OPTi 82C928 chip, and Vadim's version
+with a jumper to enable IDE support, probably with a OPTi 82C929 chip).
 Therefore detection and configuration of the ISP16 interfaces is included
 in the driver.
 If we should support any other interfaces (which cannot be configured
@@ -30,13 +30,18 @@
 know (maarel@marin.nl) and we'll see.
 
 Otherwise, you should boot DOS once (and by this, run the "configuration driver")
-and then switch to Linux by use of CTL-ALT-DEL. Each use of the RESET
+and then switch to Linux by use of CTRL-ALT-DEL. Each use of the RESET
 button or the power switch makes this procedure necessary again.
 If no ISP16 is detected, there's no harm done; a card configured trough DOS
 may still work as expected.
 
+As of version 1.4 sound through the speakers is supported; only for MSS-mode 
+and no volume controle yet.
+
+PAUSE and STOP ioctl commands don't seem to work yet.
+
 ISP16 configuration routines reside at Vadim's server
-      rbrf.msk.su:/linux/mediamagic/
+      ftp.rbrf.ru:/linux/mediamagic/
 and at Eberhard's mirror
       ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/
 
@@ -51,13 +56,13 @@
 
 The device major for sjcd is 18, and minor is 0. Create a block special
 file in your /dev directory (e.g., /dev/sjcd) with these numbers.
-(For those who don't know, being root and the following should do the trick:
+(For those who don't know, being root and doing the following should do the trick:
   mknod -m 644 /dev/sjcd b 18 0
 and mount the cdrom by /dev/sjcd).
 
 The default configuration parameters are:
   base address 0x340
-  irq 10
+  no irq
   no dma
 As of version 1.2, setting base address, irq and dma at boot time is supported
 through the use of command line options: type at the "boot:" prompt:
@@ -65,7 +70,7 @@
 (where your kernel is assumed to be called by saying "linux" to
 the boot manager).
 
-If something is wrong, e-mail to		vadim@rbrf.msk.su
+If something is wrong, e-mail to		vadim@rbrf.ru
 					or 	vadim@ipsun.ras.ru
 					or	model@cecmow.enet.dec.com
 
diff -u --recursive --new-file v1.3.34/linux/drivers/block/aztcd.c linux/drivers/block/aztcd.c
--- v1.3.34/linux/drivers/block/aztcd.c	Tue Oct 10 18:46:31 1995
+++ linux/drivers/block/aztcd.c	Sun Oct 15 20:02:23 1995
@@ -1,5 +1,5 @@
-#define AZT_VERSION "1.70"
-/*      $Id: aztcd.c,v 1.70 1995/08/19 16:16:39 root Exp root $
+#define AZT_VERSION "1.80"
+/*      $Id: aztcd.c,v 1.80 1995/10/11 19:35:03 root Exp root $
 	linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
 
 	Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
@@ -130,6 +130,10 @@
                 enough testing done. If you can test it, please contact me. For
                 details please read README.aztcd.
                 Werner Zimmermann, August 19, 1995
+        V1.80   Modification to suit the new kernel boot procedure introduced
+                with kernel 1.3.33. Will definitely not work with older kernels.
+                Programming done by Linus himself.
+                Werner Zimmermann, October 11, 1995
 	NOTE: 
 	Points marked with ??? are questionable !
 */
diff -u --recursive --new-file v1.3.34/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.34/linux/drivers/block/ide.c	Tue Oct 10 18:46:32 1995
+++ linux/drivers/block/ide.c	Sat Oct 14 10:58:47 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.14  Sep 14, 1995
+ *  linux/drivers/block/ide.c	Version 5.15  Oct 13, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
@@ -14,6 +14,22 @@
  * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
  * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
  * 
+ * It is easy to extend ide.c to handle more than four interfaces:
+ *
+ *	Change the MAX_HWIFS constant in ide.h.
+ * 
+ *	Define some new major numbers (in major.h), and insert them into
+ *	the ide_hwif_to_major table in ide.c.
+ * 
+ *	Fill in the extra values for the new interfaces into the two tables
+ *	inside ide.c:  default_io_base[]  and  default_irqs[].
+ * 
+ *	Create the new request handlers by cloning "do_ide3_request()"
+ *	for each new interface, and add them to the switch statement
+ *	in the ide_init() function in ide.c.
+ *
+ *	Recompile, create the new /dev/ entries, and it will probably work.
+ *
  *  From hd.c:
  *  |
  *  | It traverses the request-list, using interrupts to jump between functions.
@@ -145,6 +161,8 @@
  *  Version 5.14	fixes to cmd640 support.. maybe it works now(?)
  *			added & tested full EZ-DRIVE support -- don't use LILO!
  *			don't enable 2nd CMD640 PCI port during init - conflict
+ *  Version 5.15	bug fix in init_cmd640_vlb()
+ *			bug fix in interrupt sharing code
  *
  *  Driver compile-time options are in ide.h
  *
@@ -2400,6 +2418,7 @@
 	if (reg == 0xff || (reg & 0x90) != 0x90) {
 #if TRY_CMD640_VLB_AT_0x78
 		port = 0x78;
+		reg = read_cmd640_vlb(port, 0x50);
 		if (reg == 0xff || (reg & 0x90) != 0x90)
 #endif
 		{
@@ -2735,17 +2754,17 @@
 	 */
 	save_flags(flags);
 	cli();
-	if (request_irq(hwif->irq, ide_intr,
-			SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name)) {
-		restore_flags(flags);
-		printk(" -- FAILED!");
-		return 1;
-	}
-
-	/*
-	 * Got the irq,  now set everything else up
-	 */
 	if ((hwgroup = irq_to_hwgroup[hwif->irq]) == NULL) {
+		if (request_irq(hwif->irq, ide_intr,
+				SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name)) {
+			restore_flags(flags);
+			printk(" -- FAILED!");
+			return 1;
+		}
+
+		/*
+		 * Got the irq,  now set everything else up
+		 */
 		hwgroup = kmalloc (sizeof(ide_hwgroup_t), GFP_KERNEL);
 		irq_to_hwgroup[hwif->irq] = hwgroup;
 		hwgroup->hwif 	 = hwif->next = hwif;
diff -u --recursive --new-file v1.3.34/linux/drivers/block/sjcd.c linux/drivers/block/sjcd.c
--- v1.3.34/linux/drivers/block/sjcd.c	Tue Oct 10 18:46:32 1995
+++ linux/drivers/block/sjcd.c	Mon Oct 16 15:23:25 1995
@@ -1,24 +1,23 @@
 /* -- sjcd.c
  *
- *   Sanyo CD-ROM device driver implementation, Version 1.3
+ *   Sanyo CD-ROM device driver implementation, Version 1.5
  *   Copyright (C) 1995  Vadim V. Model
  *
  *   model@cecmow.enet.dec.com
- *   vadim@rbrf.msk.su
+ *   vadim@rbrf.ru
  *   vadim@ipsun.ras.ru
  *
  *   ISP16 detection and configuration.
  *   Copyright (C) 1995  Eric van der Maarel (maarel@marin.nl)
+ *                   and Vadim Model (vadim@cecmow.enet.dec.com)
  *
  *
  *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
  *  it was developed under use of mcd.c from Martin Harriss, with help of
  *  Eric van der Maarel (maarel@marin.nl).
  *
- *  ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl),
- *  with some data communicated by Vadim V. Model (vadim@rbrf.msk.su)
- *  and Leo Spiekman (spiekman@et.tudelft.nl)
- *
+ *  ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl).
+ *  Sound configuration by Vadim V. Model (model@cecmow.enet.dec.com)
  *
  *  It is planned to include these routines into sbpcd.c later - to make
  *  a "mixed use" on one cable possible for all kinds of drives which use
@@ -46,11 +45,25 @@
  *      on ISP16 soundcard.
  *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
  *  1.3 Some minor changes to README.sjcd.
+ *  1.4 MSS Sound support!! Listen to a CD through the speakers.
+ *  1.5 Module support and bugfixes.
+ *      Tray locking.
  *
  */
 
+#include <linux/major.h>
+#include <linux/config.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#define sjcd_init init_module
+#ifndef CONFIG_MODVERSIONS
+char kernel_version[]= UTS_RELEASE;
+#endif
+#endif
+
 #include <linux/errno.h>
-#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
@@ -59,7 +72,6 @@
 #include <linux/cdrom.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
-#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -102,26 +114,32 @@
 #define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
 /* ...for port */
 #define ISP16_IO_SET_PORT  0xF8E
-/* enable the drive */
-#define ISP16_NO_IDE__ENABLE_CDROM_PORT  0xF90  /* ISP16 without IDE interface */
-#define ISP16_IDE__ENABLE_CDROM_PORT  0xF91  /* ISP16 with IDE interface */
+/* enable the card */
+#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
 #define ISP16_ENABLE_CDROM  0x80  /* seven bit */
 
 /* the magic stuff */
 #define ISP16_CTRL_PORT  0xF8F
-#define ISP16_NO_IDE__CTRL  0xE2  /* ISP16 without IDE interface */
-#define ISP16_IDE__CTRL  0xE3  /* ISP16 with IDE interface */
+#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
 
 static short isp16_detect(void);
-static short isp16_no_ide__detect(void);
-static short isp16_with_ide__detect(void);
-static short isp16_config( int base, u_char drive_type, int irq, int dma );
+static short isp16_c928__detect(void);
+static short isp16_c929__detect(void);
+static short isp16_cdi_config( int base, u_char drive_type, int irq, int dma );
+static void isp16_sound_config( void );
 static short isp16_type; /* dependent on type of interface card */
 static u_char isp16_ctrl;
-static u_short isp16_enable_cdrom_port;
-
+static u_short isp16_enable_port;
 
 static int sjcd_present = 0;
+static u_char special_mask = 0;
+
+static unsigned char defaults[ 16 ] = {
+  0xA8, 0xA8, 0x18, 0x18, 0x18, 0x18, 0x8E, 0x8E,
+  0x03, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00
+};
 
 #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
 
@@ -137,6 +155,7 @@
  */
 static unsigned short sjcd_status_valid = 0;
 static unsigned short sjcd_door_closed;
+static unsigned short sjcd_door_was_open;
 static unsigned short sjcd_media_is_available;
 static unsigned short sjcd_media_is_changed;
 static unsigned short sjcd_toc_uptodate = 0;
@@ -151,9 +170,9 @@
 static int sjcd_audio_status;
 static struct sjcd_play_msf sjcd_playing;
 
-static short    sjcd_port = SJCD_BASE_ADDR;
-static int      sjcd_irq  = SJCD_INTR_NR;
-static int      sjcd_dma  = SJCD_DMA;
+static int sjcd_port = SJCD_BASE_ADDR;
+static int sjcd_irq  = SJCD_INTR_NR;
+static int sjcd_dma  = SJCD_DMA_NR;
 
 static struct wait_queue *sjcd_waitq = NULL;
 
@@ -174,17 +193,16 @@
 static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
 static long sjcd_transfer_timeout = 0;
 static int sjcd_read_count = 0;
-#if 0
-static unsigned short sjcd_tries;
-#endif
 static unsigned char sjcd_mode = 0;
 
 #define SJCD_READ_TIMEOUT 5000
 
+#if defined( SJCD_GATHER_STAT )
 /*
  * Statistic.
  */
 static struct sjcd_stat statistic;
+#endif
 
 /*
  * Timer.
@@ -202,8 +220,8 @@
  * Set up device, i.e., use command line data to set
  * base address, irq and dma.
  */
-void sjcd_setup( char *str, int *ints ){
-
+void sjcd_setup( char *str, int *ints )
+{
    if (ints[0] > 0)
       sjcd_port = ints[1];
    if (ints[0] > 1)      
@@ -243,7 +261,7 @@
  * Send a command to cdrom. Invalidate status.
  */
 static void sjcd_send_cmd( unsigned char cmd ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: send_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
@@ -256,7 +274,7 @@
  * Send a command with one arg to cdrom. Invalidate status.
  */
 static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: send_1_cmd( 0x%x, 0x%x )\n", cmd, a );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
@@ -271,7 +289,7 @@
  */
 static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a,
 	    unsigned char b, unsigned char c, unsigned char d ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: send_4_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
@@ -288,7 +306,7 @@
  * Send a play or read command to cdrom. Invalidate Status.
  */
 static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: send_long_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
@@ -312,7 +330,7 @@
 
   for( ; len; --len ){ 
     int i;
-    for( i = 200; i-- && inb( SJCDPORT( 1 ) ) !=  0x09; );
+    for( i = 200; i-- && !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ); );
     if( i > 0 ) *resp++ = ( unsigned char )inb( SJCDPORT( 0 ) );
     else break;
   }
@@ -320,7 +338,8 @@
 }
 
 /*
- * Load and parse status.
+ * Load and parse command completion status (drive info byte and maybe error).
+ * Sorry, no error classification yet.
  */
 static void sjcd_load_status( void ){
   sjcd_media_is_changed = 0;
@@ -333,7 +352,10 @@
     if( sjcd_completion_status & SST_MEDIA_CHANGED )
       sjcd_media_is_available = sjcd_media_is_changed = 1;
     else if( sjcd_completion_status & 0x0F ){
-      while( ( inb( SJCDPORT( 1 ) ) & 0x0B ) != 0x09 );
+      /*
+       * OK, we seem to catch an error ...
+       */
+      while( !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) );
       sjcd_completion_error = inb( SJCDPORT( 0 ) );
       if( ( sjcd_completion_status & 0x08 ) &&
 	 ( sjcd_completion_error & 0x40 ) )
@@ -346,8 +368,12 @@
    */
   sjcd_status_valid = 1, sjcd_error_reported = 0;
   sjcd_command_is_in_progress = 0;
+
+  /*
+   * If the disk is changed, the TOC is not valid.
+   */
   if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0;
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: status %02x.%02x loaded.\n",
 	 ( int )sjcd_completion_status, ( int )sjcd_completion_error );
 #endif
@@ -360,7 +386,7 @@
   /*
    * Try to load the response from cdrom into buffer.
    */
-  if( ( inb( SJCDPORT( 1 ) ) & 0x0B ) == 0x09 ){
+  if( SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ){
     sjcd_load_status();
     return( 1 );
   } else {
@@ -371,31 +397,55 @@
   }
 }
 
+/*
+ * This is just timout counter, and nothing more. Surprized ? :-)
+ */
 static volatile long sjcd_status_timeout;
+
+/*
+ * We need about 10 seconds to wait. The longest command takes about 5 seconds
+ * to probe the disk (usually after tray closed or drive reset). Other values
+ * should be thought of for other commands.
+ */
 #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
 
 static void sjcd_status_timer( void ){
   if( sjcd_check_status() ){
+    /*
+     * The command completed and status is loaded, stop waiting.
+     */
     wake_up( &sjcd_waitq );
   } else if( --sjcd_status_timeout <= 0 ){
+    /*
+     * We are timed out. 
+     */
     wake_up( &sjcd_waitq );
   } else {
-    SJCD_SET_TIMER( sjcd_status_timer, HZ/100 );
+    /*
+     * We have still some time to wait. Try again.
+     */
+    SJCD_SET_TIMER( sjcd_status_timer, 1 );
   }
 }
 
+/*
+ * Wait for status for 10 sec approx. Returns non-positive when timed out.
+ * Should not be used while reading data CDs.
+ */
 static int sjcd_wait_for_status( void ){
   sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
-  SJCD_SET_TIMER( sjcd_status_timer, HZ/100 );
+  SJCD_SET_TIMER( sjcd_status_timer, 1 ); 
   sleep_on( &sjcd_waitq );    
+#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
   if( sjcd_status_timeout <= 0 )
     printk( "sjcd: Error Wait For Status.\n" );
+#endif
   return( sjcd_status_timeout );
 }
 
 static int sjcd_receive_status( void ){
   int i;
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: receive_status\n" );
 #endif
   /*
@@ -403,7 +453,7 @@
    */
   for( i = 200; i-- && ( sjcd_check_status() == 0 ); );
   if( i < 0 ){
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: long wait for status\n" );
 #endif
     if( sjcd_wait_for_status() <= 0 )
@@ -414,10 +464,10 @@
 }
 
 /*
- * Load the status.
+ * Load the status. Issue get status command and wait for status available.
  */
 static void sjcd_get_status( void ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: get_status\n" );
 #endif
   sjcd_send_cmd( SCMD_GET_STATUS );
@@ -425,7 +475,7 @@
 }
 
 /*
- * Check the drive if the disk is changed.
+ * Check the drive if the disk is changed. Should be revised.
  */
 static int sjcd_disk_change( kdev_t full_dev ){
 #if 0
@@ -444,14 +494,14 @@
  * Read the table of contents (TOC) and TOC header if necessary.
  * We assume that the drive contains no more than 99 toc entries.
  */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[ 100 ];
+static struct sjcd_hw_disk_info sjcd_table_of_contents[ SJCD_MAX_TRACKS ];
 static unsigned char sjcd_first_track_no, sjcd_last_track_no;
 #define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
 
 static int sjcd_update_toc( void ){
   struct sjcd_hw_disk_info info;
   int i;
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: update toc:\n" );
 #endif
   /*
@@ -485,7 +535,7 @@
     printk( "get first failed\n" );
     return( -1 );
   }
-#if 0
+#if defined( SJCD_TRACE )
   printk( "TOC start 0x%02x ", sjcd_first_track_no );
 #endif
   /*
@@ -514,7 +564,7 @@
     printk( "get last failed\n" );
     return( -1 );
   }
-#if 0
+#if defined( SJCD_TRACE )
   printk( "TOC finish 0x%02x ", sjcd_last_track_no );
 #endif
   for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){
@@ -574,7 +624,7 @@
     printk( "get size failed\n" );
     return( 1 );
   }
-#if 0
+#if defined( SJCD_TRACE )
   printk( "(%02x:%02x.%02x)\n", sjcd_disk_length.min,
 	 sjcd_disk_length.sec, sjcd_disk_length.frame );
 #endif
@@ -586,7 +636,7 @@
  */
 static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){
   int s;
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: load sub q\n" );
 #endif
   sjcd_send_cmd( SCMD_GET_QINFO );
@@ -632,11 +682,46 @@
 }
 
 /*
+ * Tray control functions.
+ */
+static int sjcd_tray_close( void ){
+#if defined( SJCD_TRACE )
+  printk( "sjcd: tray_close\n" );
+#endif
+  sjcd_send_cmd( SCMD_CLOSE_TRAY );
+  return( sjcd_receive_status() );
+}
+
+static int sjcd_tray_lock( void ){
+#if defined( SJCD_TRACE )
+  printk( "sjcd: tray_lock\n" );
+#endif
+  sjcd_send_cmd( SCMD_LOCK_TRAY );
+  return( sjcd_receive_status() );
+}
+
+static int sjcd_tray_unlock( void ){
+#if defined( SJCD_TRACE )
+  printk( "sjcd: tray_unlock\n" );
+#endif
+  sjcd_send_cmd( SCMD_UNLOCK_TRAY );
+  return( sjcd_receive_status() );
+}
+
+static int sjcd_tray_open( void ){
+#if defined( SJCD_TRACE )
+  printk( "sjcd: tray_open\n" );
+#endif
+  sjcd_send_cmd( SCMD_EJECT_TRAY );
+  return( sjcd_receive_status() );
+}
+
+/*
  * Do some user commands.
  */
 static int sjcd_ioctl( struct inode *ip, struct file *fp,
 		       unsigned int cmd, unsigned long arg ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd:ioctl\n" );
 #endif
 
@@ -648,14 +733,14 @@
 
   switch( cmd ){
   case CDROMSTART:{
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: start\n" );
 #endif
     return( 0 );
   }
 
   case CDROMSTOP:{
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: stop\n" );
 #endif
     sjcd_send_cmd( SCMD_PAUSE );
@@ -666,7 +751,7 @@
 
   case CDROMPAUSE:{
     struct sjcd_hw_qinfo q_info;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: pause\n" );
 #endif
     if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
@@ -683,7 +768,7 @@
   }
 
   case CDROMRESUME:{
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: resume\n" );
 #endif
     if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){
@@ -702,11 +787,11 @@
 
   case CDROMPLAYTRKIND:{
     struct cdrom_ti ti; int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: playtrkind\n" );
 #endif
-    if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( ti ) ) ) == 0 ){
-      memcpy_fromfs( &ti, (void *) arg, sizeof( ti ) );
+    if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){
+      memcpy_fromfs( &ti, (void *)arg, sizeof( ti ) );
 
       if( ti.cdti_trk0 < sjcd_first_track_no ) return( -EINVAL );
       if( ti.cdti_trk1 > sjcd_last_track_no )
@@ -728,17 +813,17 @@
 
   case CDROMPLAYMSF:{
     struct cdrom_msf sjcd_msf; int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: playmsf\n" );
 #endif
-    if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( sjcd_msf ) ) ) == 0 ){
+    if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( sjcd_msf ) ) ) == 0 ){
       if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
 	sjcd_send_cmd( SCMD_PAUSE );
 	( void )sjcd_receive_status();
 	sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
       }
 
-      memcpy_fromfs( &sjcd_msf, ( void * )arg, sizeof( sjcd_msf ) );
+      memcpy_fromfs( &sjcd_msf, (void *)arg, sizeof( sjcd_msf ) );
 
       sjcd_playing.start.min = bin2bcd( sjcd_msf.cdmsf_min0 );
       sjcd_playing.start.sec = bin2bcd( sjcd_msf.cdmsf_sec0 );
@@ -757,26 +842,26 @@
 
   case CDROMREADTOCHDR:{
     struct cdrom_tochdr toc_header; int s;
-#if 0
+#if defined (SJCD_TRACE )
     printk( "sjcd: ioctl: readtocheader\n" );
 #endif
-    if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( toc_header ) ) ) == 0 ){
+    if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){
       toc_header.cdth_trk0 = sjcd_first_track_no;
       toc_header.cdth_trk1 = sjcd_last_track_no;
-      memcpy_tofs( ( void * )arg, &toc_header, sizeof( toc_header ) );
+      memcpy_tofs( (void *)arg, &toc_header, sizeof( toc_header ) );
     }
     return( s );
   }
 
   case CDROMREADTOCENTRY:{
     struct cdrom_tocentry toc_entry; int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: readtocentry\n" );
 #endif
-    if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( toc_entry ) ) ) == 0 ){
+    if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){
       struct sjcd_hw_disk_info *tp;
 
-      memcpy_fromfs( &toc_entry, ( void * )arg, sizeof( toc_entry ) );
+      memcpy_fromfs( &toc_entry, (void *)arg, sizeof( toc_entry ) );
 
       if( toc_entry.cdte_track == CDROM_LEADOUT )
 	tp = &sjcd_table_of_contents[ 0 ];
@@ -798,20 +883,20 @@
 	break;
       default: return( -EINVAL );
       }
-      memcpy_tofs( ( void * )arg, &toc_entry, sizeof( toc_entry ) );
+      memcpy_tofs( (void *)arg, &toc_entry, sizeof( toc_entry ) );
     }
     return( s );
   }
 
   case CDROMSUBCHNL:{
     struct cdrom_subchnl subchnl; int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: subchnl\n" );
 #endif
-    if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( subchnl ) ) ) == 0 ){
+    if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){
       struct sjcd_hw_qinfo q_info;
 
-      memcpy_fromfs( &subchnl, ( void * )arg, sizeof( subchnl ) );
+      memcpy_fromfs( &subchnl, (void *)arg, sizeof( subchnl ) );
       if( sjcd_get_q_info( &q_info ) < 0 ) return( -EIO );
 
       subchnl.cdsc_audiostatus = sjcd_audio_status;
@@ -835,20 +920,20 @@
 	break;
       default: return( -EINVAL );
       }
-      memcpy_tofs( ( void * )arg, &subchnl, sizeof( subchnl ) );
+      memcpy_tofs( (void *)arg, &subchnl, sizeof( subchnl ) );
     }
     return( s );
   }
 
   case CDROMVOLCTRL:{
     struct cdrom_volctrl vol_ctrl; int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: volctrl\n" );
 #endif
-    if( ( s = verify_area( VERIFY_READ, (void *) arg, sizeof( vol_ctrl ) ) ) == 0 ){
+    if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){
       unsigned char dummy[ 4 ];
 
-      memcpy_fromfs( &vol_ctrl, ( void * )arg, sizeof( vol_ctrl ) );
+      memcpy_fromfs( &vol_ctrl, (void *)arg, sizeof( vol_ctrl ) );
       sjcd_send_4_cmd( SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF,
 		      vol_ctrl.channel1, 0xFF );
       if( sjcd_receive_status() < 0 ) return( -EIO );
@@ -858,41 +943,34 @@
   }
 
   case CDROMEJECT:{
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: eject\n" );
 #endif
     if( !sjcd_command_is_in_progress ){
+      sjcd_tray_unlock();
       sjcd_send_cmd( SCMD_EJECT_TRAY );
       ( void )sjcd_receive_status();
     }
     return( 0 );
   }
 
+#if defined( SJCD_GATHER_STAT )
   case 0xABCD:{
     int s;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: ioctl: statistic\n" );
 #endif
-    if( ( s = verify_area( VERIFY_WRITE, (void *) arg, sizeof( statistic ) ) ) == 0 )
-      memcpy_tofs( ( void * )arg, &statistic, sizeof( statistic ) );
+    if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 )
+      memcpy_tofs( (void *)arg, &statistic, sizeof( statistic ) );
     return( s );
   }
+#endif
 
   default:
     return( -EINVAL );
   }
 }
 
-#if 0
-/*
- * We only seem to get interrupts after an error.
- * Just take the interrupt and clear out the status reg.
- */
-static void sjcd_interrupt( int irq, struct pt_regs *regs ){
-  printk( "sjcd: interrupt is cought\n" );
-}
-#endif
-
 /*
  * Invalidate internal buffers of the driver.
  */
@@ -912,7 +990,7 @@
       CURRENT->cmd == READ && CURRENT->sector != -1 )
 
 static void sjcd_transfer( void ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: transfer:\n" );
 #endif
   if( CURRENT_IS_VALID ){
@@ -931,7 +1009,7 @@
 	}
 	if( nr_sectors > CURRENT->nr_sectors )
 	  nr_sectors = CURRENT->nr_sectors;
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "copy out\n" );
 #endif
 	memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 );
@@ -944,35 +1022,41 @@
       }
     }
   }
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: transfer: done\n" );
 #endif
 }
 
 static void sjcd_poll( void ){
+#if defined( SJCD_GATHER_STAT )
   /*
    * Update total number of ticks.
    */
   statistic.ticks++;
   statistic.tticks[ sjcd_transfer_state ]++;
+#endif
 
  ReSwitch: switch( sjcd_transfer_state ){
       
   case SJCD_S_IDLE:{
+#if defined( SJCD_GATHER_STAT )
     statistic.idle_ticks++;
-#if 0
+#endif
+#if defined( SJCD_TRACE )
     printk( "SJCD_S_IDLE\n" );
 #endif
     return;
   }
 
   case SJCD_S_START:{
+#if defined( SJCD_GATHER_STAT )
     statistic.start_ticks++;
+#endif
     sjcd_send_cmd( SCMD_GET_STATUS );
     sjcd_transfer_state =
       sjcd_mode == SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
     sjcd_transfer_timeout = 500;
-#if 0
+#if defined( SJCD_TRACE )
     printk( "SJCD_S_START: goto SJCD_S_%s mode\n",
 	   sjcd_transfer_state == SJCD_S_READ ? "READ" : "MODE" );
 #endif
@@ -982,10 +1066,10 @@
   case SJCD_S_MODE:{
     if( sjcd_check_status() ){
       /*
-       * Previos command is completed.
+       * Previous command is completed.
        */
       if( !sjcd_status_valid || sjcd_command_failed ){
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
 #endif
 	sjcd_transfer_state = SJCD_S_STOP;
@@ -995,10 +1079,13 @@
       sjcd_mode = 0; /* unknown mode; should not be valid when failed */
       sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_COOKED );
       sjcd_transfer_state = SJCD_S_READ; sjcd_transfer_timeout = 1000;
-#if 0
+#if defined( SJCD_TRACE )
       printk( "SJCD_S_MODE: goto SJCD_S_READ mode\n" );
 #endif
-    } else statistic.mode_ticks++;
+    }
+#if defined( SJCD_GATHER_STAT )
+    else statistic.mode_ticks++;
+#endif
     break;
   }
 
@@ -1008,14 +1095,14 @@
        * Previos command is completed.
        */
       if( !sjcd_status_valid || sjcd_command_failed ){
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n" );
 #endif
 	sjcd_transfer_state = SJCD_S_STOP;
 	goto ReSwitch;
       }
       if( !sjcd_media_is_available ){
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n" );
 #endif
 	sjcd_transfer_state = SJCD_S_STOP;
@@ -1026,14 +1113,14 @@
 	 * We seem to come from set mode. So discard one byte of result.
 	 */
 	if( sjcd_load_response( &sjcd_mode, 1 ) != 0 ){
-#if 0
+#if defined( SJCD_TRACE )
 	  printk( "SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n" );
 #endif
 	  sjcd_transfer_state = SJCD_S_STOP;
 	  goto ReSwitch;
 	}
 	if( sjcd_mode != SCMD_MODE_COOKED ){
-#if 0
+#if defined( SJCD_TRACE )
 	  printk( "SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n" );
 #endif
 	  sjcd_transfer_state = SJCD_S_STOP;
@@ -1048,7 +1135,7 @@
 	hsg2msf( sjcd_next_bn, &msf.start );
 	msf.end.min = 0; msf.end.sec = 0;            
 	msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ;
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "---reading msf-address %x:%x:%x  %x:%x:%x\n",
 	       msf.start.min, msf.start.sec, msf.start.frame,
 	       msf.end.min,   msf.end.sec,   msf.end.frame );
@@ -1059,28 +1146,31 @@
 	sjcd_send_6_cmd( SCMD_DATA_READ, &msf );
 	sjcd_transfer_state = SJCD_S_DATA;
 	sjcd_transfer_timeout = 500;
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_READ: go to SJCD_S_DATA mode\n" );
 #endif
       } else {
-#if 0
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n" );
 #endif
 	sjcd_transfer_state = SJCD_S_STOP;
 	goto ReSwitch;
       }
-    } else statistic.read_ticks++;
+    }
+#if defined( SJCD_GATHER_STAT )
+    else statistic.read_ticks++;
+#endif
     break;
   }
 
   case SJCD_S_DATA:{
     unsigned char stat;
 
-  sjcd_s_data: stat = inb( SJCDPORT( 1 ) ) & 0x0B;
-#if 0
+  sjcd_s_data: stat = inb( SJCDPORT( 1 ) );
+#if defined( SJCD_TRACE )
     printk( "SJCD_S_DATA: status = 0x%02x\n", stat );
 #endif
-    if( stat == 0x09 ){
+    if( SJCD_STATUS_AVAILABLE( stat ) ){
       /*
        * No data is waiting for us in the drive buffer. Status of operation
        * completion is available. Read and parse it.
@@ -1088,10 +1178,14 @@
       sjcd_load_status();
 
       if( !sjcd_status_valid || sjcd_command_failed ){
+#if defined( SJCD_TRACE )
 	printk( "sjcd: read block %d failed, maybe audio disk? Giving up\n",
 	       sjcd_next_bn );
+#endif
 	if( CURRENT_IS_VALID ) end_request( 0 );
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n" );
+#endif
 	sjcd_transfer_state = SJCD_S_STOP;
 	goto ReSwitch;
       }
@@ -1102,17 +1196,19 @@
 	goto ReSwitch;
       }
 
-      sjcd_transfer_state = SJCD_S_START;
+      sjcd_transfer_state = SJCD_S_READ;
       goto ReSwitch;
-    } else if( stat == 0x0A ){
+    } else if( SJCD_DATA_AVAILABLE( stat ) ){
       /*
        * One frame is read into device buffer. We must copy it to our memory.
-       * Otherwise cdrom hangs up. Check to see if we have something to read
+       * Otherwise cdrom hangs up. Check to see if we have something to copy
        * to.
        */
       if( !CURRENT_IS_VALID && sjcd_buf_in == sjcd_buf_out ){
+#if defined( SJCD_TRACE )
 	printk( "SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n" );
 	printk( " ... all the date would be discarded\n" );
+#endif
 	sjcd_transfer_state = SJCD_S_STOP;
 	goto ReSwitch;
       }
@@ -1123,7 +1219,7 @@
        */
       sjcd_buf_bn[ sjcd_buf_in ] = -1; /* ??? */
       insb( SJCDPORT( 2 ), sjcd_buf + 2048 * sjcd_buf_in, 2048 );
-#if 0
+#if defined( SJCD_TRACE )
       printk( "SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
 	     sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
 	     sjcd_buf_bn[ sjcd_buf_in ] );
@@ -1153,16 +1249,21 @@
 	if( CURRENT_IS_VALID &&
 	   ( CURRENT->sector / 4 < sjcd_next_bn ||
 	    CURRENT->sector / 4 > sjcd_next_bn + SJCD_BUF_SIZ ) ){
-#if 0
+#if defined( SJCD_TRACE )
 	  printk( "SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n" );
 #endif
 	  sjcd_transfer_state = SJCD_S_STOP;
 	  goto ReSwitch;
 	}
       }
+      /*
+       * Now we should turn around rather than wait for while.
+       */
       goto sjcd_s_data;
-      /* sjcd_transfer_timeout = 500; */
-    } else statistic.data_ticks++;
+    }
+#if defined( SJCD_GATHER_STAT )
+    else statistic.data_ticks++;
+#endif
     break;
   }
 
@@ -1171,20 +1272,22 @@
     sjcd_send_cmd( SCMD_STOP );
     sjcd_transfer_state = SJCD_S_STOPPING;
     sjcd_transfer_timeout = 500;
+#if defined( SJCD_GATHER_STAT )
     statistic.stop_ticks++;
+#endif
     break;
   }
 
   case SJCD_S_STOPPING:{
     unsigned char stat;
     
-    stat = inb( SJCDPORT( 1 ) ) & 0x0B;
-#if 0
+    stat = inb( SJCDPORT( 1 ) );
+#if defined( SJCD_TRACE )
     printk( "SJCD_S_STOP: status = 0x%02x\n", stat );
 #endif      
-    if( stat == 0x0A ){
+    if( SJCD_DATA_AVAILABLE( stat ) ){
       int i;
-#if 0
+#if defined( SJCD_TRACE )
       printk( "SJCD_S_STOP: discard data\n" );
 #endif
       /*
@@ -1192,7 +1295,7 @@
        */
       for( i = 2048; i--; ( void )inb( SJCDPORT( 2 ) ) );
       sjcd_transfer_timeout = 500;
-    } else if( stat == 0x09 ){
+    } else if( SJCD_STATUS_AVAILABLE( stat ) ){
       sjcd_load_status();
       if( sjcd_status_valid && sjcd_media_is_changed ) {
 	sjcd_toc_uptodate = 0;
@@ -1203,7 +1306,10 @@
 	else sjcd_transfer_state = SJCD_S_START;
       } else sjcd_transfer_state = SJCD_S_IDLE;
       goto ReSwitch;
-    } else statistic.stopping_ticks++;
+    }
+#if defined( SJCD_GATHER_STAT )
+    else statistic.stopping_ticks++;
+#endif
     break;
   }
 
@@ -1218,16 +1324,17 @@
     sjcd_send_cmd( SCMD_STOP );
     sjcd_transfer_state = SJCD_S_IDLE;
     goto ReSwitch;
-  }
+    }
 
   /*
-   * Get back in some time.
+   * Get back in some time. 1 should be replaced with count variable to
+   * avoid unnecessary testings.
    */
-  SJCD_SET_TIMER( sjcd_poll, HZ/100 );
+  SJCD_SET_TIMER( sjcd_poll, 1 );
 }
 
 static void do_sjcd_request( void ){
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd: do_sjcd_request(%ld+%ld)\n",
 	 CURRENT->sector, CURRENT->nr_sectors );
 #endif
@@ -1258,7 +1365,7 @@
     }
   }
   sjcd_transfer_is_active = 0;
-#if 0
+#if defined( SJCD_TRACE )
   printk( "sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
 	 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[ sjcd_buf_in ] );
   printk( "do_sjcd_request ends\n" );
@@ -1266,7 +1373,7 @@
 }
 
 /*
- * Open the device special file. Check that a disk is in.
+ * Open the device special file. Check disk is in.
  */
 int sjcd_open( struct inode *ip, struct file *fp ){
   /*
@@ -1280,44 +1387,96 @@
   if( fp->f_mode & 2 ) return( -EROFS );
   
   if( sjcd_open_count == 0 ){
+    int s, sjcd_open_tries;
+/* We don't know that, do we? */
+/*
     sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
+*/
     sjcd_mode = 0;
+    sjcd_door_was_open = 0;
     sjcd_transfer_state = SJCD_S_IDLE;
     sjcd_invalidate_buffers();
+    sjcd_status_valid = 0;
 
     /*
      * Strict status checking.
      */
-    sjcd_get_status();
-    if( !sjcd_status_valid ){
-#if 0
-      printk( "sjcd: open: timed out when check status.\n" );
+    for( sjcd_open_tries = 4; --sjcd_open_tries; ){
+      if( !sjcd_status_valid ) sjcd_get_status();
+      if( !sjcd_status_valid ){
+#if defined( SJCD_DIAGNOSTIC )
+	printk( "sjcd: open: timed out when check status.\n" );
 #endif
-      return( -EIO );
-    } else if( !sjcd_media_is_available ){
-#if 0
-      printk("sjcd: open: no disk in drive\n");
+	return( -EIO );
+      } else if( !sjcd_media_is_available ){
+#if defined( SJCD_DIAGNOSTIC )
+	printk("sjcd: open: no disk in drive\n");
+#endif
+	if( !sjcd_door_closed ){
+	  sjcd_door_was_open = 1;
+#if defined( SJCD_TRACE )
+	  printk("sjcd: open: close the tray\n");
+#endif
+	  s = sjcd_tray_close();
+	  if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
+#if defined( SJCD_DIAGNOSTIC )
+	    printk("sjcd: open: tray close attempt failed\n");
+#endif
+	    return( -EIO );
+	  }
+	  continue;
+	} else return( -EIO );
+      }
+      break;
+    }
+    s = sjcd_tray_lock();
+    if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
+#if defined( SJCD_DIAGNOSTIC )
+      printk("sjcd: open: tray lock attempt failed\n");
 #endif
       return( -EIO );
     }
-#if 0
+#if defined( SJCD_TRACE )
     printk( "sjcd: open: done\n" );
 #endif
   }
-  return( ++sjcd_open_count, 0 );
+#ifdef MODULE
+  MOD_INC_USE_COUNT;
+#endif
+  ++sjcd_open_count;
+  return( 0 );
 }
 
 /*
  * On close, we flush all sjcd blocks from the buffer cache.
  */
 static void sjcd_release( struct inode *inode, struct file *file ){
-#if 0
+  int s;
+
+#if defined( SJCD_TRACE )
   printk( "sjcd: release\n" );
 #endif
+#ifdef MODULE
+  MOD_DEC_USE_COUNT;
+#endif
   if( --sjcd_open_count == 0 ){
     sjcd_invalidate_buffers();
     sync_dev( inode->i_rdev );
     invalidate_buffers( inode->i_rdev );
+    s = sjcd_tray_unlock();
+    if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
+#if defined( SJCD_DIAGNOSTIC )
+      printk("sjcd: release: tray unlock attempt failed.\n");
+#endif
+    }
+    if( sjcd_door_was_open ){
+      s = sjcd_tray_open();
+      if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
+#if defined( SJCD_DIAGNOSTIC )
+	printk("sjcd: release: tray unload attempt failed.\n");
+#endif
+      }
+    }
   }
 }
 
@@ -1344,6 +1503,7 @@
  * Following stuff is intended for initialization of the cdrom. It
  * first looks for presence of device. If the device is present, it
  * will be reset. Then read the version of the drive and load status.
+ * The version is two BCD-coded bytes.
  */
 static struct {
   unsigned char major, minor;
@@ -1361,20 +1521,27 @@
   else {
     u_char expected_drive;
 
-    printk( "ISP16 cdrom interface (%s optional IDE) detected.\n",
-      (isp16_type==2)?"with":"without" );
+    printk( "ISP16 cdrom interface (with OPTi 82C92%s chip) detected.\n",
+      (isp16_type==2)?"9":"8" );
+
+    printk( "ISP16 sound configuration.\n" );
+    isp16_sound_config();
 
     expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
 
-    if ( isp16_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) {
+    if ( isp16_cdi_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) {
       printk( "ISP16 cdrom interface has not been properly configured.\n" );
-      return -1;
+      return( -EIO );
     }
   }
 
+#if defined( SJCD_TRACE )
+  printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq );
+#endif  
+
   if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
     printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
-    return -1;
+    return( -EIO );
   }
   
   blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
@@ -1382,53 +1549,100 @@
   
   if( check_region( sjcd_port, 4 ) ){
     printk( "Init failed, I/O port (%X) is already in use\n",
-	   sjcd_port );
-    return -1;
+      sjcd_port );
+    return( -EIO );
   }
   
-  printk( "Sanyo CDR-H94A:" );
-
   /*
-   * Check for card.
+   * Check for card. Since we are booting now, we can't use standard
+   * wait algorithm.
    */
-  for( i = 100; i > 0; --i )
-    if( !( inb( SJCDPORT( 1 ) ) & 0x04 ) ) break;
-  if( i == 0 ){
-    printk( " No device at 0x%x found.\n", sjcd_port );
-    return -1;
-  }
-  
+  printk( "Sanyo: Resetting: " );
   sjcd_send_cmd( SCMD_RESET );
-  while( !sjcd_status_valid ) ( void )sjcd_check_status();
+  for( i = 1000; i-- > 0 && !sjcd_status_valid; ){
+    unsigned long timer;
+
+    /*
+     * Wait 10ms approx.
+     */
+    for( timer = jiffies; jiffies <= timer; );
+    if ( (i % 100) == 0 ) printk( "." );
+    ( void )sjcd_check_status();
+  }
+  if( i == 0 || sjcd_command_failed ){
+    printk( " reset failed, no drive found.\n" );
+    return( -EIO );
+  } else printk( "\n" );
 
   /*
    * Get and print out cdrom version.
    */
+  printk( "Sanyo: Getting version: " );
   sjcd_send_cmd( SCMD_GET_VERSION );
-  while( !sjcd_status_valid ) ( void )sjcd_check_status();
+  for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
+    unsigned long timer;
+
+    /*
+     * Wait 10ms approx.
+     */
+    for( timer = jiffies; jiffies <= timer; );
+    if ( (i % 100) == 0 ) printk( "." );
+    ( void )sjcd_check_status();
+  }
+  if( i == 0 || sjcd_command_failed ){
+    printk( " get version failed, no drive found.\n" );
+    return( -EIO );
+  }
 
   if( sjcd_load_response( &sjcd_version, sizeof( sjcd_version ) ) == 0 ){
-    printk( " Version %1x.%02x.", ( int )sjcd_version.major,
+    printk( " %1x.%02x\n", ( int )sjcd_version.major,
 	     ( int )sjcd_version.minor );
   } else {
-    printk( " Read version failed.\n" );
-    return -1;
+    printk( " read version failed, no drive found.\n" );
+    return( -EIO );
   }
 
   /*
    * Check and print out the tray state. (if it is needed?).
    */
   if( !sjcd_status_valid ){
+    printk( "Sanyo: Getting status: " );
     sjcd_send_cmd( SCMD_GET_STATUS );
-    while( !sjcd_status_valid ) ( void )sjcd_check_status();
+    for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
+      unsigned long timer;
+
+      /*
+       * Wait 10ms approx.
+       */
+      for( timer = jiffies; jiffies <= timer; );
+      if ( (i % 100) == 0 ) printk( "." );
+      ( void )sjcd_check_status();
+    }
+    if( i == 0 || sjcd_command_failed ){
+      printk( " get status failed, no drive found.\n" );
+      return( -EIO );
+    } else printk( "\n" );
   }
 
-  printk( " Status: port=0x%x, irq=%d\n",
-	 sjcd_port, sjcd_irq );
+  printk( "SANYO CDR-H94A: Status: port=0x%x, irq=%d, dma=%d.\n",
+	 sjcd_port, sjcd_irq, sjcd_dma );
 
   sjcd_present++;
-  return 0;
+  return( 0 );
+}
+
+#ifdef MODULE
+void cleanup_module( void ){
+  if( MOD_IN_USE ){
+    printk( "sjcd: module: in use - can not remove.\n" );
+  } else if( ( unregister_blkdev( MAJOR_NR, "sjcd" ) == -EINVAL ) ){
+    printk( "sjcd: module: can not unregister device.\n" );
+  } else {
+    release_region( sjcd_port, 4 );
+    printk( "sjcd: module: removed.\n");
+  }
 }
+#endif
 
 /*
  * -- ISP16 detection and configuration
@@ -1439,11 +1653,12 @@
  *
  *    Detect cdrom interface on ISP16 soundcard.
  *    Configure cdrom interface.
+ *    Configure sound interface.
  *
- *    Algorithm for the card with no IDE support option taken
+ *    Algorithm for the card with OPTi 82C928 taken
  *    from the CDSETUP.SYS driver for MSDOS,
  *    by OPTi Computers, version 2.03.
- *    Algorithm for the IDE supporting ISP16 as communicated
+ *    Algorithm for the card with OPTi 82C929 as communicated
  *    to me by Vadim Model and Leo Spiekman.
  *
  *    Use, modifification or redistribution of this software is
@@ -1459,22 +1674,22 @@
 isp16_detect(void)
 {
 
-  if ( !( isp16_with_ide__detect() < 0 ) )
+  if ( !( isp16_c929__detect() < 0 ) )
     return(2);
   else
-    return( isp16_no_ide__detect() );
+    return( isp16_c928__detect() );
 }
 
 static short
-isp16_no_ide__detect(void)
+isp16_c928__detect(void)
 {
   u_char ctrl;
   u_char enable_cdrom;
   u_char io;
   short i = -1;
 
-  isp16_ctrl = ISP16_NO_IDE__CTRL;
-  isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT;
+  isp16_ctrl = ISP16_C928__CTRL;
+  isp16_enable_port = ISP16_C928__ENABLE_PORT;
 
   /* read' and write' are a special read and write, respectively */
 
@@ -1483,7 +1698,7 @@
   ISP16_OUT( ISP16_CTRL_PORT, ctrl );
 
   /* read' 3,4 and 5-bit from the cdrom enable port */
-  enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38;
+  enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
 
   if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
     /* read' last 2 bits of ISP16_IO_SET_PORT */
@@ -1497,7 +1712,7 @@
         i = 1;
         enable_cdrom |= 0x28;
       }
-      ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom );
+      ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
     }
     else {  /* bits are not the same */
       ISP16_OUT( ISP16_CTRL_PORT, ctrl );
@@ -1515,13 +1730,13 @@
 }
 
 static short
-isp16_with_ide__detect(void)
+isp16_c929__detect(void)
 {
   u_char ctrl;
   u_char tmp;
 
-  isp16_ctrl = ISP16_IDE__CTRL;
-  isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT;
+  isp16_ctrl = ISP16_C929__CTRL;
+  isp16_enable_port = ISP16_C929__ENABLE_PORT;
 
   /* read' and write' are a special read and write, respectively */
 
@@ -1532,7 +1747,7 @@
   ISP16_OUT( ISP16_CTRL_PORT, 0 );
   tmp = ISP16_IN( ISP16_CTRL_PORT );
 
-  if ( tmp != 2 )  /* isp16 with ide option not detected */
+  if ( tmp != 2 )  /* isp16 with 82C929 not detected */
     return(-1);
 
   /* restore ctrl port value */
@@ -1542,7 +1757,7 @@
 }
 
 static short
-isp16_config( int base, u_char drive_type, int irq, int dma )
+isp16_cdi_config( int base, u_char drive_type, int irq, int dma )
 {
   u_char base_code;
   u_char irq_code;
@@ -1606,13 +1821,95 @@
   i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
   ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
 
-  /* enable cdrom on interface with ide support */
+  /* enable cdrom on interface with 82C929 chip */
   if ( isp16_type > 1 )
-    ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM );
+    ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
 
   /* set base address, irq and dma */
   i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
   ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
 
   return(0);
+}
+
+static void isp16_sound_config( void )
+{
+  int i;
+  u_char saved;
+
+  saved = ISP16_IN( 0xF8D ) & 0x8F;
+    
+  ISP16_OUT( 0xF8D, 0x40 );
+
+  /*
+   * Now we should wait for a while...
+   */
+  for( i = 16*1024; i--; );
+  
+  ISP16_OUT( 0xF8D, saved );
+
+  ISP16_OUT( 0xF91, 0x1B );
+
+  for( i = 5*64*1024; i != 0; i-- )
+    if( !( inb( 0x534 ) & 0x80 ) ) break;
+
+  if( i > 0 ) {
+    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0A;
+    outb( saved, 0x534 );
+
+    special_mask = ( inb( 0x535 ) >> 4 ) & 0x08;
+
+    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0C;
+    outb( saved, 0x534 );
+
+    switch( inb( 0x535 ) ) {
+      case 0x09:
+      case 0x0A:
+        special_mask |= 0x05;
+        break;
+      case 0x8A:
+        special_mask = 0x0F;
+        break;
+      default:
+        i = 0;
+    }
+  }
+  if ( i == 0 ) {
+    printk( "Strange MediaMagic, but\n" );
+  }
+  else {
+    printk( "Conf:" );
+    saved = inb( 0x534 ) & 0xE0;
+    for( i = 0; i < 16; i++ ) {
+      outb( 0x20 | ( u_char )i, 0x534 );
+      outb( defaults[i], 0x535 );
+    }
+    for ( i = 0; i < 16; i++ ) {
+      outb( 0x20 | ( u_char )i, 0x534 );
+      saved = inb( 0x535 );
+      printk( " %02X", saved );
+    }
+    printk( "\n" );
+  }
+
+  ISP16_OUT( 0xF91, 0xA0 | special_mask );
+
+  /*
+   * The following have no explaination yet.
+   */
+  ISP16_OUT( 0xF90, 0xA2 );
+  ISP16_OUT( 0xF92, 0x03 );
+
+  /*
+   * Turn general sound on and set total volume.
+   */
+  ISP16_OUT( 0xF93, 0x0A );
+
+/*
+  outb( 0x04, 0x224 );
+  saved = inb( 0x225 );
+  outb( 0x04, 0x224 );
+  outb( saved, 0x225 );
+*/
+
 }
diff -u --recursive --new-file v1.3.34/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v1.3.34/linux/drivers/block/triton.c	Tue Oct 10 18:46:32 1995
+++ linux/drivers/block/triton.c	Sat Oct 14 10:58:47 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/triton.c	Version 1.01  Aug 28, 1995
+ *  linux/drivers/block/triton.c	Version 1.02  Oct 13, 1995
  *
  *  Copyright (c) 1995  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -109,8 +109,13 @@
  * Note that the driver reverts to PIO mode for individual requests that exceed
  * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
  * 100% of all crazy scenarios here is not necessary.
+ *
+ * As it turns out, though, we must allocate a full 4KB page for this,
+ * so the two PRD tables (ide0 & ide1) will each get half of that,
+ * allowing each to have about 256 entries (8 bytes each) from this.
  */
-#define PRD_ENTRIES	128	/* max memory area count per DMA */
+#define PRD_BYTES	8
+#define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
 
 /*
  * dma_intr() is the handler for disk read/write DMA interrupts
@@ -298,6 +303,7 @@
 	int rc = 0, h;
 	unsigned short bmiba, pcicmd;
 	unsigned int timings;
+	unsigned char *dmatable = NULL;
 	extern ide_hwif_t ide_hwifs[];
 
 	/*
@@ -351,13 +357,22 @@
 		if (check_region(base, 8)) {
 			printk(" -- ERROR, PORTS ALREADY IN USE");
 		} else {
-			unsigned long *table;
 			request_region(base, 8, hwif->name);
-			hwif->dma_base  = base;
-			table = (void *) __get_dma_pages(GFP_KERNEL, 0);
-			hwif->dmatable = table;
-			outl(virt_to_bus(table), base + 4);
-			hwif->dmaproc  = &triton_dmaproc;
+			hwif->dma_base = base;
+			if (dmatable == NULL) {
+				/*
+				 * Since we know we are on a PCI bus, we could
+				 * actually use __get_free_pages() here instead
+				 * of __get_dma_pages() -- no ISA limitations.
+				 */
+				dmatable = (void *) __get_dma_pages(GFP_KERNEL, 0);
+			}
+			if (dmatable != NULL) {
+				hwif->dmatable = (unsigned long *) dmatable;
+				dmatable += (PRD_ENTRIES * PRD_BYTES);
+				outl(virt_to_bus(hwif->dmatable), base + 4);
+				hwif->dmaproc  = &triton_dmaproc;
+			}
 		}
 		printk("\n    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n",
 		 hwif->name, time, ((~time>>12)&3)+2, ((~time>>8)&3)+1);
diff -u --recursive --new-file v1.3.34/linux/drivers/char/README.scc linux/drivers/char/README.scc
--- v1.3.34/linux/drivers/char/README.scc	Sat Sep  9 15:26:51 1995
+++ linux/drivers/char/README.scc	Sat Oct 14 10:55:16 1995
@@ -1,4 +1,4 @@
-// 950824: note -- I will upload the new version 1.9 to ftp.ucsd.edu
+// 950913: note -- I will upload the new version 1.9a to ftp.ucsd.edu
 //         as soon as possible... 
 //
 // ******
@@ -7,12 +7,21 @@
 //
 // please remake /dev/sc*:
 //
-// mknod /dev/sc1 c 34 0
-// mknod /dev/sc2 c 34 1
-// mknod /dev/sc3 c 34 2
-// mknod /dev/sc4 c 34 3
+// mknod /dev/scc0 c 34 0
+// mknod /dev/scc1 c 34 1
+// mknod /dev/scc2 c 34 2
+// mknod /dev/scc3 c 34 3
 //
 // (and so on...)
+//
+// If you want to use the old device naming scheme use:
+//
+// ln -f /dev/scc0 /dev/sc1
+// ln -f /dev/scc1 /dev/sc2
+// ln -f /dev/scc2 /dev/sc3
+// ln -f /dev/scc3 /dev/sc4
+//
+// (you get the idea...)
 //
 // -dl1bke-
 
diff -u --recursive --new-file v1.3.34/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
--- v1.3.34/linux/drivers/char/atixlmouse.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/atixlmouse.c	Sat Oct 14 10:58:47 1995
@@ -26,6 +26,7 @@
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/mouse.h>
+#include <linux/random.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -89,6 +90,7 @@
 	outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */
 	buttons = inb( ATIXL_MSE_DATA_PORT);
 	if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) {
+		add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
 		mouse.latch_buttons |= buttons;
 		mouse.dx += dx;
 		mouse.dy += dy;
diff -u --recursive --new-file v1.3.34/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v1.3.34/linux/drivers/char/busmouse.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/busmouse.c	Sat Oct 14 10:58:47 1995
@@ -46,6 +46,7 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/mouse.h>
+#include <linux/random.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -78,6 +79,7 @@
 	dy |= (buttons & 0xf) << 4;
 	buttons = ((buttons >> 5) & 0x07);
 	if (dx != 0 || dy != 0 || buttons != mouse.buttons) {
+	  add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
 	  mouse.buttons = buttons;
 	  mouse.dx += dx;
 	  mouse.dy -= dy;
diff -u --recursive --new-file v1.3.34/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.3.34/linux/drivers/char/keyboard.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/keyboard.c	Sat Oct 14 10:58:47 1995
@@ -373,9 +373,7 @@
 		prev_scancode = 0;
 		goto end_kbd_intr;
 	}
-#ifdef CONFIG_RANDOM
 	add_keyboard_randomness(scancode);
-#endif
 
 	tty = ttytab[fg_console];
  	kbd = kbd_table + fg_console;
diff -u --recursive --new-file v1.3.34/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v1.3.34/linux/drivers/char/mem.c	Fri Oct 13 14:44:32 1995
+++ linux/drivers/char/mem.c	Sat Oct 14 10:58:47 1995
@@ -233,7 +233,6 @@
 #define mmap_kmem	mmap_mem
 #define zero_lseek	null_lseek
 #define write_zero	write_null
-#define write_random	write_null
 
 static struct file_operations ram_fops = {
 	memory_lseek,
@@ -324,15 +323,14 @@
 	NULL		/* no special release code */
 };
 
-#ifdef CONFIG_RANDOM
 static struct file_operations random_fops = {
 	memory_lseek,
 	read_random,
 	write_random,
-	NULL,		/* full_readdir */
-	NULL,		/* full_select */
-	NULL,		/* full_ioctl */	
-	NULL,		/* full_mmap */
+	NULL,		/* random_readdir */
+	NULL,		/* random_select */
+	random_ioctl,
+	NULL,		/* random_mmap */
 	NULL,		/* no special open code */
 	NULL		/* no special release code */
 };
@@ -341,14 +339,13 @@
 	memory_lseek,
 	read_random_unlimited,
 	write_random,
-	NULL,		/* full_readdir */
-	NULL,		/* full_select */
-	NULL,		/* full_ioctl */	
-	NULL,		/* full_mmap */
+	NULL,		/* urandom_readdir */
+	NULL,		/* urandom_select */
+	random_ioctl,
+	NULL,		/* urandom_mmap */
 	NULL,		/* no special open code */
 	NULL		/* no special release code */
 };
-#endif
 
 static int memory_open(struct inode * inode, struct file * filp)
 {
@@ -374,14 +371,12 @@
 		case 7:
 			filp->f_op = &full_fops;
 			break;
-#ifdef CONFIG_RANDOM
 		case 8:
 			filp->f_op = &random_fops;
 			break;
 		case 9:
 			filp->f_op = &urandom_fops;
 			break;
-#endif
 		default:
 			return -ENODEV;
 	}
@@ -407,9 +402,7 @@
 {
 	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
-#ifdef CONFIG_RANDOM
 	rand_initialize();
-#endif
 	tty_init();
 #ifdef CONFIG_PRINTER
 	lp_init();
diff -u --recursive --new-file v1.3.34/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v1.3.34/linux/drivers/char/msbusmouse.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/msbusmouse.c	Sat Oct 14 10:58:47 1995
@@ -48,6 +48,7 @@
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/mouse.h>
+#include <linux/random.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -77,6 +78,7 @@
 	outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT);
 
 	if (dx != 0 || dy != 0 || buttons != mouse.buttons || ((~buttons) & 0x07)) {
+		add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
 		mouse.buttons = buttons;
 		mouse.dx += dx;
 		mouse.dy += dy;
diff -u --recursive --new-file v1.3.34/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v1.3.34/linux/drivers/char/psaux.c	Tue Oct 10 18:46:33 1995
+++ linux/drivers/char/psaux.c	Sat Oct 14 10:58:47 1995
@@ -46,6 +46,7 @@
 #include <linux/timer.h>
 #include <linux/malloc.h>
 #include <linux/mouse.h>
+#include <linux/random.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -221,7 +222,7 @@
 	if ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL)
 		return;
 
-	queue->buf[head] = inb(AUX_INPUT_PORT);
+	add_mouse_randomness(queue->buf[head] = inb(AUX_INPUT_PORT));
 	if (head != maxhead) {
 		head++;
 		head &= AUX_BUF_SIZE-1;
@@ -244,7 +245,7 @@
 	int head = queue->head;
 	int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
 
-	queue->buf[head] = inb(qp_data);
+	add_mouse_randomness(queue->buf[head] = inb(qp_data));
 	if (head != maxhead) {
 		head++;
 		head &= AUX_BUF_SIZE-1;
diff -u --recursive --new-file v1.3.34/linux/drivers/char/random.c linux/drivers/char/random.c
--- v1.3.34/linux/drivers/char/random.c	Wed Oct  4 14:14:30 1995
+++ linux/drivers/char/random.c	Sat Oct 14 10:58:47 1995
@@ -1,7 +1,7 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 0.92, last modified 21-Sep-95
+ * Version 0.94, last modified 11-Oct-95
  * 
  * Copyright Theodore Ts'o, 1994, 1995.  All rights reserved.
  *
@@ -65,34 +65,33 @@
  * timings, inter-interrupt timings from some interrupts, and other
  * events which are both (a) non-deterministic and (b) hard for an
  * outside observer to measure.  Randomness from these sources are
- * added to an "entropy pool", which is periodically mixed using the
- * MD5 compression function in CBC mode.  As random bytes are mixed
- * into the entropy pool, the routines keep an *estimate* of how many
- * bits of randomness have been stored into the random number
- * generator's internal state.
+ * added to an "entropy pool", which is mixed using a CRC-like function.
+ * This is not cryptographically strong, but it is adequate assuming
+ * the randomness is not chosen maliciously, and it is fast enough that
+ * the overhead of doing it on every interrupt is very reasonable.
+ * As random bytes are mixed into the entropy pool, the routines keep
+ * an *estimate* of how many bits of randomness have been stored into
+ * the random number generator's internal state.
  * 
  * When random bytes are desired, they are obtained by taking the MD5
- * hash of a counter plus the contents of the "entropy pool".  The
- * reason for the MD5 hash is so that we can avoid exposing the
- * internal state of random number generator.  Although the MD5 hash
- * does protect the pool, as each random byte which is generated from
- * the pool reveals some information which was derived from the
- * internal state, and thus increasing the amount of information an
- * outside attacker has available to try to make some guesses about
- * the random number generator's internal state.  For this reason,
- * the routine decreases its internal estimate of how many bits of
- * "true randomness" are contained in the entropy pool as it outputs
- * random numbers.
- * 
- * If this estimate goes to zero, the routine can still generate random
- * numbers; however it may now be possible for an attacker to analyze
- * the output of the random number generator, and the MD5 algorithm,
- * and thus have some success in guessing the output of the routine.
- * Phil Karn (who devised this mechanism of using MD5 plus a counter
- * to extract random numbers from an entropy pool) calls this
- * "practical randomness", since in the worse case this is equivalent
- * to hashing MD5 with a counter and an undisclosed secret.  If MD5 is
- * a strong cryptographic hash, this should be fairly resistant to attack.
+ * hash of the contents of the "entropy pool".  The MD5 hash avoids
+ * exposing the internal state of the entropy pool.  It is believed to
+ * be computationally infeasible to derive any useful information
+ * about the input of MD5 from its output.  Even if it is possible to
+ * analyze MD5 in some clever way, as long as the amount of data
+ * returned from the generator is less than the inherent entropy in
+ * the pool, the output data is totally unpredictable.  For this
+ * reason, the routine decreases its internal estimate of how many
+ * bits of "true randomness" are contained in the entropy pool as it
+ * outputs random numbers.
+ * 
+ * If this estimate goes to zero, the routine can still generate
+ * random numbers; however, an attacker may (at least in theory) be
+ * able to infer the future output of the generator from prior
+ * outputs.  This requires successful cryptanalysis of MD5, which is
+ * not believed to be feasible, but there is a remote possiblility.
+ * Nonetheless, these numbers should be useful for the vast majority
+ * of purposes.
  * 
  * Exported interfaces ---- output
  * ===============================
@@ -107,47 +106,61 @@
  * 
  * The two other interfaces are two character devices /dev/random and
  * /dev/urandom.  /dev/random is suitable for use when very high
- * quality randomness is desired (for example, for key generation.),
- * as it will only return a maximum of the number of bits of
- * randomness (as estimated by the random number generator) contained
- * in the entropy pool.
+ * quality randomness is desired (for example, for key generation or
+ * one-time pads), as it will only return a maximum of the number of
+ * bits of randomness (as estimated by the random number generator)
+ * contained in the entropy pool.
  * 
  * The /dev/urandom device does not have this limit, and will return
  * as many bytes as are requested.  As more and more random bytes are
  * requested without giving time for the entropy pool to recharge,
- * this will result in lower quality random numbers.  For many
- * applications, however, this is acceptable.
+ * this will result in random numbers that are merely cryptographically
+ * strong.  For many applications, however, this is acceptable.
  *
  * Exported interfaces ---- input
  * ==============================
- *
- * The two current exported interfaces for gathering environmental
- * noise from the devices are:
+ * 
+ * The current exported interfaces for gathering environmental noise
+ * from the devices are:
  * 
  * 	void add_keyboard_randomness(unsigned char scancode);
+ * 	void add_mouse_randomness(__u32 mouse_data);
  * 	void add_interrupt_randomness(int irq);
+ * 	void add_blkdev_randomness(int irq);
  * 
- * The first function uses the inter-keypress timing, as well as the
+ * add_keyboard_randomness() uses the inter-keypress timing, as well as the
  * scancode as random inputs into the "entropy pool".
+ * 
+ * add_mouse_randomness() uses the mouse interrupt timing, as well as
+ * the reported position of the mouse from the hardware.
  *
- * The second function uses the inter-interrupt timing as random
+ * add_interrupt_randomness() uses the inter-interrupt timing as random
  * inputs to the entropy pool.  Note that not all interrupts are good
  * sources of randomness!  For example, the timer interrupts is not a
  * good choice, because the periodicity of the interrupts is to
  * regular, and hence predictable to an attacker.  Disk interrupts are
  * a better measure, since the timing of the disk interrupts are more
- * unpredictable.  The routines try to estimate how many bits of
- * randomness a particular interrupt channel offers, by keeping track
- * of the first and second order deltas in the interrupt timings.
+ * unpredictable.
+ * 
+ * add_blkdev_randomness() times the finishing time of block requests.
+ * 
+ * All of these routines try to estimate how many bits of randomness a
+ * particular randomness source.  They do this by keeping track of the
+ * first and second order deltas of the event timings.
  *
  * Acknowledgements:
  * =================
- * 
+ *
  * Ideas for constructing this random number generator were derived
  * from the Pretty Good Privacy's random number generator, and from
- * private discussions with Phil Karn.  This design has been further
- * modified by myself, so any flaws are solely my responsibility, and
- * should not be attributed to the authors of PGP or to Phil.
+ * private discussions with Phil Karn.  Colin Plumb provided a faster
+ * random number generator, which speed up the mixing function of the
+ * entropy pool, taken from PGP 3.0 (under development).  It has since
+ * been modified by myself to provide better mixing in the case where
+ * the input values to add_entropy_word() are mostly small numbers.
+ * 
+ * Any flaws in the design are solely my responsibility, and should
+ * not be attributed to the Phil, Colin, or any of authors of PGP.
  * 
  * The code for MD5 transform was taken from Colin Plumb's
  * implementation, which has been placed in the public domain.  The
@@ -159,31 +172,50 @@
  * Eastlake, Steve Crocker, and Jeff Schiller.
  */
 
-#ifdef linux
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/malloc.h>
 #include <linux/random.h>
 
 #include <asm/segment.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#endif
 
-#ifdef CONFIG_RANDOM
-
-#define RANDPOOL 512
+/*
+ * The pool is stirred with a primitive polynomial of degree 128
+ * over GF(2), namely x^128 + x^119 + x^72 + x^64 + x^14 + x^8 + 1.
+ * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
+ */
+#define POOLWORDS 128    /* Power of 2 - note that this is 32-bit words */
+#define POOLBITS (POOLWORDS*32)
+#if POOLWORDS == 128
+#define TAP1    119     /* The polynomial taps */
+#define TAP2    72
+#define TAP3    64
+#define TAP4    14
+#define TAP5    8
+#elif POOLWORDS == 64
+#define TAP1    62      /* The polynomial taps */
+#define TAP2    38
+#define TAP3    10
+#define TAP4    6
+#define TAP5    1
+#else
+#error No primitive polynomial available for chosen POOLWORDS
+#endif
 
+/* There is actually only one of these, globally. */
 struct random_bucket {
-	int add_ptr;
-	int entropy_count;
-	int length;
-	int bit_length;
-	int delay_mix:1;
-	__u8 *pool;
+	unsigned add_ptr;
+	unsigned entropy_count;
+	int input_rotate;
+	__u32 *pool;
 };
 
+/* There is one of these per entropy source */
 struct timer_rand_state {
 	unsigned long	last_time;
 	int 		last_delta;
@@ -191,34 +223,206 @@
 };
 
 static struct random_bucket random_state;
-static __u32 rand_pool_key[16];
-static __u8 random_pool[RANDPOOL];
-static __u32 random_counter[16];
+static __u32 random_pool[POOLWORDS];
 static struct timer_rand_state keyboard_timer_state;
-static struct timer_rand_state irq_timer_state[NR_IRQS];
+static struct timer_rand_state mouse_timer_state;
+static struct timer_rand_state extract_timer_state;
+static struct timer_rand_state *irq_timer_state[NR_IRQS];
+static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV];
+static struct wait_queue *random_wait;
 
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 	
-static void flush_random(struct random_bucket *random_state)
+void rand_initialize(void)
+{
+	random_state.add_ptr = 0;
+	random_state.entropy_count = 0;
+	random_state.pool = random_pool;
+	memset(irq_timer_state, 0, sizeof(irq_timer_state));
+	memset(blkdev_timer_state, 0, sizeof(blkdev_timer_state));
+	random_wait = NULL;}
+
+void rand_initialize_irq(int irq)
 {
-	random_state->add_ptr = 0;
-	random_state->bit_length = random_state->length * 8;
-	random_state->entropy_count = 0;
-	random_state->delay_mix = 0;
+	if (irq >= NR_IRQS || irq_timer_state[irq])
+		return;
+
+	/*
+	 * If kamlloc returns null, we just won't use that entropy
+	 * source.
+	 */
+	irq_timer_state[irq] = kmalloc(sizeof(struct timer_rand_state), 
+				       GFP_KERNEL);
 }
 
-void rand_initialize(void)
+void rand_initialize_blkdev(int major)
 {
-	random_state.length = RANDPOOL;
-	random_state.pool = random_pool;
-	flush_random(&random_state);
+	if (major >= MAX_BLKDEV || blkdev_timer_state[major])
+		return;
+
+	/*
+	 * If kamlloc returns null, we just won't use that entropy
+	 * source.
+	 */
+	blkdev_timer_state[major] = kmalloc(sizeof(struct timer_rand_state), 
+					    GFP_KERNEL);
+}
+
+/*
+ * This function adds a byte into the entropy "pool".  It does not
+ * update the entropy estimate.  The caller must do this if appropriate.
+ *
+ * The pool is stirred with a primitive polynomial of degree 128
+ * over GF(2), namely x^128 + x^119 + x^72 + x^64 + x^14 + x^8 + 1.
+ * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
+ * 
+ * We rotate the input word by a changing number of bits, to help
+ * assure that all bits in the entropy get toggled.  Otherwise, if we
+ * consistently feed the entropy pool small numbers (like jiffies and
+ * scancodes, for example), the upper bits of the entropy pool don't
+ * get affected. --- TYT, 10/11/95
+ */
+static inline void add_entropy_word(struct random_bucket *r,
+				    const __u32 input)
+{
+	unsigned i;
+	__u32 w;
+
+	w = (input << r->input_rotate) | (input >> (32 - r->input_rotate));
+	i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1);
+	if (i)
+		r->input_rotate = (r->input_rotate + 7) & 31;
+	else
+		/*
+		 * At the beginning of the pool, add an extra 7 bits
+		 * rotation, so that successive passes spread the
+		 * input bits across the pool evenly.
+		 */
+		r->input_rotate = (r->input_rotate + 14) & 31;
+
+	/* XOR in the various taps */
+	w ^= r->pool[(i+TAP1)&(POOLWORDS-1)];
+	w ^= r->pool[(i+TAP2)&(POOLWORDS-1)];
+	w ^= r->pool[(i+TAP3)&(POOLWORDS-1)];
+	w ^= r->pool[(i+TAP4)&(POOLWORDS-1)];
+	w ^= r->pool[(i+TAP5)&(POOLWORDS-1)];
+	w ^= r->pool[i];
+	/* Rotate w left 1 bit (stolen from SHA) and store */
+	r->pool[i] = (w << 1) | (w >> 31);
+}
+
+/*
+ * This function adds entropy to the entropy "pool" by using timing
+ * delays.  It uses the timer_rand_state structure to make an estimate
+ * of how many bits of entropy this call has added to the pool.
+ *
+ * The number "num" is also added to the pool - it should somehow describe
+ * the type of event which just happened.  This is currently 0-255 for
+ * keyboard scan codes, and 256 upwards for interrupts.
+ * On the i386, this is assumed to be at most 16 bits, and the high bits
+ * are used for a high-resolution timer.
+ *
+ * TODO: Read the time stamp register on the Pentium.
+ */
+static void add_timer_randomness(struct random_bucket *r,
+				 struct timer_rand_state *state, unsigned num)
+{
+	int	delta, delta2;
+	unsigned	nbits;
+	__u32		time;
+
+#if defined (__i386__)
+	if (x86_capability & 16) {
+		unsigned long low, high;
+		__asm__(".byte 0x0f,0x31"
+			:"=a" (low), "=d" (high));
+		time = (__u32) low;
+		num ^= (__u32) high;
+	} else {
+#if 0
+		/*
+		 * On a 386, read the high resolution timer.  We assume that
+		 * this gives us 2 bits of randomness.
+		 *
+		 * This is turned off for now because of the speed hit
+		 * it entails.
+		 */ 
+		outb_p(0x00, 0x43);	/* latch the count ASAP */
+		num |= inb_p(0x40) << 16;
+		num |= inb(0x40) << 24;
+		r->entropy_count += 2;
+#endif
+		
+		time = jiffies;
+	}
+#else
+	time = jiffies;
+#endif
+
+	add_entropy_word(r, (__u32) num);
+	add_entropy_word(r, time);
+
+	/*
+	 * Calculate number of bits of randomness we probably
+	 * added.  We take into account the first and second order
+	 * deltas in order to make our estimate.
+	 */
+	delta = time - state->last_time;
+	state->last_time = time;
+
+	delta2 = delta - state->last_delta;
+	state->last_delta = delta;
+
+	if (delta < 0) delta = -delta;
+	if (delta2 < 0) delta2 = -delta2;
+	delta = MIN(delta, delta2) >> 1;
+	for (nbits = 0; delta; nbits++)
+		delta >>= 1;
+
+	r->entropy_count += nbits;
+	
+	/* Prevent overflow */
+	if (r->entropy_count > POOLBITS)
+		r->entropy_count = POOLBITS;
+	
+	wake_up_interruptible(&random_wait);	
+}
+
+void add_keyboard_randomness(unsigned char scancode)
+{
+	add_timer_randomness(&random_state, &keyboard_timer_state, scancode);
+}
+
+void add_mouse_randomness(__u32 mouse_data)
+{
+	add_timer_randomness(&random_state, &mouse_timer_state, mouse_data);
+}
+
+void add_interrupt_randomness(int irq)
+{
+	if (irq >= NR_IRQS || irq_timer_state[irq] == 0)
+		return;
+
+	add_timer_randomness(&random_state, irq_timer_state[irq], 0x100+irq);
+}
+
+void add_blkdev_randomness(int major)
+{
+	if (major >= MAX_BLKDEV || blkdev_timer_state[major] == 0)
+		return;
+
+	add_timer_randomness(&random_state, blkdev_timer_state[major],
+			     0x200+major);
 }
 
 /*
  * MD5 transform algorithm, taken from code written by Colin Plumb,
  * and put into the public domain
+ *
+ * QUESTION: Replace this with SHA, which as generally received better
+ * reviews from the cryptographic community?
  */
 
 /* The four core functions - F1 is optimized somewhat */
@@ -328,141 +532,10 @@
 #undef F4
 #undef MD5STEP
 
-/*
- * The function signature should be take a struct random_bucket * as
- * input, but this makes tqueue unhappy.
- */
-static void mix_bucket(void *v)
-{
-	struct random_bucket *r = (struct random_bucket *) v;
-	int	i, num_passes;
-	__u32 *p;
-	__u32 iv[4];
-
-	r->delay_mix = 0;
-	
-	/* Start IV from last block of the random pool */
-	memcpy(iv, r->pool + r->length - sizeof(iv), sizeof(iv));
-
-	num_passes = r->length / 16;
-	for (i = 0, p = (__u32 *) r->pool; i < num_passes; i++) {
-		MD5Transform(iv, rand_pool_key);
-		iv[0] = (*p++ ^= iv[0]);
-		iv[1] = (*p++ ^= iv[1]);
-		iv[2] = (*p++ ^= iv[2]);
-		iv[3] = (*p++ ^= iv[3]);
-	}
-	memcpy(rand_pool_key, r->pool, sizeof(rand_pool_key));
-	
-	/* Wipe iv from memory */
-	memset(iv, 0, sizeof(iv));
-
-	r->add_ptr = 0;
-}
-
-/*
- * This function adds a byte into the entropy "pool".  It does not
- * update the entropy estimate.  The caller must do this if appropriate.
- */
-static inline void add_entropy_byte(struct random_bucket *r,
-				    const __u8 ch,
-				    int delay)
-{
-	if (!delay && r->delay_mix)
-		mix_bucket(r);
-	r->pool[r->add_ptr++] ^= ch;
-	if (r->add_ptr >= r->length) {
-		if (delay) {
-			r->delay_mix = 1;
-			r->add_ptr = 0;
-		} else
-			mix_bucket(r);
-	}
-}
 
-/*
- * This function adds some number of bytes into the entropy pool and
- * updates the entropy count as appropriate.
- */
-void add_entropy(struct random_bucket *r, const __u8 *ptr,
-		 int length, int entropy_level, int delay)
-{
-	while (length-- > 0)
-		add_entropy_byte(r, *ptr++, delay);
-		
-	r->entropy_count += entropy_level;
-	if (r->entropy_count > r->length*8)
-		r->entropy_count = r->length * 8;
-}
-
-/*
- * This function adds entropy to the entropy "pool" by using timing
- * delays.  It uses the timer_rand_state structure to make an estimate
- * of how many bits of entropy this call has added to the pool.
- */
-static void add_timer_randomness(struct random_bucket *r,
-				 struct timer_rand_state *state, int delay)
-{
-	int	delta, delta2;
-	int	nbits;
-
-	/*
-	 * Calculate number of bits of randomness we probably
-	 * added.  We take into account the first and second order
-	 * delta's in order to make our estimate.
-	 */
-	delta = jiffies - state->last_time;
-	delta2 = delta - state->last_delta;
-	state->last_time = jiffies;
-	state->last_delta = delta;
-	if (delta < 0) delta = -delta;
-	if (delta2 < 0) delta2 = -delta2;
-	delta = MIN(delta, delta2) >> 1;
-	for (nbits = 0; delta; nbits++)
-		delta >>= 1;
-	
-	add_entropy(r, (__u8 *) &jiffies, sizeof(jiffies),
-		    nbits, delay);
-
-#if defined (__i386__)
-	/*
-	 * On a Pentium, read the cycle counter. We assume that
-	 * this gives us 8 bits of randomness.  XXX This needs
-	 * investigation.
-	 */
-	if (x86_capability & 16) {
-		unsigned long low, high;
-		__asm__(".byte 0x0f,0x31"
-			:"=a" (low), "=d" (high));
-		add_entropy_byte(r, low, 1);
-		r->entropy_count += 8;
-		if (r->entropy_count > r->bit_length)
-			r->entropy_count = r->bit_length;
-	}
+#if POOLWORDS % 16
+#error extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
 #endif
-}
-
-void add_keyboard_randomness(unsigned char scancode)
-{
-	struct random_bucket *r = &random_state;
-
-	add_timer_randomness(r, &keyboard_timer_state, 0);
-	add_entropy_byte(r, scancode, 0);
-	r->entropy_count += 6;
-	if (r->entropy_count > r->bit_length)
-		r->entropy_count = r->bit_length;
-}
-
-void add_interrupt_randomness(int irq)
-{
-	struct random_bucket *r = &random_state;
-
-	if (irq >= NR_IRQS)
-		return;
-
-	add_timer_randomness(r, &irq_timer_state[irq], 1);
-}
-
 /*
  * This function extracts randomness from the "entropy pool", and
  * returns it in a buffer.  This function computes how many remaining
@@ -472,41 +545,57 @@
 static inline int extract_entropy(struct random_bucket *r, char * buf,
 				  int nbytes, int to_user)
 {
-	int length, ret, passes, i;
+	int ret, i;
 	__u32 tmp[4];
-	u8 *cp;
 	
-	add_entropy(r, (u8 *) &jiffies, sizeof(jiffies), 0, 0);
+	add_timer_randomness(r, &extract_timer_state, nbytes);
 	
-	if (r->entropy_count > r->bit_length) 
-		r->entropy_count = r->bit_length;
+	/* Redundant, but just in case... */
+	if (r->entropy_count > POOLBITS) 
+		r->entropy_count = POOLBITS;
+	/* Why is this here?  Left in from Ted Ts'o.  Perhaps to limit time. */
 	if (nbytes > 32768)
 		nbytes = 32768;
+
 	ret = nbytes;
-	r->entropy_count -= ret * 8;
-	if (r->entropy_count < 0)
+	if (r->entropy_count / 8 >= nbytes)
+		r->entropy_count -= nbytes*8;
+	else
 		r->entropy_count = 0;
-	passes = r->length / 64;
+
 	while (nbytes) {
-		length = MIN(nbytes, 16);
-		for (i=0; i < 16; i++) {
-			if (++random_counter[i] != 0)
-				break;
-		}
+		/* Hash the pool to get the output */
 		tmp[0] = 0x67452301;
 		tmp[1] = 0xefcdab89;
 		tmp[2] = 0x98badcfe;
 		tmp[3] = 0x10325476;
-		MD5Transform(tmp, random_counter);
-		for (i = 0, cp = r->pool; i < passes; i++, cp+=64)
-			MD5Transform(tmp, (__u32 *) cp);
+		for (i = 0; i < POOLWORDS; i += 16)
+			MD5Transform(tmp, r->pool+i);
+		/* Modify pool so next hash will produce different results */
+		add_entropy_word(r, tmp[0]);
+		add_entropy_word(r, tmp[1]);
+		add_entropy_word(r, tmp[2]);
+		add_entropy_word(r, tmp[3]);
+		/*
+		 * Run the MD5 Transform one more time, since we want
+		 * to add at least minimal obscuring of the inputs to
+		 * add_entropy_word().  --- TYT
+		 */
+		MD5Transform(tmp, r->pool);
+		
+		/* Copy data to destination buffer */
+		i = MIN(nbytes, 16);
 		if (to_user)
-			memcpy_tofs(buf, tmp, length);
+			memcpy_tofs(buf, (__u8 const *)tmp, i);
 		else
-			memcpy(buf, tmp, length);
-		nbytes -= length;
-		buf += length;
+			memcpy(buf, (__u8 const *)tmp, i);
+		nbytes -= i;
+		buf += i;
 	}
+
+	/* Wipe data from memory */
+	memset(tmp, 0, sizeof(tmp));
+	
 	return ret;
 }
 
@@ -520,20 +609,73 @@
 	extract_entropy(&random_state, (char *) buf, nbytes, 0);
 }
 
-#ifdef linux
-int read_random(struct inode * inode,struct file * file,char * buf,int nbytes)
+int read_random(struct inode * inode, struct file * file,
+                char * buf, int nbytes)
 {
-	if ((nbytes * 8) > random_state.entropy_count)
+	if (nbytes > random_state.entropy_count / 8)
 		nbytes = random_state.entropy_count / 8;
 	
 	return extract_entropy(&random_state, buf, nbytes, 1);
 }
 
-int read_random_unlimited(struct inode * inode,struct file * file,
-			  char * buf,int nbytes)
+int read_random_unlimited(struct inode * inode, struct file * file,
+			  char * buf, int nbytes)
 {
 	return extract_entropy(&random_state, buf, nbytes, 1);
 }
-#endif
 
-#endif /* CONFIG_RANDOM */
+int write_random(struct inode * inode, struct file * file,
+		 const char * buffer, int count)
+{
+	int i;
+	__u32 word, *p;
+
+	for (i = count, p = (__u32 *)buffer;
+	     i >= sizeof(__u32);
+	     i-= sizeof(__u32), p++) {
+		memcpy_fromfs(&word, p, sizeof(__u32));
+		add_entropy_word(&random_state, word);
+	}
+	if (i) {
+		word = 0;
+		memcpy_fromfs(&word, p, i);
+		add_entropy_word(&random_state, word);
+	}
+	inode->i_mtime = CURRENT_TIME;
+	return count;
+}
+
+int random_ioctl(struct inode * inode, struct file * file,
+			unsigned int cmd, unsigned long arg)
+{
+	int *p, max_size;
+	
+	switch (cmd) {
+	case RNDGETENTCNT:
+		put_user(random_state.entropy_count, (int *) arg);
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!suser())
+			return -EPERM;
+		random_state.entropy_count += get_user((int *) arg);
+		if (random_state.entropy_count > POOLBITS)
+			random_state.entropy_count = POOLBITS;
+		return 0;
+	case RNDGETPOOL:
+		if (!suser())
+			return -EPERM;
+		p = (int *) arg;
+		put_user(random_state.entropy_count, p);
+		max_size = get_user(++p);
+		put_user(POOLWORDS, p);
+		if (max_size < 0)
+			return -EINVAL;
+		if (max_size > POOLWORDS)
+			max_size = POOLWORDS;
+		memcpy_tofs(++p, random_state.pool,
+			    max_size*sizeof(__u32));
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
diff -u --recursive --new-file v1.3.34/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v1.3.34/linux/drivers/net/lance.c	Tue Oct 10 18:46:36 1995
+++ linux/drivers/net/lance.c	Sat Oct 14 10:28:15 1995
@@ -406,6 +406,7 @@
 
 	/* Make certain the data structures used by the LANCE are aligned and DMAble. */
 	lp = (struct lance_private *) kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL);
+	memset(lp, 0, sizeof(*lp));
 	dev->priv = lp;
 	lp->name = chipname;
 	lp->rx_buffs = (unsigned long) kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL);
diff -u --recursive --new-file v1.3.34/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v1.3.34/linux/drivers/net/ppp.c	Tue Oct 10 18:46:36 1995
+++ linux/drivers/net/ppp.c	Mon Oct 16 12:09:40 1995
@@ -3143,8 +3143,8 @@
  * Validate the tty linkage
  */
 	if (ppp->flags & SC_DEBUG)
-		printk (KERN_DEBUG "ppp_dev_xmit [%s]: skb %X\n",
-			dev->name, (int) skb);
+		printk (KERN_DEBUG "ppp_dev_xmit [%s]: skb %p\n",
+			dev->name, skb);
 /*
  * Validate the tty interface
  */
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v1.3.34/linux/drivers/scsi/aha1542.c	Mon Sep 18 14:53:55 1995
+++ linux/drivers/scsi/aha1542.c	Mon Oct 16 07:55:23 1995
@@ -1198,7 +1198,24 @@
 	 * we do this?  Try this first, and we can add that later
 	 * if it turns out to be useful.
 	 */
-	outb(SCRST, CONTROL(SCpnt->host->io_port));
+	outb(HRST | SCRST, CONTROL(SCpnt->host->io_port));
+
+	/*
+	 * Wait for the thing to settle down a bit.  Unfortunately
+	 * this is going to basically lock up the machine while we
+	 * wait for this to complete.  To be 100% correct, we need to
+	 * check for timeout, and if we are doing something like this
+	 * we are pretty desperate anyways.
+	 */
+	WAIT(STATUS(SCpnt->host->io_port), 
+	     STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
+
+	/*
+	 * We need to do this too before the 1542 can interact with
+	 * us again.
+	 */
+	setup_mailboxes(SCpnt->host->io_port, SCpnt->host);
+
 	/*
 	 * Now try and pick up the pieces.  Restart all commands
 	 * that are currently active on the bus, and reset all of
@@ -1226,6 +1243,12 @@
 	 * then report SUCCESS.
 	 */
 	return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET);
+fail:
+	printk("aha1542.c: Unable to perform hard reset.\n");
+	printk("Power cycle machine to reset\n");
+	return (SCSI_RESET_ERROR | SCSI_RESET_BUS_RESET);
+
+
       }
     else
       {
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c
--- v1.3.34/linux/drivers/scsi/eata_dma_proc.c	Wed Oct  4 14:14:32 1995
+++ linux/drivers/scsi/eata_dma_proc.c	Mon Oct 16 10:37:16 1995
@@ -181,28 +181,16 @@
 	scmd.channel = 0;
 	scmd.use_sg = 0;
 
-	/* Used for mutex if loading devices after boot */
-	scmd.request.sem = NULL;
-	scmd.request.rq_status = RQ_SCSI_BUSY;
-	
-	scsi_do_cmd (&scmd, cmnd, buff + 0x144, 0x66,  
-		     eata_scsi_done, 1 * HZ, 1);
 	/*
-	 * Wait for command to finish. Use simple wait if we are
-	 * booting, else do it right and use a mutex
+	 * Do the command and wait for it to finish.
 	 */	
-	if (current->pid == 0) {
-	    while (scmd.request.rq_status != RQ_SCSI_DONE)
-		barrier();
-	} else if (scmd.request.rq_status != RQ_SCSI_DONE) {
+	{
 	    struct semaphore sem = MUTEX_LOCKED;
-	    
+	    scmd.request.rq_status = RQ_SCSI_BUSY;
 	    scmd.request.sem = &sem;
+	    scsi_do_cmd (&scmd, cmnd, buff + 0x144, 0x66,  
+			 eata_scsi_done, 1 * HZ, 1);
 	    down(&sem);
-	    
-	    /* Hmm.. Have to ask about this one */
-	    while (scmd.request.rq_status != RQ_SCSI_DONE)
-	      schedule();
 	}
 
 	size = sprintf(buffer + len, "IRQ: %2d, %s triggered\n", cc->interrupt,
@@ -321,30 +309,18 @@
  
 	scmd.cmd_len = 10;
 
-	/* Used for mutex if loading devices after boot */
-	scmd.request.sem = NULL;
-	scmd.request.rq_status = RQ_SCSI_BUSY; /* Mark busy */
-	
-	scsi_do_cmd (&scmd, cmnd, buff2, 0x144,  
-		     eata_scsi_done, 1 * HZ, 1);
 	/*
-	 * Wait for command to finish. Use simple wait if we are
-	 * booting, else do it right and use a mutex
+	 * Do the command and wait for it to finish.
 	 */	
-	if (current->pid == 0)
-	    while (scmd.request.rq_status != RQ_SCSI_DONE)
-		barrier();
-	else if (scmd.request.rq_status != RQ_SCSI_DONE) {
+	{
 	    struct semaphore sem = MUTEX_LOCKED;
-	    
+	    scmd.request.rq_status = RQ_SCSI_BUSY;
 	    scmd.request.sem = &sem;
+	    scsi_do_cmd (&scmd, cmnd, buff2, 0x144,
+			 eata_scsi_done, 1 * HZ, 1);
 	    down(&sem);
-	    
-	    /* Hmm.. Have to ask about this one */
-	    while (scmd.request.rq_status != RQ_SCSI_DONE)
-	      schedule();
 	}
-	
+
 	swap_statistics(buff2);
 	rhcs = (hst_cmd_stat *)(buff2 + 0x2c); 
 	whcs = (hst_cmd_stat *)(buff2 + 0x8c);		 
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.34/linux/drivers/scsi/scsi.c	Fri Oct 13 14:44:33 1995
+++ linux/drivers/scsi/scsi.c	Mon Oct 16 08:57:43 1995
@@ -68,6 +68,13 @@
 static void print_inquiry(unsigned char *data);
 static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid);
 
+static unsigned char * dma_malloc_freelist = NULL;
+static int scsi_need_isa_bounce_buffers;
+static unsigned int dma_sectors = 0;
+unsigned int dma_free_sectors = 0;
+unsigned int need_isa_buffer = 0;
+static unsigned char ** dma_malloc_pages = NULL;
+
 static int time_start;
 static int time_elapsed;
 static volatile struct Scsi_Host * host_active = NULL;
@@ -102,6 +109,7 @@
 unsigned long scsi_pid = 0;
 
 static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
+static void resize_dma_pool(void);
 
 /* This variable is merely a hook so that we can debug the kernel with gdb. */
 Scsi_Cmnd * last_cmnd = NULL;
@@ -192,10 +200,8 @@
 
 /*
  * This is what was previously known as the blacklist.  The concept
- * has been expanded so that we can specify other 
- * The blacklist is used to determine which devices cannot tolerate a
- * lun probe because of buggy firmware.  Far too many for my liking,
- * which is why the default is now for there to be no lun scan. 
+ * has been expanded so that we can specify other types of things we
+ * need to be aware of.
  */
 static struct dev_info device_list[] =
 {
@@ -394,7 +400,7 @@
     if(scsi_devices) while(SDtail->next) SDtail = SDtail->next;
     
     /* Make sure we have something that is valid for DMA purposes */
-    scsi_result = ((current->pid == 0  || !shpnt->unchecked_isa_dma)
+    scsi_result = ((!dma_malloc_freelist  || !shpnt->unchecked_isa_dma)
 		   ?  &scsi_result0[0] : scsi_malloc(512));
     
     if(scsi_result == NULL) {
@@ -455,33 +461,19 @@
 		    SCpnt->lun = SDpnt->lun;
 		    SCpnt->channel = SDpnt->channel;
 
-		    /* Used for mutex if loading devices after boot */
-		    SCpnt->request.sem = NULL;
-		    SCpnt->request.rq_status = RQ_SCSI_BUSY;
-		    
-		    scsi_do_cmd (SCpnt, (void *)  scsi_cmd, 
-				 (void *) scsi_result,
-				 256,  scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
-		    
-		    /* 
-		     * Wait for command to finish. Use simple wait if we are 
-		     * booting, else do it right and use a mutex 
-		     */
-		    
-		    if (current->pid == 0)
-			while (SCpnt->request.rq_status != RQ_SCSI_DONE) 
-			    barrier();
-		    else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+		    {
+			/*
+			 * Do the actual command, and wait for it to finish
+			 */
 			struct semaphore sem = MUTEX_LOCKED;
-			
 			SCpnt->request.sem = &sem;
+			SCpnt->request.rq_status = RQ_SCSI_BUSY;
+			scsi_do_cmd (SCpnt, (void *)  scsi_cmd, 
+				     (void *) scsi_result,
+				     256,  scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
 			down(&sem);
-			
-			/* Hmm.. Have to ask about this one */
-			while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-			    schedule();
 		    }
-		    
+
 #if defined(DEBUG) || defined(DEBUG_INIT)
 		    printk("scsi: scan SCSIS id %d lun %d\n", dev, lun);
 		    printk("scsi: return code %08x\n", SCpnt->result);
@@ -515,25 +507,16 @@
 		    scsi_cmd[4] = 255;
 		    scsi_cmd[5] = 0;
 		    
-		    SCpnt->request.rq_status = RQ_SCSI_BUSY;
 		    SCpnt->cmd_len = 0;
 
-		    scsi_do_cmd (SCpnt, (void *)  scsi_cmd, 
-				 (void *) scsi_result,
-				 256,  scan_scsis_done, SCSI_TIMEOUT, 3);
-		    
-		    if (current->pid == 0)
-			while (SCpnt->request.rq_status != RQ_SCSI_DONE) 
-			    barrier();
-		    else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+		    {
 			struct semaphore sem = MUTEX_LOCKED;
-			
 			SCpnt->request.sem = &sem;
+			SCpnt->request.rq_status = RQ_SCSI_BUSY;
+			scsi_do_cmd (SCpnt, (void *)  scsi_cmd, 
+				 (void *) scsi_result,
+				 256,  scan_scsis_done, SCSI_TIMEOUT, 3);
 			down(&sem);
-			
-			/* Hmm.. Have to ask about this one */
-			while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-			  schedule();
 		    }
 		    
 		    the_result = SCpnt->result;
@@ -689,24 +672,15 @@
 				scsi_cmd[4] = 0x2a;
 				scsi_cmd[5] = 0;
 				
-				SCpnt->request.rq_status = RQ_SCSI_BUSY;
 				SCpnt->cmd_len = 0;
-				
-				scsi_do_cmd (SCpnt, (void *)  scsi_cmd,
-					     (void *) scsi_result, 0x2a,  
-					     scan_scsis_done, SCSI_TIMEOUT, 3);
-				
-				if (current->pid == 0)
-				    while (SCpnt->request.rq_status != RQ_SCSI_DONE);
-				else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+				{
 				    struct semaphore sem = MUTEX_LOCKED;
-				    
+				    SCpnt->request.rq_status = RQ_SCSI_BUSY;
 				    SCpnt->request.sem = &sem;
+				    scsi_do_cmd (SCpnt, (void *)  scsi_cmd,
+					     (void *) scsi_result, 0x2a,  
+					     scan_scsis_done, SCSI_TIMEOUT, 3);
 				    down(&sem);
-				    
-				    /* Hmm.. Have to ask about this one */
-				    while (SCpnt->request.rq_status != RQ_SCSI_DONE) 
-					schedule();
 				}
 			    }
 			    /* Add this device to the linked list at the end */
@@ -1324,38 +1298,6 @@
 #endif
 }
 
-
-
-/*
- * The scsi_done() function disables the timeout timer for the scsi host,
- * marks the host as not busy, and calls the user specified completion
- * function for that host's current command.
- */
-
-static void reset (Scsi_Cmnd * SCpnt)
-{
-#ifdef DEBUG
-    printk("scsi: reset(%d, channel %d)\n", SCpnt->host->host_no, 
-	   SCpnt->channel);
-#endif
-
-    SCpnt->flags |= (WAS_RESET | IS_RESETTING);
-    scsi_reset(SCpnt, FALSE);
-
-#ifdef DEBUG
-    printk("performing request sense\n");
-#endif
-
-#if 0  /* FIXME - remove this when done */
-    if(SCpnt->flags & NEEDS_JUMPSTART) {
-	SCpnt->flags &= ~NEEDS_JUMPSTART;
-	scsi_request_sense (SCpnt);
-    }
-#endif
-}
-
-
-
 static int check_sense (Scsi_Cmnd * SCpnt)
 {
     /* If there is no sense information, request it.  If we have already
@@ -1493,7 +1435,7 @@
 		       " failed, performing reset.\n",
 		       SCpnt->host->host_no, SCpnt->channel, SCpnt->target, 
 		       SCpnt->lun);
-		reset(SCpnt);
+		scsi_reset(SCpnt, FALSE);
 		return;
 	    }
 	    else
@@ -1594,7 +1536,7 @@
 	    case RESERVATION_CONFLICT:
 		printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
 		       " reset.\n", SCpnt->host->host_no, SCpnt->channel);
-		reset(SCpnt);
+		scsi_reset(SCpnt, FALSE);
 		return;
 #if 0
 		exit = DRIVER_SOFT | SUGGEST_ABORT;
@@ -1709,7 +1651,7 @@
 	    {
 		printk("scsi%d channel %d : resetting for second half of retries.\n",
 		       SCpnt->host->host_no, SCpnt->channel);
-		reset(SCpnt);
+		scsi_reset(SCpnt, FALSE);
 		break;
 	    }
 	    
@@ -1928,13 +1870,16 @@
      */
     SCpnt1 = host->host_queue;
     while(SCpnt1) {
-        if( SCpnt->request.rq_status != RQ_INACTIVE
-           && (SCpnt->flags & WAS_RESET) == 0 )
+	if( SCpnt1->request.rq_status != RQ_INACTIVE
+	   && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
+	{
             break;
+	}
         SCpnt1 = SCpnt1->next;
  	}
-    if( SCpnt1 == NULL )
+    if( SCpnt1 == NULL ) {
         SCpnt->host->suggest_bus_reset = TRUE;
+    }
     
     
     /*
@@ -1942,8 +1887,9 @@
      * definitely request it.  This usually occurs because a
      * BUS_DEVICE_RESET times out.
      */
-    if( bus_reset_flag )
+    if( bus_reset_flag ) {
         SCpnt->host->suggest_bus_reset = TRUE;
+    }
     
     while (1) {
 	save_flags(flags);
@@ -1970,7 +1916,7 @@
 			    !(SCpnt1->internal_timeout & IN_ABORT))
 			    scsi_abort(SCpnt1, DID_RESET, SCpnt->pid);
 #endif
-			SCpnt1->flags |= IS_RESETTING;
+			SCpnt1->flags |= (WAS_RESET | IS_RESETTING);
 		    }
 		    SCpnt1 = SCpnt1->next;
 		}
@@ -1984,6 +1930,7 @@
 		if (!host->block) host->host_busy++;
 		restore_flags(flags);
 		host->last_reset = jiffies;
+	        SCpnt->flags |= (WAS_RESET | IS_RESETTING);
 		temp = host->hostt->reset(SCpnt);
 		host->last_reset = jiffies;
 		if (!host->block) host->host_busy--;
@@ -2176,13 +2123,6 @@
     return oldto;
 }
 
-
-static unsigned char * dma_malloc_freelist = NULL;
-static int scsi_need_isa_bounce_buffers;
-static unsigned int dma_sectors = 0;
-unsigned int dma_free_sectors = 0;
-unsigned int need_isa_buffer = 0;
-static unsigned char ** dma_malloc_pages = NULL;
 #define MALLOC_PAGEBITS 12
 
 static int scsi_register_host(Scsi_Host_Template *);
@@ -2341,11 +2281,9 @@
 
 int scsi_dev_init(void)
 {
-    struct Scsi_Host * host = NULL;
     Scsi_Device * SDpnt;
     struct Scsi_Host * shpnt;
     struct Scsi_Device_Template * sdtpnt;
-    int i;
 #ifdef FOO_ON_YOU
     return;
 #endif
@@ -2391,50 +2329,13 @@
     }
     
 
-    if (scsi_devicelist)
-	dma_sectors = 16;  /* Base value we use */
-    
-    if (high_memory-1 > ISA_DMA_THRESHOLD)
-	scsi_need_isa_bounce_buffers = 1;
-    else
-	scsi_need_isa_bounce_buffers = 0;
-    
-    for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
-	host = SDpnt->host;
-	
-	if(SDpnt->type != TYPE_TAPE)
-	    dma_sectors += ((host->sg_tablesize *
-			     sizeof(struct scatterlist) + 511) >> 9) *
-				 host->cmd_per_lun;
-	
-	if(host->unchecked_isa_dma &&
-	   high_memory - 1 > ISA_DMA_THRESHOLD &&
-	   SDpnt->type != TYPE_TAPE) {
-	    dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
-		host->cmd_per_lun;
-	    need_isa_buffer++;
-	}
-    }
-    
-    dma_sectors = (dma_sectors + 15) & 0xfff0;
-    dma_free_sectors = dma_sectors;  /* This must be a multiple of 16 */
-
-    if (dma_sectors)
-    {
-	dma_malloc_freelist = (unsigned char *)
-	    scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC);
-	memset(dma_malloc_freelist, 0, dma_sectors >> 3);
-
-	dma_malloc_pages = (unsigned char **)
-	    scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC);
-	memset(dma_malloc_pages, 0, dma_sectors >> 1);
+    /*
+     * This should build the DMA pool.
+     */
+    resize_dma_pool();
 
-	for(i=0; i< dma_sectors >> 3; i++)
-	    dma_malloc_pages[i] = (unsigned char *)
-		scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
-    
-    }
-    /* OK, now we finish the initialization by doing spin-up, read
+    /*
+     * OK, now we finish the initialization by doing spin-up, read
      * capacity, etc, etc 
      */
     for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
@@ -2576,6 +2477,126 @@
 }
 #endif
 
+/*
+ * Go through the device list and recompute the most appropriate size
+ * for the dma pool.  Then grab more memory (as required).
+ */
+static void resize_dma_pool(void)
+{
+    int i;
+    struct Scsi_Host * shpnt;
+    struct Scsi_Host * host = NULL;
+    Scsi_Device * SDpnt;
+    unsigned long flags;
+    unsigned char * new_dma_malloc_freelist = NULL;
+    unsigned int new_dma_sectors = 0;
+    unsigned int new_need_isa_buffer = 0;
+    unsigned char ** new_dma_malloc_pages = NULL;
+
+    if( !scsi_devices )
+    {
+	/*
+	 * Free up the DMA pool.
+	 */
+	if( dma_free_sectors != dma_sectors )
+	    panic("SCSI DMA pool memory leak\n");
+
+	for(i=0; i < dma_sectors >> 3; i++)
+	    scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
+	if (dma_malloc_pages)
+	    scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+	dma_malloc_pages = NULL;
+	if (dma_malloc_freelist)
+	    scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+	dma_malloc_freelist = NULL;
+	dma_sectors = 0;
+	dma_free_sectors = 0;
+	return;
+    }
+    /* Next, check to see if we need to extend the DMA buffer pool */
+	
+    new_dma_sectors = 16;  /* Base value we use */
+
+    if (high_memory-1 > ISA_DMA_THRESHOLD)
+	scsi_need_isa_bounce_buffers = 1;
+    else
+	scsi_need_isa_bounce_buffers = 0;
+    
+    if (scsi_devicelist)
+	for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
+	    new_dma_sectors += 8;  /* Increment for each host */
+    
+    for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
+	host = SDpnt->host;
+	
+	if(SDpnt->type != TYPE_TAPE)
+	    new_dma_sectors += ((host->sg_tablesize *
+	                         sizeof(struct scatterlist) + 511) >> 9) *
+	                             host->cmd_per_lun;
+	
+	if(host->unchecked_isa_dma &&
+	   scsi_need_isa_bounce_buffers &&
+	   SDpnt->type != TYPE_TAPE) {
+	    new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
+	        host->cmd_per_lun;
+	    new_need_isa_buffer++;
+	}
+    }
+    
+    new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
+    
+    /*
+     * We never shrink the buffers - this leads to
+     * race conditions that I would rather not even think
+     * about right now.
+     */
+    if( new_dma_sectors < dma_sectors )
+	new_dma_sectors = dma_sectors;
+    
+    if (new_dma_sectors)
+    {
+	new_dma_malloc_freelist = (unsigned char *)
+	    scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
+	memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
+	
+	new_dma_malloc_pages = (unsigned char **)
+	    scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
+	memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
+    }
+    
+    /*
+     * If we need more buffers, expand the list.
+     */
+    if( new_dma_sectors > dma_sectors ) { 
+	for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++)
+	    new_dma_malloc_pages[i] = (unsigned char *)
+	        scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+    }
+    
+    /* When we dick with the actual DMA list, we need to 
+     * protect things 
+     */
+    save_flags(flags);
+    cli();
+    if (dma_malloc_freelist)
+    {
+	memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
+	scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+    }
+    dma_malloc_freelist = new_dma_malloc_freelist;
+    
+    if (dma_malloc_pages)
+    {
+	memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
+	scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+    }
+    
+    dma_free_sectors += new_dma_sectors - dma_sectors;
+    dma_malloc_pages = new_dma_malloc_pages;
+    dma_sectors = new_dma_sectors;
+    need_isa_buffer = new_need_isa_buffer;
+    restore_flags(flags);
+}
 
 /*
  * This entry point should be called by a loadable module if it is trying
@@ -2585,11 +2606,8 @@
 {
     int pcount;
     struct Scsi_Host * shpnt;
-    struct Scsi_Host * host = NULL;
-    unsigned long flags;
     Scsi_Device * SDpnt;
     struct Scsi_Device_Template * sdtpnt;
-    int i;
     const char * name;
     
     if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or
@@ -2653,90 +2671,12 @@
 		if(SDpnt->attached) scsi_build_commandblocks(SDpnt);
 	    }
 	
-	/* Next, check to see if we need to extend the DMA buffer pool */
-    {
-	unsigned char * new_dma_malloc_freelist = NULL;
-	unsigned int new_dma_sectors = 0;
-	unsigned int new_need_isa_buffer = 0;
-	unsigned char ** new_dma_malloc_pages = NULL;
-	
-	new_dma_sectors = 16;  /* Base value we use */
-	if (scsi_devicelist)
-	    for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
-		new_dma_sectors += 8;  /* Increment for each host */
-	
-	for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
-	    host = SDpnt->host;
-	    
-	    if(SDpnt->type != TYPE_TAPE)
-		new_dma_sectors += ((host->sg_tablesize *
-				     sizeof(struct scatterlist) + 511) >> 9) *
-					 host->cmd_per_lun;
-	    
-	    if(host->unchecked_isa_dma &&
-	       scsi_need_isa_bounce_buffers &&
-	       SDpnt->type != TYPE_TAPE) {
-		new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
-		    host->cmd_per_lun;
-		new_need_isa_buffer++;
-	    }
-	}
-	
-	new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
-	
 	/*
-	 * We never shrink the buffers - this leads to
-	 * race conditions that I would rather not even think
-	 * about right now.
-	 */
-	if( new_dma_sectors < dma_sectors )
-	    new_dma_sectors = dma_sectors;
-
-	if (new_dma_sectors)
-	{
-	    new_dma_malloc_freelist = (unsigned char *)
-		scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
-	    memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
-
-	    new_dma_malloc_pages = (unsigned char **)
-		scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
-	    memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
-	}
+	 * Now that we have all of the devices, resize the DMA pool,
+	 * as required.  */
+	resize_dma_pool();
 
-	/*
-	 * If we need more buffers, expand the list.
-	 */
-	if( new_dma_sectors > dma_sectors ) { 
-	    for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++)
-		new_dma_malloc_pages[i] = (unsigned char *)
-	      scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
-	}
-	
-	/* When we dick with the actual DMA list, we need to 
-	 * protect things 
-	 */
-	save_flags(flags);
-	cli();
-	if (dma_malloc_freelist)
-	{
-	    memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
-	    scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
-	}
-	dma_malloc_freelist = new_dma_malloc_freelist;
-	
-	if (dma_malloc_pages)
-	{
-	    memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
-	    scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
-	}
 
-	dma_free_sectors += new_dma_sectors - dma_sectors;
-	dma_malloc_pages = new_dma_malloc_pages;
-	dma_sectors = new_dma_sectors;
-	need_isa_buffer = new_need_isa_buffer;
-	restore_flags(flags);
-    }
-	
 	/* This does any final handling that is required. */
 	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
 	    if(sdtpnt->finish && sdtpnt->nr_dev)
@@ -2749,7 +2689,7 @@
 	    (scsi_init_memory_start - scsi_memory_lower_value) / 1024,
 	    (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 #endif
-    
+	
     MOD_INC_USE_COUNT;
     return 0;
 }
@@ -2869,6 +2809,14 @@
 	shpnt = sh1;
     }
     
+    /*
+     * If there are absolutely no more hosts left, it is safe
+     * to completely nuke the DMA pool.  The resize operation will
+     * do the right thing and free everything.
+     */
+    if( !scsi_devices )
+	resize_dma_pool();
+
     printk ("scsi : %d host%s.\n", next_scsi_host,
 	    (next_scsi_host == 1) ? "" : "s");
     
@@ -3165,13 +3113,8 @@
     /*
      * Free up the DMA pool.
      */
-    for(i=0; i < dma_sectors >> 3; i++)
-	scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
-    if (dma_malloc_pages)
-	scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
-    if (dma_malloc_freelist)
-	scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
-    
+    resize_dma_pool();
+
     timer_table[SCSI_TIMER].fn = NULL;
     timer_table[SCSI_TIMER].expires = 0;
     /*
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v1.3.34/linux/drivers/scsi/scsi_ioctl.c	Mon Sep 18 14:54:02 1995
+++ linux/drivers/scsi/scsi_ioctl.c	Mon Oct 16 10:23:21 1995
@@ -113,18 +113,14 @@
     Scsi_Cmnd * SCpnt;
     
     SCpnt = allocate_device(NULL, dev, 1);
-    scsi_do_cmd(SCpnt,  cmd, NULL,  0,
-		scsi_ioctl_done,  MAX_TIMEOUT,
-		MAX_RETRIES);
-    
-    if (SCpnt->request.rq_status != RQ_SCSI_DONE){
+    {
 	struct semaphore sem = MUTEX_LOCKED;
 	SCpnt->request.sem = &sem;
+	scsi_do_cmd(SCpnt,  cmd, NULL,  0,
+		    scsi_ioctl_done,  MAX_TIMEOUT,
+		    MAX_RETRIES);
 	down(&sem);
-	/* Hmm.. Have to ask about this one */
-	while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-	    schedule();
-    };
+    }
     
     if(driver_byte(SCpnt->result) != 0)
 	switch(SCpnt->sense_buffer[2] & 0xf) {
@@ -248,19 +244,14 @@
 #ifndef DEBUG_NO_CMD
     
     SCpnt = allocate_device(NULL, dev, 1);
-    
-    scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,  MAX_TIMEOUT, 
-		MAX_RETRIES);
-    
-    if (SCpnt->request.rq_status != RQ_SCSI_DONE){
+
+    {
 	struct semaphore sem = MUTEX_LOCKED;
 	SCpnt->request.sem = &sem;
+	scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,  MAX_TIMEOUT, 
+		    MAX_RETRIES);
 	down(&sem);
-	/* Hmm.. Have to ask about this one */
-	while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-	    schedule();
     }
-    
     
     /* 
      * If there was an error condition, pass the info back to the user. 
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.3.34/linux/drivers/scsi/sd.c	Wed Oct  4 14:14:32 1995
+++ linux/drivers/scsi/sd.c	Mon Oct 16 10:33:51 1995
@@ -112,6 +112,22 @@
     if(rscsi_disks[target].device->removable) {
 	check_disk_change(inode->i_rdev);
 	
+	/*
+	 * If the drive is empty, just let the open fail.
+	 */
+	if ( !rscsi_disks[target].ready ) {
+	    return -ENXIO;
+	}
+
+	/*
+	 * Similarily, if the device has the write protect tab set,
+	 * have the open fail if the user expects to be able to write
+	 * to the thing.
+	 */
+	if ( (rscsi_disks[target].write_prot) && (filp->f_mode & 2) ) { 
+	    return -EROFS;
+	}
+
 	if(!rscsi_disks[target].device->access_count)
 	    sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
     };
@@ -904,11 +920,20 @@
 		 * and we will figure it out later once the drive is
 		 * available again.  */
 	
+	rscsi_disks[target].ready = 0;
 	rscsi_disks[target].device->changed = 1;
 	return 1; /* This will force a flush, if called from
 		   * check_disk_change */
     };
     
+    /* 
+     * for removable scsi disk ( FLOPTICAL ) we have to recognise the
+     * presence of disk in the drive. This is kept in the Scsi_Disk
+     * struct and tested at open !  Daniel Roche ( dan@lectra.fr ) 
+     */
+    
+    rscsi_disks[target].ready = 1;	/* FLOPTICAL */
+
     retval = rscsi_disks[target].device->changed;
     if(!flag) rscsi_disks[target].device->changed = 0;
     return retval;
@@ -945,7 +970,7 @@
     spintime = 0;
     
     /* Spin up drives, as required.  Only do this at boot time */
-    if (current->pid == 0){
+    if (!MODULE_FLAG){
 	do{
 	    retries = 0;
 	    while(retries < 3)
@@ -953,18 +978,22 @@
 		cmd[0] = TEST_UNIT_READY;
 		cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
 		memset ((void *) &cmd[2], 0, 8);
-		SCpnt->request.rq_status = RQ_SCSI_BUSY;  /* Mark as really busy again */
 		SCpnt->cmd_len = 0;
 		SCpnt->sense_buffer[0] = 0;
 		SCpnt->sense_buffer[2] = 0;
-		
-		scsi_do_cmd (SCpnt,
-			     (void *) cmd, (void *) buffer,
-			     512, sd_init_done,  SD_TIMEOUT,
-			     MAX_RETRIES);
-		
-		while(SCpnt->request.rq_status != RQ_SCSI_DONE) barrier();
-		
+
+		{
+		    struct semaphore sem = MUTEX_LOCKED;
+		    /* Mark as really busy again */
+		    SCpnt->request.rq_status = RQ_SCSI_BUSY;
+		    SCpnt->request.sem = &sem;
+		    scsi_do_cmd (SCpnt,
+				 (void *) cmd, (void *) buffer,
+				 512, sd_init_done,  SD_TIMEOUT,
+				 MAX_RETRIES);
+		    down(&sem);
+		}
+
 		the_result = SCpnt->result;
 		retries++;
 		if(   the_result == 0
@@ -984,22 +1013,24 @@
 		    cmd[1] |= 1;  /* Return immediately */
 		    memset ((void *) &cmd[2], 0, 8);
 		    cmd[4] = 1; /* Start spin cycle */
-		    /* Mark as really busy again */
-		    SCpnt->request.rq_status = RQ_SCSI_BUSY; 
 		    SCpnt->cmd_len = 0;
 		    SCpnt->sense_buffer[0] = 0;
 		    SCpnt->sense_buffer[2] = 0;
 		    
-		    scsi_do_cmd (SCpnt,
-				 (void *) cmd, (void *) buffer,
-				 512, sd_init_done,  SD_TIMEOUT,
-				 MAX_RETRIES);
-		    
-		    while(SCpnt->request.rq_status != RQ_SCSI_DONE)
-		      barrier();
+		    {
+		    	struct semaphore sem = MUTEX_LOCKED;
+			/* Mark as really busy again */
+			SCpnt->request.rq_status = RQ_SCSI_BUSY; 
+		    	SCpnt->request.sem = &sem;
+			scsi_do_cmd (SCpnt,
+				     (void *) cmd, (void *) buffer,
+				     512, sd_init_done,  SD_TIMEOUT,
+				     MAX_RETRIES);
+			down(&sem);
+		    }
 		    
 		    spintime = jiffies;
-		};
+		}
 		
 		time1 = jiffies;
 		while(jiffies < time1 + HZ); /* Wait 1 second for next try */
@@ -1012,7 +1043,7 @@
 	    else
 		printk( "ready\n" );
 	}
-    };  /* current->pid == 0 */
+    };  /* !MODULE_FLAG */
     
     
     retries = 3;
@@ -1021,28 +1052,20 @@
 	cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
 	memset ((void *) &cmd[2], 0, 8);
 	memset ((void *) buffer, 0, 8);
-	SCpnt->request.rq_status = RQ_SCSI_BUSY;  /* Mark as really busy again */
 	SCpnt->cmd_len = 0;
 	SCpnt->sense_buffer[0] = 0;
 	SCpnt->sense_buffer[2] = 0;
-	
-	scsi_do_cmd (SCpnt,
-		     (void *) cmd, (void *) buffer,
-		     8, sd_init_done,  SD_TIMEOUT,
-		     MAX_RETRIES);
-	
-	if (current->pid == 0) {
-	    while(SCpnt->request.rq_status != RQ_SCSI_DONE)
-	      barrier();
-	} else {
-	    if (SCpnt->request.rq_status != RQ_SCSI_DONE){
-		struct semaphore sem = MUTEX_LOCKED;
-		SCpnt->request.sem = &sem;
-		down(&sem);
-		/* Hmm.. Have to ask about this one.. */
-		while (SCpnt->request.rq_status != RQ_SCSI_DONE) 
-		  schedule();
-	    }
+
+	{
+	    struct semaphore sem = MUTEX_LOCKED;
+	    /* Mark as really busy again */
+	    SCpnt->request.rq_status = RQ_SCSI_BUSY;
+	    SCpnt->request.sem = &sem;
+	    scsi_do_cmd (SCpnt,
+			 (void *) cmd, (void *) buffer,
+			 8, sd_init_done,  SD_TIMEOUT,
+			 MAX_RETRIES);
+	    down(&sem);	/* sleep until it is ready */
 	}
 	
 	the_result = SCpnt->result;
@@ -1100,6 +1123,11 @@
     }
     else
     {
+	/*
+	 * FLOPTICAL , if read_capa is ok , drive is assumed to be ready 
+	 */
+	rscsi_disks[i].ready = 1;
+
 	rscsi_disks[i].capacity = (buffer[0] << 24) |
 	    (buffer[1] << 16) |
 		(buffer[2] << 8) |
@@ -1144,6 +1172,57 @@
 	    rscsi_disks[i].capacity >>= 1;  /* Change into 512 byte sectors */
     }
     
+
+    /*
+     * Unless otherwise specified, this is not write protected.
+     */
+    rscsi_disks[i].write_prot = 0;
+    if ( rscsi_disks[i].device->removable && rscsi_disks[i].ready ) {
+	/* FLOPTICAL */
+
+	/* 
+	 *	for removable scsi disk ( FLOPTICAL ) we have to recognise  
+	 * the Write Protect Flag. This flag is kept in the Scsi_Disk struct
+	 * and tested at open !
+	 * Daniel Roche ( dan@lectra.fr )
+	 */
+	
+	memset ((void *) &cmd[0], 0, 8);
+	cmd[0] = MODE_SENSE;
+	cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+	cmd[2] = 1;	 /* page code 1 ?? */
+	cmd[4] = 12;
+	SCpnt->cmd_len = 0;
+	SCpnt->sense_buffer[0] = 0;
+	SCpnt->sense_buffer[2] = 0;
+
+	/* same code as READCAPA !! */
+	{
+	    struct semaphore sem = MUTEX_LOCKED;
+	    SCpnt->request.rq_status = RQ_SCSI_BUSY;  /* Mark as really busy again */
+	    SCpnt->request.sem = &sem;
+	    scsi_do_cmd (SCpnt,
+			 (void *) cmd, (void *) buffer,
+			 512, sd_init_done,  SD_TIMEOUT,
+			 MAX_RETRIES);
+	    down(&sem);
+	}
+	
+	the_result = SCpnt->result;
+	SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
+	wake_up(&SCpnt->device->device_wait); 
+	
+	if ( the_result ) {
+	    printk ("sd%c: test WP failed, assume Write Protected\n",i+'a');
+	    rscsi_disks[i].write_prot = 1;
+	} else {
+	    rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0);
+	    printk ("sd%c: Write Protect is %s\n",i+'a',
+	            rscsi_disks[i].write_prot ? "on" : "off");
+	}
+	
+    }	/* check for write protect */
+ 
     rscsi_disks[i].ten = 1;
     rscsi_disks[i].remap = 1;
     scsi_free(buffer, 512);
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/sd.h linux/drivers/scsi/sd.h
--- v1.3.34/linux/drivers/scsi/sd.h	Mon Sep 18 14:54:03 1995
+++ linux/drivers/scsi/sd.h	Mon Oct 16 07:55:22 1995
@@ -29,6 +29,8 @@
     unsigned capacity;		    /* size in blocks */
     unsigned sector_size;	    /* size in bytes */
     Scsi_Device	 *device;	    
+    unsigned char ready;	    /* flag ready for FLOPTICAL */
+    unsigned char write_prot;	    /* flag write_protect for rmvable dev */
     unsigned char sector_bit_size;  /* sector_size = 2 to the  bit size power */
     unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
     unsigned ten:1;		    /* support ten byte read / write */
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.3.34/linux/drivers/scsi/sr.c	Wed Sep 27 15:59:59 1995
+++ linux/drivers/scsi/sr.c	Mon Oct 16 08:36:58 1995
@@ -989,24 +989,17 @@
 	SCpnt->cmd_len = 0;
 	
 	memset(buffer, 0, 8);
-	
-	scsi_do_cmd (SCpnt,
-		     (void *) cmd, (void *) buffer,
-		     512, sr_init_done,  SR_TIMEOUT,
-		     MAX_RETRIES);
-	
-	if (current->pid == 0)
-	    while(SCpnt->request.rq_status != RQ_SCSI_DONE)
-		barrier();
-	else
-	    if (SCpnt->request.rq_status != RQ_SCSI_DONE){
-		struct semaphore sem = MUTEX_LOCKED;
-		SCpnt->request.sem = &sem;
-		down(&sem);
-		/* Hmm.. Have to ask about this */
-		while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-		    schedule();
-	    };
+
+	/* Do the command and wait.. */
+	{
+	    struct semaphore sem = MUTEX_LOCKED;
+	    SCpnt->request.sem = &sem;
+	    scsi_do_cmd (SCpnt,
+			 (void *) cmd, (void *) buffer,
+			 512, sr_init_done,  SR_TIMEOUT,
+			 MAX_RETRIES);
+	    down(&sem);
+	}
 	
 	the_result = SCpnt->result;
 	retries--;
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v1.3.34/linux/drivers/scsi/sr_ioctl.c	Wed Oct  4 14:14:32 1995
+++ linux/drivers/scsi/sr_ioctl.c	Mon Oct 16 12:38:25 1995
@@ -44,21 +44,16 @@
 {
     Scsi_Cmnd * SCpnt;
     int result;
-    
+
     SCpnt = allocate_device(NULL, scsi_CDs[target].device, 1);
-    scsi_do_cmd(SCpnt,
-		(void *) sr_cmd, buffer, buflength, sr_ioctl_done, 
-		IOCTL_TIMEOUT, IOCTL_RETRIES);
-    
-    
-    if (SCpnt->request.rq_status != RQ_SCSI_DONE){
+    {
 	struct semaphore sem = MUTEX_LOCKED;
 	SCpnt->request.sem = &sem;
+	scsi_do_cmd(SCpnt,
+		    (void *) sr_cmd, buffer, buflength, sr_ioctl_done, 
+		    IOCTL_TIMEOUT, IOCTL_RETRIES);
 	down(&sem);
-	/* Hmm.. Have to ask about this */
-	while (SCpnt->request.rq_status != RQ_SCSI_DONE)
-	  schedule();
-    };
+    }
     
     result = SCpnt->result;
     
diff -u --recursive --new-file v1.3.34/linux/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c
--- v1.3.34/linux/drivers/sound/sb_dsp.c	Fri Oct 13 14:44:43 1995
+++ linux/drivers/sound/sb_dsp.c	Sat Oct 14 10:58:47 1995
@@ -1171,6 +1171,9 @@
 		ess_minor & 0x0f);
     }
 
+   if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0)
+	  printk ("sb_dsp: Can't allocate IRQ\n");;
+
 #ifndef EXCLUDE_SBPRO
   if (sbc_major >= 3)
     mixer_type = sb_mixer_init (sbc_major);
@@ -1247,8 +1250,6 @@
 		}
 	    }
 #endif
-	if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0)
-	  printk ("sb_dsp: Can't allocate IRQ\n");;
       }
     else
       printk ("SB: Too many DSP devices available\n");
diff -u --recursive --new-file v1.3.34/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v1.3.34/linux/fs/binfmt_elf.c	Wed Oct  4 14:14:33 1995
+++ linux/fs/binfmt_elf.c	Mon Oct 16 07:55:22 1995
@@ -210,13 +210,28 @@
 	
 	elf_phdata =  (struct elf_phdr *) 
 		kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
-	if(!elf_phdata) return 0xffffffff;
+	if(!elf_phdata)
+	  return 0xffffffff;
 	
+	/*
+	 * If the size of this structure has changed, then punt, since
+	 * we will be doing the wrong thing.
+	 */
+	if( interp_elf_ex->e_phentsize != 32 )
+	  {
+	    kfree(elf_phdata);
+	    return 0xffffffff;
+	  }
+
 	retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
 	
 	elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
-	if (elf_exec_fileno < 0) return 0xffffffff;
+	if (elf_exec_fileno < 0) {
+	  kfree(elf_phdata);
+	  return 0xffffffff;
+	}
+
 	file = current->files->fd[elf_exec_fileno];
 
 	eppnt = elf_phdata;
@@ -425,8 +440,18 @@
 	
 	for(i=0;i < elf_ex.e_phnum; i++){
 		if(elf_ppnt->p_type == PT_INTERP) {
-			/* This is the program interpreter used for shared libraries - 
-			   for now assume that this is an a.out format binary */
+		  	if( elf_interpreter != NULL )
+			{
+				kfree (elf_phdata);
+				kfree(elf_interpreter);
+				MOD_DEC_USE_COUNT;
+				return -EINVAL;
+			}
+
+			/* This is the program interpreter used for
+			 * shared libraries - for now assume that this
+			 * is an a.out format binary 
+			 */
 			
 			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
 							   GFP_KERNEL);
@@ -475,12 +500,7 @@
 	/* Some simple consistency checks for the interpreter */
 	if(elf_interpreter){
 		interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
-		if(retval < 0) {
-			kfree(elf_interpreter);
-			kfree(elf_phdata);
-			MOD_DEC_USE_COUNT;
-			return -ELIBACC;
-		}
+
 		/* Now figure out which format our binary is */
 		if((N_MAGIC(interp_ex) != OMAGIC) && 
 		   (N_MAGIC(interp_ex) != ZMAGIC) &&
@@ -569,6 +589,7 @@
 		  kfree(elf_interpreter);
 			
 		  if(elf_entry == 0xffffffff) { 
+		    set_fs(old_fs);
 		    printk("Unable to load interpreter\n");
 		    kfree(elf_phdata);
 		    send_sig(SIGSEGV, current, 0);
@@ -600,7 +621,7 @@
 			if(k > start_code) start_code = k;
 			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 			if(k > elf_bss) elf_bss = k;
-			if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
+			if((elf_ppnt->p_flags | PF_W) && end_code <  k)
 				end_code = k; 
 			if(end_data < k) end_data = k; 
 			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
diff -u --recursive --new-file v1.3.34/linux/include/linux/aztcd.h linux/include/linux/aztcd.h
--- v1.3.34/linux/include/linux/aztcd.h	Sun Sep  3 12:27:02 1995
+++ linux/include/linux/aztcd.h	Sun Oct 15 20:02:23 1995
@@ -1,4 +1,4 @@
-/* $Id: aztcd.h,v 1.70 1995/08/19 16:16:45 root Exp root $
+/* $Id: aztcd.h,v 1.80 1995/10/11 19:39:18 root Exp root $
  *
  * Definitions for a AztechCD268 CD-ROM interface
  *	Copyright (C) 1994, 1995  Werner Zimmermann
@@ -57,6 +57,7 @@
 
 /*---------------------------------------------------------------------------*/
 /*-----nothing to be configured for normal applications below this line------*/
+
 
 /* Increase this if you get lots of timeouts; if you get kernel panic, replace
    STEN_LOW_WAIT by STEN_LOW in the source code */
diff -u --recursive --new-file v1.3.34/linux/include/linux/major.h linux/include/linux/major.h
--- v1.3.34/linux/include/linux/major.h	Fri Sep 15 11:13:02 1995
+++ linux/include/linux/major.h	Sat Oct 14 10:55:16 1995
@@ -39,7 +39,7 @@
  * 19 - cyclades /dev/ttyC*
  * 20 - cyclades /dev/cub*     mitsumi (mcdx) cdrom
  * 21 - scsi generic
- * 22 - Z8530 driver           ide1
+ * 22 -                        ide1
  * 23 -                        mitsumi cdrom
  * 24 -	                       sony535 cdrom
  * 25 -                        matsushita cdrom       minors 0..3
@@ -49,7 +49,7 @@
  * 29 -                        aztech/orchid/okano/wearnes cdrom
  * 32 -                        philips/lms cm206 cdrom
  * 33 -                        ide2
- * 34 -                        ide3
+ * 34 - z8530 driver           ide3
  */
 
 #define UNNAMED_MAJOR	0
@@ -79,7 +79,7 @@
 #define CYCLADESAUX_MAJOR 20
 #define MITSUMI_X_CDROM_MAJOR 20
 #define SCSI_GENERIC_MAJOR 21
-#define Z8530_MAJOR 22
+#define Z8530_MAJOR 34
 #define IDE1_MAJOR	22
 #define MITSUMI_CDROM_MAJOR 23
 #define CDU535_CDROM_MAJOR 24
diff -u --recursive --new-file v1.3.34/linux/include/linux/random.h linux/include/linux/random.h
--- v1.3.34/linux/include/linux/random.h	Wed Sep 27 16:00:00 1995
+++ linux/include/linux/random.h	Sat Oct 14 10:58:47 1995
@@ -4,33 +4,44 @@
  * Include file for the random number generator.
  */
 
-/*
- * We should always include the random number generator, since it's
- * relatively small, and it's most useful when application developers
- * can assume that all Linux systems have it.  (Ideally, it would be
- * best if we could assume that all Unix systems had it, but oh
- * well....)
- * 
- * Also, many kernel routines will have a use for good random numbers,
- * for example, for truely random TCP sequence numbers, which prevent
- * certain forms of TCP spoofing attacks.
- */
-#define CONFIG_RANDOM
+#ifndef _LINUX_RANDOM_H
+#define _LINUX_RANDOM_H
+
+/* ioctl()'s for the random number generator */
+
+#define RNDGETENTCNT	0x01080000
+#define RNDADDTOENTCNT	0x01080001
+#define RNDGETPOOL	0x01080002
+
+struct rand_pool_state {
+	int	entropy_count;
+	int	pool_size;
+	__u32	pool[0];
+};
 
 /* Exported functions */
 
-#ifdef CONFIG_RANDOM
+#ifdef __KERNEL__
+
 void rand_initialize(void);
+void rand_initialize_irq(int irq);
+void rand_initialize_blkdev(int irq);
 
 void add_keyboard_randomness(unsigned char scancode);
+void add_mouse_randomness(__u32 mouse_data);
 void add_interrupt_randomness(int irq);
+void add_blkdev_randomness(int major);
 
 void get_random_bytes(void *buf, int nbytes);
 int read_random(struct inode * inode, struct file * file,
 		char * buf, int nbytes);
 int read_random_unlimited(struct inode * inode, struct file * file,
 			  char * buf, int nbytes);
-#else
-#define add_keyboard_randomness(x)
-#define add_interrupt_randomness(x)
-#endif
+int write_random(struct inode * inode, struct file * file,
+		 const char * buffer, int count);
+int random_ioctl(struct inode * inode, struct file * file,
+		 unsigned int cmd, unsigned long arg);
+
+#endif /* __KERNEL___ */
+
+#endif /* _LINUX_RANDOM_H */
diff -u --recursive --new-file v1.3.34/linux/include/linux/rpcsock.h linux/include/linux/rpcsock.h
--- v1.3.34/linux/include/linux/rpcsock.h	Fri Oct  6 14:35:16 1995
+++ linux/include/linux/rpcsock.h	Mon Oct 16 12:10:35 1995
@@ -31,7 +31,7 @@
 	int			*buf;
 	int			len;
 	char			gotit;
-	u32			xid;
+	__u32			xid;
 };
 
 struct rpc_sock {
diff -u --recursive --new-file v1.3.34/linux/include/linux/sjcd.h linux/include/linux/sjcd.h
--- v1.3.34/linux/include/linux/sjcd.h	Tue Jul 18 16:28:59 1995
+++ linux/include/linux/sjcd.h	Mon Oct 16 15:23:25 1995
@@ -1,46 +1,76 @@
-/* -- sjcd.h
- *
- * Definitions for a Sanyo CD-ROM interface
+/*
+ * Definitions for a Sanyo CD-ROM interface.
  *
  *   Copyright (C) 1995  Vadim V. Model
+ *                                       model@cecmow.enet.dec.com
+ *                                       vadim@rbrf.msk.su
+ *                                       vadim@ipsun.ras.ru
+ *                       Eric van der Maarel
+ *                                       maarel@marin.nl
+ *
+ *  This information is based on mcd.c from M. Harriss and sjcd102.lst from
+ *  E. Moenkeberg.
  *
- *   model@cecmow.enet.dec.com
- *   vadim@rbrf.msk.su
- *   vadim@ipsun.ras.ru
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #ifndef __SJCD_H__
 #define __SJCD_H__
 
 /*
- * Change this to set the I/O port address.
+ * Change this to set the I/O port address as default. More flexibility
+ * come with setup implementation.
  */
 #define SJCD_BASE_ADDR      0x340
 
 /*
- * Change this to set the irq.
+ * Change this to set the irq as default. Really SANYO do not use interrupts
+ * at all.
  */
-#define SJCD_INTR_NR        10
+#define SJCD_INTR_NR        0
 
 /*
- * Change this to set the dma channel.
+ * Change this to set the dma as default value. really SANYO does not use
+ * direct memory access at all.
  */
-#define SJCD_DMA            0
+#define SJCD_DMA_NR         0
 
 /*
- * port access macros
+ * Macros which allow us to find out the status of the drive.
  */
-#define SJCDPORT( x )       ( sjcd_port + ( x ) )
+#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
+#define SJCD_DATA_AVAILABLE( x )   (((x)&0x01)==0)
 
-/* status bits */
+/*
+ * Port access macro. Three ports are available: S-data port (command port),
+ * status port (read only) and D-data port (read only).
+ */
+#define SJCDPORT( x )       ( sjcd_port + ( x ) )
+#define SJCD_STATUS_PORT    SJCDPORT( 1 )
+#define SJCD_S_DATA_PORT    SJCDPORT( 0 )
+#define SJCD_COMMAND_PORT   SJCDPORT( 0 )
+#define SJCD_D_DATA_PORT    SJCDPORT( 2 )
 
-#define SST_NOT_READY       0x10        /* no disk in the drive */
+/*
+ * Drive info bits. Drive info available as first (mandatory) byte of
+ * command completion status.
+ */
+#define SST_NOT_READY       0x10        /* no disk in the drive (???) */
 #define SST_MEDIA_CHANGED   0x20        /* disk is changed */
 #define SST_DOOR_OPENED     0x40        /* door is open */
 
-/* flag bits */
-
 /* commands */
 
 #define SCMD_EJECT_TRAY     0xD0        /* eject tray if not locked */
@@ -52,7 +82,7 @@
 #define SCMD_GET_STATUS     0x80
 #define SCMD_GET_VERSION    0xCC
 
-#define SCMD_DATA_READ      0xA0
+#define SCMD_DATA_READ      0xA0        /* are the same, depend on mode&args */
 #define SCMD_SEEK           0xA0
 #define SCMD_PLAY           0xA0
 
@@ -60,24 +90,32 @@
 
 #define SCMD_SET_MODE       0xC4
 #define SCMD_MODE_PLAY      0xE0
-#define SCMD_MODE_COOKED    0xF8
+#define SCMD_MODE_COOKED    (0xF8 & ~0x20)
 #define SCMD_MODE_RAW       0xF9
-#define SCMD_MODE_x20_BIT   0x20
+#define SCMD_MODE_x20_BIT   0x20        /* What is it for ? */
 
 #define SCMD_SET_VOLUME     0xAE
 #define SCMD_PAUSE          0xE0
 #define SCMD_STOP           0xE0
 
 #define SCMD_GET_DISK_INFO  0xAA
+
+/*
+ * Some standard arguments for SCMD_GET_DISK_INFO.
+ */
 #define SCMD_GET_1_TRACK    0xA0    /* get the first track information */
 #define SCMD_GET_L_TRACK    0xA1    /* get the last track information */
 #define SCMD_GET_D_SIZE     0xA2    /* get the whole disk information */
 
 /*
- * borrowed from hd.c
+ * Borrowed from hd.c. Allows to optimize multiple port read commands.
  */
 #define S_READ_DATA( port, buf, nr )      insb( port, buf, nr )
 
+/*
+ * We assume that there are no audio disks with TOC lenght more than this
+ * number (I personally have never seen disks with morethan 20 fragments).
+ */
 #define SJCD_MAX_TRACKS		100
 
 struct msf {
@@ -124,6 +162,8 @@
   struct msf      disk_time;
 };
 
+#if defined( SJCD_GATHER_STAT )
+
 struct sjcd_stat {
   int ticks;
   int tticks[ 8 ];
@@ -135,5 +175,7 @@
   int stop_ticks;
   int stopping_ticks;
 };
+
+#endif
 
 #endif
diff -u --recursive --new-file v1.3.34/linux/kernel/module.c linux/kernel/module.c
--- v1.3.34/linux/kernel/module.c	Wed Aug  9 14:55:43 1995
+++ linux/kernel/module.c	Sat Oct 14 10:58:47 1995
@@ -529,6 +529,8 @@
 		if (p - buf > 4096 - 100)
 			break;			/* avoid overflowing buffer */
 		q = mp->name;
+		if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
+			continue; /* don't list modules for kernel syms */
 		i = 20;
 		while (*q) {
 			*p++ = *q++;
diff -u --recursive --new-file v1.3.34/linux/scripts/Configure linux/scripts/Configure
--- v1.3.34/linux/scripts/Configure	Mon Sep 18 14:54:13 1995
+++ linux/scripts/Configure	Sun Oct 15 18:57:01 1995
@@ -16,6 +16,10 @@
 #
 # 030995 (storner@osiris.ping.dk) - added support for tri-state answers,
 # for selecting modules to compile.
+#
+# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for
+# use with a config.in modified for make menuconfig.
+#
 
 #
 # Make sure we're really running bash.
@@ -29,6 +33,16 @@
 # Disable filename globbing once and for all.
 # Enable function cacheing.
 set -f -h
+
+#
+# Dummy functions for use with a config.in modified for menuconf
+#
+function mainmenu_option () {
+	:
+}
+function mainmenu_name () {
+	:
+}
 
 #
 # readln reads a line into $ans.
diff -u --recursive --new-file v1.3.34/linux/scripts/Makefile linux/scripts/Makefile
--- v1.3.34/linux/scripts/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/scripts/Makefile	Sun Oct 15 19:08:04 1995
@@ -0,0 +1,28 @@
+HEADER=header.tk
+TAIL=tail.tk
+
+kconfig.tk: ../arch/${ARCH}/config.in tkparse ${HEADER} ${TAIL}
+	./tkparse < ../arch/${ARCH}/config.in  > kconfig.tmp
+	cp ${HEADER} ./kconfig.tk
+	cat kconfig.tmp >> kconfig.tk
+	rm -f kconfig.tmp
+	cat ${TAIL} >> kconfig.tk
+	chmod 755 kconfig.tk
+
+
+tkparse: tkparse.o tkcond.o tkgen.o
+	${HOSTCC} -o tkparse tkparse.o tkcond.o tkgen.o
+
+tkparse.o: tkparse.c tkparse.h
+	$(HOSTCC) $(HOSTCFLAGS) -c -o tkparse.o tkparse.c
+
+tkcond.o: tkcond.c tkparse.h
+	$(HOSTCC) $(HOSTCFLAGS) -c -o tkcond.o tkcond.c
+
+tkgen.o: tkgen.c tkparse.h
+	$(HOSTCC) $(HOSTCFLAGS) -c -o tkgen.o tkgen.c
+
+clean:
+	rm -f kconfig.tk *.o parse
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.34/linux/scripts/header.tk linux/scripts/header.tk
--- v1.3.34/linux/scripts/header.tk	Thu Jan  1 02:00:00 1970
+++ linux/scripts/header.tk	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,337 @@
+#!/usr/bin/wish -f
+
+#
+# Used to determine size of canvas inserted for booleans. It holds the
+# place where the 'm' button goes in a tristate, and keeps the look and feel
+# consistent.
+#
+set modbutton_width 0
+set modbutton_height 0
+
+
+#
+# Define some macros we will need to parse the kmenu-config.dat file.
+#
+proc mainmenu_name { text } {
+	message .header.message -width 400 -relief raised -bg grey -text "$text"
+	pack .header.label .header.message -side left -padx 15
+        wm title . "$text"
+}
+
+proc menu_option { w menu_num text } {
+	button .f0.x$menu_num -text "$text" -width 50 -command "$w .$w \"$text\""
+	pack .f0.x$menu_num -anchor w -pady 1
+}
+
+#
+# Not used at the moment, but this runs a command in a subprocess and
+# displays the result in a window with a scrollbar.
+#
+proc do_cmd { w command } {
+	catch {destroy $w}
+	toplevel $w -class Dialog
+	frame $w.tb
+	text $w.tb.text -relief raised -bd 2 -yscrollcommand "$w.tb.scroll set"
+	scrollbar $w.tb.scroll -command "$w.tb.text yview"
+	pack $w.tb.scroll -side right -fill y
+	pack $w.tb.text -side left
+
+	set oldFocus [focus]
+	frame $w.back
+	button $w.back.ok -text "OK" -activebackground green -width 20 \
+		-command "destroy $w; focus $oldFocus" -state disabled
+	button $w.back.ccl -text "Cancel" -activebackground green -width 20 \
+		-command "destroy $w; focus $oldFocus"
+	pack $w.tb -side top
+	pack $w.back.ok $w.back.ccl -side left
+	pack $w.back -side bottom -pady 10
+
+	focus $w
+	wm geometry $w +30+35	
+
+	$w.tb.text delete 1.0 end
+	set f [open |$command]
+	while {![eof $f]} {
+		$w.tb.text insert end [read $f 256]
+	}
+	close $f
+	$w.back.ok configure -state normal
+}
+
+proc load_configfile { w title func } {
+	catch {destroy $w}
+	toplevel $w -class Dialog
+	global loadfile
+	frame $w.x
+	label $w.bm -bitmap questhead
+	pack  $w.bm -pady 10 -side top -padx 10
+	label $w.x.l -text "Enter filename:" -relief raised
+	entry $w.x.x -width 35 -relief sunken -borderwidth 2 \
+		-textvariable loadfile
+	pack $w.x.l $w.x.x -anchor w -side left
+	pack $w.x -side top -pady 10
+	wm title $w "$title" 
+
+	set oldFocus [focus]
+	frame $w.f
+	button $w.f.back -text "OK" -activebackground green -width 20 \
+		-command "destroy $w; focus $oldFocus;$func .fileio"
+	button $w.f.canc -text "Cancel" -activebackground red \
+		-width 20 -command "destroy $w; focus $oldFocus"
+	pack $w.f.back $w.f.canc -side left -pady 10 -padx 45
+	pack $w.f -pady 10 -side bottom -padx 10 -anchor w
+	focus $w
+	wm geometry $w +30+35	
+}
+
+proc read_config_file { w } {
+	global loadfile
+	if { [string length $loadfile] != 0 && [file readable $loadfile] == 1 } then {
+		read_config $loadfile
+	} else {
+		catch {destroy $w}
+		toplevel $w -class Dialog
+		message $w.m -width 400 -aspect 300 -text \
+			"Unable to read file $loadfile" \
+			 -relief raised -fg black
+		label $w.bm -bitmap error
+		pack $w.bm $w.m -pady 10 -side top -padx 10
+		wm title $w "Oops" 
+
+		set oldFocus [focus]
+		frame $w.f
+		button $w.f.back -text "Bummer" -activebackground green \
+			-width 10 -command "destroy $w; focus $oldFocus"
+		pack $w.f.back -side bottom -pady 10 -anchor s
+		pack $w.f -pady 10 -side top -padx 10 -anchor s
+		focus $w
+		wm geometry $w +30+35
+	}
+}
+
+proc write_config_file  { w } {
+	global loadfile
+	if { [string length $loadfile] != 0 && [file writable $loadfile] == 1 } then {
+		writeconfig $loadfile /dev/null
+	} else {
+		catch {destroy $w}
+		toplevel $w -class Dialog
+		message $w.m -width 400 -aspect 300 -text \
+			"Unable to write file $loadfile" \
+			 -relief raised -fg black
+		label $w.bm -bitmap error
+		pack $w.bm $w.m -pady 10 -side top -padx 10
+		wm title $w "Oops" 
+
+		set oldFocus [focus]
+		frame $w.f
+		button $w.f.back -text "OK" -activebackground green \
+			-width 10 -command "destroy $w; focus $oldFocus"
+		pack $w.f.back -side bottom -pady 10 -anchor s
+		pack $w.f -pady 10 -side top -padx 10 -anchor s
+		focus $w
+		wm geometry $w +30+35
+	}
+}
+
+proc read_config { filename } {
+	set file1 [open $filename r]
+	while { [gets $file1 line] >= 0} {
+		if [regexp {([0-9A-Z_]+)=([ynm])} $line foo var value] {
+			if { $value == "y" } then { set cmd "global $var; set $var 1" }
+			if { $value == "n" } then { set cmd "global $var; set $var 0" }
+			if { $value == "m" } then { set cmd "global $var; set $var 2" }
+			eval $cmd
+		}
+		if [regexp {# ([0-9A-Z_]+) is not set} $line foo var] {
+			set cmd "global $var; set $var 0"
+			eval $cmd
+		}
+	}
+	close $file1
+}
+proc write_comment { file1 file2 text } {
+	puts $file1 "#"
+	puts $file1 "# $text"
+	puts $file1 "#"
+	puts $file2 "/*"
+	puts $file2 " * $text"
+	puts $file2 " */"
+}
+
+proc write_variable { file1 file2 varname variable dep } {
+	if { $variable == 0 } \
+		then { puts $file1 "# $varname is not set"; \
+		       puts $file2 "#undef $varname"}
+	if { $variable == 2 || ($dep == 2 && $variable == 1) } \
+		then { puts $file1 "$varname=m"; \
+		       puts $file2 "#undef $varname"  }
+	if { $variable == 1 && $dep != 2 } \
+		then { puts $file1 "$varname=y"; \
+		       puts $file2 "#define $varname 1" }
+}
+
+proc bool {w mnum line text variable default} {
+	frame $w.x$line
+	global modbutton_width
+	global modbutton_height
+	radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	radiobutton $w.x$line.n -text "n"  -variable $variable -value 0 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	canvas $w.x$line.m -width $modbutton_width -relief raised \
+		-height $modbutton_height
+	button $w.x$line.help -text "Help" -relief raised \
+		-command "dohelp .dohelp $variable"
+	pack $w.x$line.y $w.x$line.m  -anchor w -side left
+	button $w.x$line.l -text "$text" -relief raised 
+	pack $w.x$line.n $w.x$line.help $w.x$line.l -anchor w -side left
+	pack $w.x$line -anchor w
+#
+# If we don't know the size yet, update the screen and calculate the size
+# of the 'm' button by measuring the size of the 'y' button.  The buttons
+# have fixed size anyways, so it should always be correct.
+#
+	if { $modbutton_width == 0 } then {
+		update
+		set modbutton_width [winfo width $w.x$line.y]
+		set modbutton_height [winfo height $w.x$line.y]
+		$w.x$line.m configure -height $modbutton_height \
+			-width $modbutton_width
+	}
+}
+
+proc int { w mnum line text variable default } {
+	frame $w.x$line
+	button $w.x$line.help -text "Help" -relief raised \
+		-command "dohelp .dohelp $variable "
+	button $w.x$line.l -text "$text" -relief raised 
+	entry $w.x$line.x -width 15 -relief sunken -borderwidth 2 \
+		-textvariable $variable
+	pack $w.x$line.x $w.x$line.help $w.x$line.l -anchor w -side left
+	pack $w.x$line -anchor w
+}
+
+proc comment {w line text } {
+#nothing done for comments now.
+}
+
+proc do_make { w line option dir target target } {
+#nothing to do for now.
+}
+
+proc dohelp {w varname }  {
+	catch {destroy $w}
+	toplevel $w -class Dialog
+
+	set filefound 0
+	set found 0
+	if { [file readable Documentation/Configure.help] == 1} then {
+		set f [open Documentation/Configure.help r]
+		set filefound 1	
+		while {![eof $f]} {
+			gets $f line
+		        set line1 [string trim $line]
+			if { $line1 == $varname } then {
+				set found 1
+			} else {
+				if { $found == 0 } continue 
+			}
+			if { [string length $line1 ] == 0 } break
+			append message $line
+		}
+		close $f
+	}
+
+	if { $found == 0 } then {
+		if { $filefound == 0 } then {
+		message $w.m -width 400 -aspect 300 -text \
+			"No help available - unable to open file Documentation/Configure.help"  -relief raised -fg black
+		} else {
+		message $w.m -width 400 -aspect 300 -text \
+			"No help available for $varname"  -relief raised -fg black
+		}
+		label $w.bm -bitmap error
+		pack $w.bm $w.m -pady 10 -side top -padx 10
+		wm title $w "RTFM" 
+	} else {
+		message $w.m -width 400 -aspect 300 -text $message \
+			 -relief raised -fg black
+		label $w.bm -bitmap info
+		pack $w.bm $w.m -pady 10 -side top -padx 10
+		wm title $w "Configuration help" 
+	}
+	set oldFocus [focus]
+	frame $w.f
+	button $w.f.back -text "OK" -activebackground green \
+		-width 10 -command "destroy $w; focus $oldFocus"
+	pack $w.f.back -side bottom -pady 10 -anchor s
+	pack $w.f -pady 10 -side top -padx 10 -anchor s
+	focus $w
+	wm geometry $w +30+35
+}
+
+proc wrapup {w }  {
+	catch {destroy $w}
+	toplevel $w -class Dialog
+	message $w.m -width 400 -aspect 300 -text \
+		"The linux kernel is now hopefully configured for your setup. Check the top-level Makefile for additional configuration, and do a 'make dep ; make clean' if you want to be sure all the files are correctly re-made."  -relief raised -fg black
+	label $w.bm -bitmap info
+	pack $w.bm $w.m -pady 10 -side top -padx 10
+	wm title $w "Kernel build instructions" 
+
+	set oldFocus [focus]
+	frame $w.f
+	button $w.f.back -text "OK" -activebackground green \
+		-width 10 -command "exit"
+	pack $w.f.back -side bottom -pady 10 -anchor s
+	pack $w.f -pady 10 -side top -padx 10 -anchor s
+	focus $w
+	wm geometry $w +30+35
+
+}
+
+proc check_sound_config { num } {
+#nothing for now.
+}
+
+proc tristate {w mnum line text variable default} {
+	frame $w.x$line
+	radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	radiobutton $w.x$line.n -text "n"  -variable $variable -value 0 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	radiobutton $w.x$line.m -text "m"  -variable $variable -value 2 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	button $w.x$line.help -text "Help" -relief raised \
+		-command "dohelp .dohelp $variable"
+	button $w.x$line.l -text "$text" -relief raised 
+	pack $w.x$line.y $w.x$line.m $w.x$line.n $w.x$line.help $w.x$line.l -anchor w -side left
+	pack $w.x$line -anchor w
+}
+
+proc dep_tristate {w mnum line text variable default} {
+	frame $w.x$line
+	radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	radiobutton $w.x$line.n -text "n"  -variable $variable -value 0 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	radiobutton $w.x$line.m -text "m"  -variable $variable -value 2 \
+		-width 2 -command "update_menu$mnum .menu$mnum"
+	button $w.x$line.help -text "Help" -relief raised \
+		-command "dohelp .dohelp $variable"
+	button $w.x$line.l -text "$text" -relief raised 
+	pack $w.x$line.y $w.x$line.m $w.x$line.n $w.x$line.help $w.x$line.l -anchor w -side left
+	pack $w.x$line -anchor w
+}
+
+
+#
+# Next set up the particulars for the top level menu, and define a few
+# buttons which we will stick down at the bottom.
+#
+frame .header
+label .header.label 
+
+frame .f0 
+
diff -u --recursive --new-file v1.3.34/linux/scripts/tail.tk linux/scripts/tail.tk
--- v1.3.34/linux/scripts/tail.tk	Thu Jan  1 02:00:00 1970
+++ linux/scripts/tail.tk	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,71 @@
+
+pack .header -side top -padx 10 -pady 10
+pack .f0 -side top -padx 15 -pady 10
+
+#
+# Misc buttons to save/restore state and so forth.
+# 
+frame .f0r_bot
+frame .f0l_bot
+
+#
+# Read the users settings from .config.  These wil override whatever is
+# in config.in.  Don't do this if the user specified a -D to force
+# the defaults.
+#
+if { [file readable .config] == 1} then {
+	if { $argc > 0 } then {
+		if { [lindex $argv 0] != "-D" } then {
+			read_config .config
+		}
+	} else {
+		read_config .config
+	}
+}
+
+button .f0r_bot.save -text "Write Configuration" -width 25 -command {
+	writeconfig .config include/linux/autoconf.h; wrapup .wrap }
+
+button .f0r_bot.quit -text "Quit" -command { exit } -width 25 \
+	-activebackground red -activeforeground white
+
+button .f0l_bot.store -text "Store Configuration to file" -width 25 -command {
+	load_configfile .load "Store Configuration" write_config_file
+}
+
+button .f0l_bot.load -text "Load Configuration" -width 25 -command {
+	load_configfile .load "Load Configuration" read_config_file
+}
+
+pack  .f0r_bot.save .f0r_bot.quit -padx 25 -ipadx 10 -ipady 2 -anchor w
+
+pack  .f0l_bot.load .f0l_bot.store -padx 25 -ipadx 10 -ipady 2 -anchor w
+
+pack .f0r_bot .f0l_bot -side left -padx 15 -pady 10 -anchor w
+
+#
+# If we cannot write our config files, disable the write button.
+#
+if { [file exists .config] == 1 } then {
+		if { [file writable .config] == 0 } then {
+			.f0r_bot.save configure -state disabled
+		}
+	} else {
+		if { [file writable .] == 0 } then {
+			.f0r_bot.save configure -state disabled
+		}
+	}
+
+if { [file exists include/linux/autoconf.h] == 1 } then {
+		if { [file writable include/linux/autoconf.h] == 0 } then {
+			.f0r_bot.save configure -state disabled
+		}
+	} else {
+		if { [file writable include/linux/] == 0 } then {
+			.f0r_bot.save configure -state disabled
+		}
+	}
+
+if { [file writable .config] == 0 || [file writable include/linux/autoconf.h ] == 0 } then {
+	.f0r_bot.save configure -state disabled
+	}
diff -u --recursive --new-file v1.3.34/linux/scripts/tkcond.c linux/scripts/tkcond.c
--- v1.3.34/linux/scripts/tkcond.c	Thu Jan  1 02:00:00 1970
+++ linux/scripts/tkcond.c	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,415 @@
+/* parser config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ *
+ * The general idea here is that we want to parse a config.in file and 
+ * from this, we generate a wish script which gives us effectively the
+ * same functionality that the original config.in script provided.
+ *
+ * This task is split roughly into 3 parts.  The first parse is the parse
+ * of the input file itself.  The second part is where we analyze the 
+ * #ifdef clauses, and attach a linked list of tokens to each of the
+ * menu items.  In this way, each menu item has a complete list of
+ * dependencies that are used to enable/disable the options.
+ * The third part is to take the configuration database we have build,
+ * and build the actual wish script.
+ *
+ * This file contains the code to further process the conditions from
+ * the "ifdef" clauses.
+ *
+ * The conditions are assumed to be one of the folowing formats
+ *
+ * simple_condition:= "$VARIABLE" == y/n/m
+ * simple_condition:= "$VARIABLE != y/n/m
+ *
+ * simple_condition -a simple_condition
+ *
+ * If the input condition contains '(' or ')' it would screw us up, but for now
+ * this is not a problem.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "tkparse.h"
+
+
+/*
+ * Walk a condition chain and invert it so that the logical result is
+ * inverted.
+ */
+static int invert_condition(struct condition * cnd)
+{
+  /*
+   * This is simple.  Just walk through the list, and invert
+   * all of the operators.
+   */
+  for(;cnd; cnd = cnd->next)
+    {
+      switch(cnd->op)
+	{
+	case op_and:
+	  cnd->op = op_or;
+	  break;
+	case op_or:
+	  cnd->op = op_and;
+	  break;
+	case op_neq:
+	  cnd->op = op_eq;
+	  break;
+	case op_eq:
+	  cnd->op = op_neq;
+	  break;
+	}
+    }
+}
+
+/*
+ * Walk a condition chain, and free the memory associated with it.
+ */
+static int free_condition(struct condition * cnd)
+{
+  struct condition * next;
+  for(;cnd; cnd = next)
+    {
+      next = cnd->next;
+
+      if( cnd->variable.str != NULL )
+	free(cnd->variable.str);
+
+      free(cnd);
+    }
+}
+
+/*
+ * Walk the stack of conditions, and clone all of them with "&&" operators
+ * gluing them together.  The conditions from each level of the stack
+ * are wrapped in parenthesis so as to guarantee that the results
+ * are logically correct.
+ */
+struct condition * get_token_cond(struct condition ** cond, int depth)
+{
+  int i;
+  struct condition * newcond;
+  struct condition * tail;
+  struct condition * new;
+  struct condition * ocond;
+  struct kconfig * cfg;
+
+  newcond = tail = NULL;
+  for(i=0; i<depth; i++, cond++)
+    {
+      /*
+       * First insert the left parenthesis
+       */
+      new = (struct condition *) malloc(sizeof(struct condition));
+      memset(new, 0, sizeof(*new));
+      new->op = op_lparen;
+      if( tail == NULL )
+	{
+	  newcond = tail = new;
+	}
+      else
+	{
+	  tail->next = new;
+	  tail = new;
+	}
+
+      /*
+       * Now duplicate the chain.
+       */
+      ocond = *cond;
+      for(;ocond != NULL; ocond = ocond->next)
+	{
+	  new = (struct condition *) malloc(sizeof(struct condition));
+	  memset(new, 0, sizeof(*new));
+	  new->op = ocond->op;
+	  if( ocond->variable.str != NULL )
+	    {
+	      if( ocond->op == op_variable )
+		{
+		  /*
+		   * Search for structure to insert here.
+		   */
+		  for(cfg = config;cfg != NULL; cfg = cfg->next)
+		    {
+		      if( cfg->tok != tok_bool && cfg->tok != tok_int
+			 && cfg->tok != tok_tristate 
+			 && cfg->tok != tok_dep_tristate)
+			{
+			  continue;
+			}
+		      if( strcmp(cfg->optionname, ocond->variable.str) == 0)
+			{
+			  new->variable.cfg = cfg;
+			  new->op = op_kvariable;
+			  break;
+			}
+		    }
+		}
+	      else
+		{
+		  new->variable.str = strdup(ocond->variable.str);
+		}
+	    }
+	  tail->next = new;
+	  tail = new;
+	}
+
+      /*
+       * Next insert the left parenthesis
+       */
+      new = (struct condition *) malloc(sizeof(struct condition));
+      memset(new, 0, sizeof(*new));
+      new->op = op_rparen;
+      tail->next = new;
+      tail = new;
+
+      /*
+       * Insert an and operator, if we have another condition.
+       */
+      if( i < depth - 1 )
+	{
+	  new = (struct condition *) malloc(sizeof(struct condition));
+	  memset(new, 0, sizeof(*new));
+	  new->op = op_and;
+	  tail->next = new;
+	  tail = new;
+	}
+
+    }
+
+  return newcond;
+}
+
+/*
+ * Walk a single chain of conditions and clone it.  These are assumed
+ * to be created/processed by  get_token_cond in a previous pass.
+ */
+struct condition * get_token_cond_frag(struct condition * cond, 
+				       struct condition ** last)
+{
+  int i;
+  struct condition * newcond;
+  struct condition * tail;
+  struct condition * new;
+  struct condition * ocond;
+  struct kconfig * cfg;
+
+  newcond = tail = NULL;
+
+  /*
+   * Now duplicate the chain.
+   */
+  for(ocond = cond;ocond != NULL; ocond = ocond->next)
+    {
+      new = (struct condition *) malloc(sizeof(struct condition));
+      memset(new, 0, sizeof(*new));
+      new->op = ocond->op;
+      new->variable.cfg = ocond->variable.cfg;
+      if( tail == NULL )
+	{
+	  newcond = tail = new;
+	}
+      else
+	{
+	  tail->next = new;
+	  tail = new;
+	}
+    }
+
+  new = (struct condition *) malloc(sizeof(struct condition));
+  memset(new, 0, sizeof(*new));
+  new->op = op_and;
+  tail->next = new;
+  tail = new;
+  
+  *last = tail;
+  return newcond;
+}
+
+/*
+ * Walk through the if conditionals and maintain a chain.
+ */
+int fix_conditionals(struct kconfig * scfg)
+{
+  int depth = 0;
+  int i;
+  struct kconfig * cfg;
+  struct condition * conditions[25];
+  struct condition * cnd;
+  struct condition * cnd1;
+  struct condition * cnd2;
+  struct condition * cnd3;
+  struct condition * newcond;
+  struct condition * last;
+
+  /*
+   * Start by walking the chain.  Every time we see an ifdef, push
+   * the condition chain on the stack.  When we see an "else", we invert
+   * the condition at the top of the stack, and when we see an "endif"
+   * we free all of the memory for the condition at the top of the stack
+   * and remove the condition from the top of the stack.
+   *
+   * For any other type of token (i.e. a bool), we clone a new condition chain
+   * by anding together all of the conditions that are currently stored on
+   * the stack.  In this way, we have a correct representation of whatever
+   * conditions govern the usage of each option.
+   */
+  memset(conditions, 0, sizeof(conditions));
+  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+    {
+      switch(cfg->tok)
+	{
+	case tok_if:
+	  /*
+	   * Push this condition on the stack, and nuke the token
+	   * representing the ifdef, since we no longer need it.
+	   */
+	  conditions[depth] = cfg->cond;
+	  depth++;
+	  cfg->tok = tok_nop;
+	  cfg->cond =  NULL;
+	  break;
+	case tok_else:
+	  /*
+	   * For an else, we just invert the condition at the top of
+	   * the stack.  This is done in place with no reallocation
+	   * of memory taking place.
+	   */
+	  invert_condition(conditions[depth-1]);
+	  cfg->tok = tok_nop;
+	  break;
+	case tok_fi:
+	  depth--;
+	  free_condition(conditions[depth]);
+	  conditions[depth] = NULL;
+	  cfg->tok = tok_nop;
+	  break;
+	case tok_comment:
+	case tok_menuoption:
+	case tok_bool:
+	case tok_tristate:
+	case tok_dep_tristate:
+	case tok_int:
+	  /*
+	   * We need to duplicate the chain of conditions and attach them to
+	   * this token.
+	   */
+	  cfg->cond = get_token_cond(&conditions[0], depth);
+	  break;
+	default:
+	  break;
+	}
+    }
+  /*
+   * Now go through the list, and every time we see a kvariable, check
+   * to see whether it also has some dependencies.  If so, then
+   * append it to our list.  The reason we do this is that we might have
+   * option CONFIG_FOO which is only used if CONFIG_BAR is set.  It may
+   * turn out that in config.in that the default value for CONFIG_BAR is
+   * set to "y", but that CONFIG_BAR is not enabled because CONFIG_XYZZY
+   * is not set.  The current condition chain does not reflect this, but
+   * we can fix this by searching for the tokens that this option depends
+   * upon and cloning the conditions and merging them with the list.
+   */
+  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+    {
+      /*
+       * Search for a token that has a condition list.
+       */
+      if(cfg->cond == NULL) continue;
+      for(cnd = cfg->cond; cnd; cnd=cnd->next)
+	{
+	  /*
+	   * Now search the condition list for a known configuration variable
+	   * that has conditions of it's own.
+	   */
+	  if(cnd->op != op_kvariable) continue;
+	  if(cnd->variable.cfg->cond == NULL) continue;
+
+	  /*
+	   * OK, we have some conditions to append to cfg.  Make  a clone
+	   * of the conditions,
+	   */
+	  newcond = get_token_cond_frag(cnd->variable.cfg->cond, &last);
+
+	  /*
+	   * Finally, we splice it into our list.
+	   */
+	  last->next = cfg->cond;
+	  cfg->cond = newcond;
+
+	}
+    }
+
+  /*
+   * There is a strong possibility that we have duplicate conditions
+   * in here.  It would make the script more efficient and readable to
+   * remove these.  Here is where we assume here that there are no
+   * parenthesis in the input script.
+   */
+  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+    {
+      /*
+       * Search for configuration options that have conditions.
+       */
+      if(cfg->cond == NULL) continue;
+      for(cnd = cfg->cond; cnd; cnd=cnd->next)
+	{
+	  /*
+	   * Search for a left parenthesis.
+	   */
+	  if(cnd->op != op_lparen) continue;
+	  for(cnd1 = cnd->next; cnd1; cnd1=cnd1->next)
+	    {
+	      /*
+	       * Search after the previous left parenthesis, and try
+	       * and find a second left parenthesis.
+	       */
+	      if(cnd1->op != op_lparen) continue;
+
+	      /*
+	       * Now compare the next 5 tokens to see if they are
+	       * identical.  We are looking for two chains that
+	       * are like: '(' $VARIABLE operator constant ')'.
+	       */
+	      cnd2 = cnd;
+	      cnd3 = cnd1;
+	      for(i=0; i<5; i++, cnd2=cnd2->next, cnd3=cnd3->next)
+		{
+		  if(!cnd2 || !cnd3) break;
+		  if(cnd2->op != cnd3->op) break;
+		  if(i == 1 && (cnd2->op != op_kvariable 
+		     || cnd2->variable.cfg != cnd3->variable.cfg) ) break;
+		  if(i==2 && cnd2->op != op_eq && cnd2->op != op_neq) break;
+		  if(i == 3 && cnd2->op != op_constant &&
+		     strcmp(cnd2->variable.str, cnd3->variable.str) != 0)
+		    break;
+		  if(i==4 && cnd2->op != op_rparen) break;
+		}
+	      /*
+	       * If these match, and there is an and gluing these together,
+	       * then we can nuke the second one.
+	       */
+	      if(i==5 && ((cnd3 && cnd3->op == op_and)
+			  ||(cnd2 && cnd2->op == op_and)))
+		{
+		  /*
+		   * We have a duplicate.  Nuke 5 ops.
+		   */
+		  cnd3 = cnd1;
+		  for(i=0; i<5; i++, cnd3=cnd3->next)
+		    {
+		      cnd3->op = op_nuked;
+		    }
+		  /*
+		   * Nuke the and that glues the conditions together.
+		   */
+		  if(cnd3 && cnd3->op == op_and) cnd3->op = op_nuked;
+		  else if(cnd2 && cnd2->op == op_and) cnd2->op = op_nuked;
+		}
+	    }
+	}
+    }
+}
diff -u --recursive --new-file v1.3.34/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v1.3.34/linux/scripts/tkgen.c	Thu Jan  1 02:00:00 1970
+++ linux/scripts/tkgen.c	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,719 @@
+/* Generate tk script based upon config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ */
+#include <stdio.h>
+#include "tkparse.h"
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+/*
+ * Generate portion of wish script for the beginning of a submenu.
+ * The guts get filled in with the various options.
+ */
+static start_proc(char * label, int menu_num, int flag)
+{
+  if( flag )
+    printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
+  printf("proc menu%d {w title} {\n", menu_num);
+  printf("\tcatch {destroy $w}\n");
+  printf("\ttoplevel $w -class Dialog\n");
+  printf("\tmessage $w.m -width 400 -aspect 300 -background grey -text \\\n");
+  printf("\t\t\"$title\"  -relief raised -bg grey\n");
+  printf("\tpack $w.m -pady 10 -side top -padx 10\n");
+  printf("\twm title $w \"$title\" \n\n\n");
+}
+
+/*
+ * Each proc we create needs a global declaration for any global variables we
+ * use.  To minimize the size of the file, we set a flag each time we output
+ * a global declaration so we know whether we need to insert one for a
+ * given function or not.
+ */
+clear_globalflags(struct kconfig * cfg)
+{
+  for(; cfg != NULL; cfg = cfg->next)
+  {
+    cfg->flags &= ~GLOBAL_WRITTEN;
+  }
+}
+
+/*
+ * This function walks the chain of conditions that we got from cond.c,
+ * and creates a wish conditional to enable/disable a given widget.
+ */
+generate_if(struct kconfig * item,
+	    struct condition * cond,
+	    int menu_num,
+	    int line_num)
+{
+  struct condition * ocond;
+
+  /*
+   * First write any global declarations we need for this conditional.
+   */
+  ocond = cond;
+  while(cond != NULL )
+    {
+      switch(cond->op){
+      case op_variable:
+	printf("\tglobal %s\n", cond->variable.str);
+	break;
+      case op_kvariable:
+	if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
+	cond->variable.cfg->flags |= GLOBAL_WRITTEN;
+	printf("\tglobal %s\n", cond->variable.cfg->optionname);
+	break;
+      default:
+	break;
+      }
+      cond = cond->next;
+    }
+
+  /*
+   * Now generate the body of the conditional.
+   */
+  printf("\tif {");
+  cond = ocond;
+  while(cond != NULL )
+    {
+      switch(cond->op){
+      case op_bang:
+	printf(" ! ");
+	break;
+      case op_eq:
+	printf(" == ");
+	break;
+      case op_neq:
+	printf(" != ");
+	break;
+      case op_and:
+	printf(" && ");
+	break;
+      case op_or:
+	printf(" || ");
+	break;
+      case op_lparen:
+	printf("(");
+	break;
+      case op_rparen:
+	printf(")");
+	break;
+      case op_variable:
+	printf("$%s", cond->variable.str);
+	break;
+      case op_kvariable:
+	printf("$%s", cond->variable.cfg->optionname);
+	break;
+      case op_constant:
+	if( strcmp(cond->variable.str, "y") == 0 )
+	  printf("1");
+	else if( strcmp(cond->variable.str, "n") == 0 )
+	  printf("0");
+	else if( strcmp(cond->variable.str, "m") == 0 )
+	  printf("2");
+	else
+	  printf("'%s'", cond->variable);
+	break;
+      }
+      cond = cond->next;
+    }
+
+  /*
+   * Now we generate what we do depending upon the value of the conditional.
+   * Depending upon what the token type is, there are different things
+   * we must do to enable/disable the given widget - this code needs to
+   * be closely coordinated with the widget creation procedures in header.tk.
+   */
+  switch(item->tok)
+    {
+    case tok_menuoption:
+      printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
+	     menu_num, menu_num);
+      break;
+    case tok_int:
+      printf("} then { ");
+      printf(".menu%d.x%d.x configure -state normal; ", menu_num, line_num);
+      printf(".menu%d.x%d.l configure -state normal; ", menu_num, line_num);
+      printf("} else { ");
+      printf(".menu%d.x%d.x configure -state disabled;", menu_num, line_num );
+      printf(".menu%d.x%d.l configure -state disabled;", menu_num, line_num );
+      printf("}\n");
+      break;
+    case tok_bool:
+#ifdef BOOL_IS_BUTTON
+      /*
+       * If a bool is just a button, then use this definition.
+       */
+      printf("} then { .menu%d.x%d configure -state normal } else { .menu%d.x%d configure -state disabled }\n",
+	     menu_num, line_num,
+	     menu_num, line_num );
+#else
+      /*
+       * If a bool is a radiobutton, then use this instead.
+       */
+      printf("} then { ");
+      printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
+      printf(".menu%d.x%d.n configure -state normal;",menu_num, line_num);
+      printf(".menu%d.x%d.l configure -state normal;",menu_num, line_num);
+      printf("} else { ");
+      printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
+      printf(".menu%d.x%d.n configure -state disabled;",menu_num, line_num);
+      printf(".menu%d.x%d.l configure -state disabled;",menu_num, line_num);
+      printf("}\n");
+#endif
+      break;
+    case tok_tristate:
+    case tok_dep_tristate:
+      printf("} then { ");
+      if( item->tok == tok_dep_tristate )
+	{
+	  printf("if { $%s == 2 } then {", item->depend.str);
+	  printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
+	  printf("} else {");
+	  printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
+	  printf("}; ");
+	}
+      else
+	{
+	  printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
+	}
+      
+      printf(".menu%d.x%d.n configure -state normal;",menu_num, line_num);
+      printf(".menu%d.x%d.m configure -state normal;",menu_num, line_num);
+      printf(".menu%d.x%d.l configure -state normal;",menu_num, line_num);
+      printf("} else { ");
+      printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
+      printf(".menu%d.x%d.n configure -state disabled;",menu_num, line_num);
+      printf(".menu%d.x%d.m configure -state disabled;",menu_num, line_num);
+      printf(".menu%d.x%d.l configure -state disabled;",menu_num, line_num);
+      printf("}\n");
+      break;
+    default:
+      break;
+    }
+}
+
+/*
+ * Similar to generate_if, except we come here when generating an
+ * output file.  Thus instead of enabling/disabling a widget, we
+ * need to decide whether to write out a given configuration variable
+ * to the output file.
+ */
+generate_if_for_outfile(struct kconfig * item,
+	    struct condition * cond)
+{
+  struct condition * ocond;
+
+  /*
+   * First write any global declarations we need for this conditional.
+   */
+  ocond = cond;
+  for(; cond != NULL; cond = cond->next )
+    {
+      switch(cond->op){
+      case op_variable:
+	printf("\tglobal %s\n", cond->variable.str);
+	break;
+      case op_kvariable:
+	if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
+	cond->variable.cfg->flags |= GLOBAL_WRITTEN;
+	printf("\tglobal %s\n", cond->variable.cfg->optionname);
+	break;
+      default:
+	break;
+      }
+    }
+
+  /*
+   * Now generate the body of the conditional.
+   */
+  printf("\tif {");
+  cond = ocond;
+  while(cond != NULL )
+    {
+      switch(cond->op){
+      case op_bang:
+	printf(" ! ");
+	break;
+      case op_eq:
+	printf(" == ");
+	break;
+      case op_neq:
+	printf(" != ");
+	break;
+      case op_and:
+	printf(" && ");
+	break;
+      case op_or:
+	printf(" || ");
+	break;
+      case op_lparen:
+	printf("(");
+	break;
+      case op_rparen:
+	printf(")");
+	break;
+      case op_variable:
+	printf("$%s", cond->variable.str);
+	break;
+      case op_kvariable:
+	printf("$%s", cond->variable.cfg->optionname);
+	break;
+      case op_constant:
+	if( strcmp(cond->variable.str, "y") == 0 )
+	  printf("1");
+	else if( strcmp(cond->variable.str, "n") == 0 )
+	  printf("0");
+	else if( strcmp(cond->variable.str, "m") == 0 )
+	  printf("2");
+	else
+	  printf("'%s'", cond->variable);
+	break;
+      }
+      cond = cond->next;
+    }
+
+  /*
+   * Now we generate what we do depending upon the value of the
+   * conditional.  Depending upon what the token type is, there are
+   * different things we must do write the value the given widget -
+   * this code needs to be closely coordinated with the widget
+   * creation procedures in header.tk.  
+   */
+  switch(item->tok)
+    {
+    case tok_comment:
+      printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
+      break;
+    case tok_dep_tristate:
+      printf("} then { write_variable $cfg $autocfg %s $%s $%s } \n", 
+	     item->optionname, item->optionname, item->depend.str);
+      break;
+    case tok_tristate:
+    case tok_bool:
+    case tok_int:
+      printf("} then { write_variable $cfg $autocfg %s $%s $notmod }\n", 
+	     item->optionname, item->optionname);
+      break;
+    default:
+      break;
+    }
+}
+
+/*
+ * Generates a fragment of wish script that closes out a submenu procedure.
+ */
+static end_proc(int menu_num, int first, int last)
+{
+  struct kconfig * cfg;
+
+  printf("\n\n\n");
+  printf("\tset oldFocus [focus]\n");
+  printf("\tframe $w.f\n");
+
+  /*
+   * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
+   */
+  printf("\tbutton $w.f.prev -text \"Prev\" -activebackground green \\\n");
+      printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num-1, menu_num-1);
+  if(first == menu_num ) printf("\t$w.f.prev configure -state disabled\n");
+
+  printf("\tbutton $w.f.next -text \"Next\" -activebackground green \\\n");
+  printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1);
+  if(last == menu_num ) printf("\t$w.f.next configure -state disabled\n");
+
+  printf("\tbutton $w.f.back -text \"Main Menu\" -activebackground green \\\n");
+  printf("\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
+
+  printf("\tpack $w.f.back $w.f.next $w.f.prev -side left -pady 10 -padx 45\n");
+  printf("\tpack $w.f -pady 10 -side top -padx 10 -anchor w\n");
+  printf("\tfocus $w\n");
+  printf("\tupdate_menu%d $w\n", menu_num);
+  printf("\twm geometry $w +30+35\n");
+  printf("}\n\n\n");
+
+  /*
+   * Now we generate the companion procedure for the muen we just
+   * generated.  This procedure contains all of the code to
+   * disable/enable widgets based upon the settings of the other
+   * widgets, and will be called first when the window is mapped,
+   * and each time one of the buttons in the window are clicked.
+   */
+  printf("proc update_menu%d {w}  {\n", menu_num);
+
+  clear_globalflags(config);
+  for(cfg = config;cfg != NULL; cfg = cfg->next)
+    {
+      /*
+       * Skip items not for this menu, or ones having no conditions.
+       */
+      if (cfg->menu_number != menu_num ) continue;
+      if (cfg->tok == tok_menuoption) continue;
+      if (cfg->cond != NULL ) 
+	generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
+      else
+	{
+	  /*
+	   * If this token has no conditionals, check to see whether
+	   * it is a tristate - if so, then generate the conditional
+	   * to enable/disable the "y" button based upon the setting
+	   * of the option it depends upon.
+	   */
+	  if(cfg->tok == tok_dep_tristate)
+	    {
+	      printf("\tif {$%s == 2 } then { .menu3.x5.y configure -state normal} else { .menu3.x5.y configure -state disabled}\n",cfg->depend.str,
+		     menu_num, cfg->menu_line,
+		     menu_num, cfg->menu_line);
+	      
+	    }
+	}
+
+    }
+
+
+  printf("}\n\n\n");
+}
+
+/*
+ * This function goes through and counts up the number of items in
+ * each submenu. If there are too many options, we need to split it
+ * into submenus.  This function just calculates how many submenus,
+ * and how many items go in each submenu.
+ */
+static int find_menu_size(struct kconfig *cfg,
+			  int *menu_max, 
+			  int *menu_maxlines)
+
+{
+  struct kconfig * pnt;
+  int tot;
+  int div;
+  
+  /*
+   * First count up the number of options in this menu.
+   */
+  tot = 0;
+  for(pnt = cfg->next; pnt; pnt = pnt->next)
+  {
+    if( pnt->tok == tok_menuoption) break;
+    switch (pnt->tok)
+      {
+      case tok_bool:
+      case tok_tristate:
+      case tok_dep_tristate:
+      case tok_int:
+	tot++;
+	break;
+      default:
+	break;
+      }
+  }
+
+  /*
+   * Now figure out how many items go on each page.
+   */
+  div = 1;
+  while(tot / div > 15) div++;
+  *menu_max = cfg->menu_number + div - 1;
+  *menu_maxlines = (tot + div -1) / div;
+}
+
+/*
+ * This is the top level function for generating the tk script.
+ */
+dump_tk_script(struct kconfig *scfg)
+{
+  int menu_num =0;
+  int menu_max =0;
+  int menu_min =0;
+  int menu_line = 0;
+  int menu_maxlines = 0;
+  struct kconfig * cfg;
+
+  /*
+   * Start by assigning menu numbers, and submenu numbers.
+   */
+  for(cfg = scfg;cfg != NULL; cfg = cfg->next)
+    {
+      switch (cfg->tok)
+	{
+	case tok_menuname:
+	  break;
+	case tok_menuoption:
+	  /*
+	   * At the start of a new menu, calculate the number of items
+	   * we will put into each submenu so we know when to bump the
+	   * menu number. The submenus are really no different from a
+	   * normal menu, but the top level buttons only access the first
+	   * of the chain of menus, and the prev/next buttons are used
+	   * access the submenus.
+	   */
+	  cfg->menu_number = ++menu_num;
+	  find_menu_size(cfg, &menu_max, &menu_maxlines);
+	  cfg->submenu_start = menu_num;
+	  cfg->submenu_end = menu_max;
+	  menu_line = 0;
+	  break;
+	case tok_bool:
+	case tok_tristate:
+	case tok_dep_tristate:
+	case tok_int:
+	  /*
+	   * If we have overfilled the menu, then go to the next one.
+	   */
+	  if( menu_line == menu_maxlines )
+	    {
+	      menu_line = 0;
+	      menu_num++;
+	    }
+	  cfg->menu_number = menu_num;
+	  cfg->submenu_start = menu_min;
+	  cfg->submenu_end = menu_max;
+	  cfg->menu_line = menu_line++;
+	  break;
+	default:
+	  break;
+	};
+    }
+
+  /*
+   * Now start generating the actual wish script that we will use.
+   * We need to keep track of the menu numbers of the min/max menu
+   * for a range of submenus so that we can correctly limit the
+   * prev and next buttons so that they don't go over into some other
+   * category.
+   */
+  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    {
+      switch (cfg->tok)
+	{
+	case tok_menuname:
+	  printf("mainmenu_name \"%s\"\n", cfg->label);
+	  break;
+	case tok_menuoption:
+	  /*
+	   * We are at the start of a new menu. If we had one that
+	   * we were working on before, close it out, and then generate
+	   * the script to start the new one.
+	   */
+	  if( cfg->menu_number > 1 )
+	    {
+	      end_proc(menu_num, menu_min, menu_max);
+	    }
+	  start_proc(cfg->label, cfg->menu_number, TRUE);
+	  menu_num = cfg->menu_number;
+	  menu_max = cfg->submenu_end;
+	  menu_min = cfg->submenu_start;
+	  break;
+	case tok_bool:
+	  /*
+	   * If we reached the point where we need to switch over
+	   * to the next submenu, then bump the menu number and generate
+	   * the code to close out the old menu and start the new one.
+	   */
+	  if( cfg->menu_number != menu_num )
+	    {
+	      end_proc(menu_num, menu_min, menu_max);
+	      start_proc(cfg->label, cfg->menu_number, FALSE);
+	      menu_num = cfg->menu_number;
+	    }
+	  printf("\tbool $w %d %d \"%s\" %s %s\n",
+		 cfg->menu_number,
+		 cfg->menu_line,
+		 cfg->label,
+		 cfg->optionname,
+		 cfg->dflt);
+	  break;
+
+	case tok_tristate:
+	  if( cfg->menu_number != menu_num )
+	    {
+	      end_proc(menu_num, menu_min, menu_max);
+	      start_proc(cfg->label, cfg->menu_number, FALSE);
+	      menu_num = cfg->menu_number;
+	    }
+	  printf("\ttristate $w %d %d \"%s\" %s %s\n",
+		 cfg->menu_number,
+		 cfg->menu_line,
+		 cfg->label,
+		 cfg->optionname,
+		 cfg->dflt);
+	  break;
+	case tok_dep_tristate:
+	  if( cfg->menu_number != menu_num )
+	    {
+	      end_proc(menu_num, menu_min, menu_max);
+	      start_proc(cfg->label, cfg->menu_number, FALSE);
+	      menu_num = cfg->menu_number;
+	    }
+	  printf("\tdep_tristate $w %d %d \"%s\" %s %s\n",
+		 cfg->menu_number,
+		 cfg->menu_line,
+		 cfg->label,
+		 cfg->optionname,
+		 cfg->dflt,
+		 cfg->depend);
+	  break;
+	case tok_int:
+	  printf("\tint $w %d %d \"%s\" %s %s\n",
+		 cfg->menu_number,
+		 cfg->menu_line,
+		 cfg->label,
+		 cfg->optionname,
+		 cfg->dflt);
+	default:
+	  break;
+	}
+
+    }
+
+  /*
+   * Generate the code to close out the last menu.
+   */
+  end_proc(menu_num, menu_min, menu_max);
+
+  /*
+   * Generate the code for configuring the sound driver.  Right now this
+   * cannot be done from the X script, but we insert the menu anyways.
+   */
+  start_proc("Configure sound driver", ++menu_num, TRUE);
+#if 0
+  printf("\tdo_make -C drivers/sound config\n");
+  printf("\techo check_sound_config %d\n",menu_num);
+#endif
+  printf("\tlabel $w.m0 -bitmap error\n");
+  printf("\tmessage $w.m1 -width 400 -aspect 300 -text \"The sound drivers cannot as of yet be configured via the X-based interface\" -relief raised\n");
+  printf("\tpack $w.m0 $w.m1 -side top -pady 10\n");
+
+  /*
+   * Close out the last menu.
+   */
+  end_proc(menu_num, menu_num, menu_num);
+
+  /*
+   * The top level menu also needs an update function.  When we exit a
+   * submenu, we may need to disable one or more of the submenus on
+   * the top level menu, and this procedure will ensure that things are
+   * correct.
+   */
+  printf("proc update_mainmenu {w}  {\n");
+  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    {
+      switch (cfg->tok)
+	{
+	case tok_menuoption:
+	  if (cfg->cond != NULL ) 
+	    generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  printf("}\n\n\n");
+
+  /*
+   * Now generate code to load the default settings into the variables.
+   * Note that the script in tail.tk will attempt to load .config,
+   * which may override these settings, but that's OK.
+   */
+  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    {
+      switch (cfg->tok)
+	{
+	case tok_int:
+	    printf("set %s %s\n", cfg->optionname, cfg->dflt);
+	    break;
+	case tok_bool:
+	case tok_tristate:
+	case tok_dep_tristate:
+	  if( strcmp(cfg->dflt, "y") == 0 )
+	    printf("set %s 1\n", cfg->optionname);
+	  else if( strcmp(cfg->dflt, "n") == 0 )
+	    printf("set %s 0\n", cfg->optionname);
+	  else if( strcmp(cfg->dflt, "m") == 0 )
+	    printf("set %s 2\n", cfg->optionname);
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  /*
+   * Next generate a function that can be called from the main menu that will
+   * write all of the variables out.  This also serves double duty - we can
+   * save configuration to a file using this.
+   */
+  printf("proc writeconfig {file1 file2} {\n");
+  printf("\tset cfg [open $file1 w]\n");
+  printf("\tset autocfg [open $file2 w]\n");
+  printf("\tset notmod 1\n");
+  printf("\tset notset 0\n");
+  clear_globalflags(config);
+  printf("\tputs $cfg \"#\"\n");
+  printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
+  printf("\tputs $cfg \"#\"\n");
+
+  printf("\tputs $autocfg \"/*\"\n");
+  printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
+  printf("\tputs $autocfg \" */\"\n");
+  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    {
+      switch (cfg->tok)
+	{
+	case tok_int:
+	case tok_bool:
+	case tok_tristate:
+	case tok_dep_tristate:
+	  if(cfg->flags & GLOBAL_WRITTEN) break;
+	  cfg->flags |= GLOBAL_WRITTEN;
+	  printf("\tglobal %s\n", cfg->optionname);
+
+	case tok_comment:
+	  if (cfg->cond != NULL ) 
+	    generate_if_for_outfile(cfg, cfg->cond);
+	  else
+	    {
+	      if(cfg->tok == tok_dep_tristate)
+		{
+		  printf("\tif {$%s == 2 } then { write_variable $cfg $autocfg %s $%s %s } else { write_variable $cfg $autocfg %s $notset $notmod }\n",
+			 cfg->optionname,
+			 cfg->optionname,
+			 cfg->depend.str,
+			 cfg->optionname);
+		}
+	      else if(cfg->tok == tok_comment)
+		{
+		  printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
+		}
+	      else
+		{
+		  printf("\twrite_variable $cfg $autocfg %s $%s $notmod\n",
+			 cfg->optionname,
+			 cfg->optionname);
+			 
+		}
+	    }
+	  break;
+	default:
+	  break;
+	}
+    }
+  printf("\tclose $cfg\n");
+  printf("\tclose $autocfg\n");
+  printf("}\n\n\n");
+
+  /*
+   * That's it.  We are done.  The output of this file will have header.tk
+   * prepended and tail.tk appended to create an executable wish script.
+   */
+}
diff -u --recursive --new-file v1.3.34/linux/scripts/tkparse.c linux/scripts/tkparse.c
--- v1.3.34/linux/scripts/tkparse.c	Thu Jan  1 02:00:00 1970
+++ linux/scripts/tkparse.c	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,529 @@
+/* parser config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ *
+ * The general idea here is that we want to parse a config.in file and 
+ * from this, we generate a wish script which gives us effectively the
+ * same functionality that the original config.in script provided.
+ *
+ * This task is split roughly into 3 parts.  The first parse is the parse
+ * of the input file itself.  The second part is where we analyze the 
+ * #ifdef clauses, and attach a linked list of tokens to each of the
+ * menu items.  In this way, each menu item has a complete list of
+ * dependencies that are used to enable/disable the options.
+ * The third part is to take the configuration database we have build,
+ * and build the actual wish script.
+ *
+ * This file contains the code to do the first parse of config.in.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "tkparse.h"
+
+struct kconfig * config = NULL;
+struct kconfig * clast = NULL;
+struct kconfig * koption = NULL;
+static int lineno = 0;
+/*
+ * Simple function just to skip over spaces and tabs in config.in.
+ */
+static char * skip_whitespace(char * pnt)
+{
+  while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+  return pnt;
+}
+
+/*
+ * This function parses a conditional from a config.in (i.e. from an ifdef)
+ * and generates a linked list of tokens that describes the conditional.
+ */
+static struct condition * parse_if(char * pnt)
+{
+  char * opnt;
+  struct condition *list;
+  struct condition *last;
+  struct condition *cpnt;
+  char varname[64];
+  char * pnt1;
+
+  opnt = pnt;
+
+  /*
+   * We need to find the various tokens, and build the linked list.
+   */
+  pnt = skip_whitespace(pnt);
+  if( *pnt != '[' ) return NULL;
+  pnt++;
+  pnt = skip_whitespace(pnt);
+
+  list = last = NULL;
+  while(*pnt && *pnt != ']') {
+
+    pnt = skip_whitespace(pnt);
+    if(*pnt== '\0' || *pnt == ']') break;
+
+    /*
+     * Allocate memory for the token we are about to parse, and insert
+     * it in the linked list.
+     */
+    cpnt = (struct condition *) malloc(sizeof(struct condition));
+    memset(cpnt, 0, sizeof(struct condition));
+    if( last == NULL )
+      {
+	list = last = cpnt;
+      }
+    else
+      {
+	last->next = cpnt;
+	last = cpnt;
+      }
+
+    /*
+     * Determine what type of operation this token represents.
+     */
+    if( *pnt == '-' && pnt[1] == 'a' )
+      {
+	cpnt->op = op_and;
+	pnt += 2;
+	continue;
+      }
+
+    if( *pnt == '!' && pnt[1] == '=' )
+      {
+	cpnt->op = op_neq;
+	pnt += 2;
+	continue;
+      }
+
+    if( *pnt == '=')
+      {
+	cpnt->op = op_eq;
+	pnt += 1;
+	continue;
+      }
+
+    if( *pnt == '!')
+      {
+	cpnt->op = op_bang;
+	pnt += 1;
+	continue;
+      }
+
+    if( *pnt != '"' ) goto error;  /* This cannot be right. */
+    pnt++;
+    if( *pnt == '$' )
+      {
+	cpnt->op = op_variable;
+	pnt1 = varname;
+	pnt++;
+	while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
+	*pnt1++ = '\0';
+	cpnt->variable = strdup(varname);
+	if( *pnt == '"' ) pnt++;
+	continue;
+      }
+
+    cpnt->op = op_constant;
+    pnt1 = varname;
+    while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
+    *pnt1++ = '\0';
+    cpnt->variable = strdup(varname);
+    if( *pnt == '"' ) pnt++;
+    continue;
+  }
+
+  return list;
+
+ error:
+  printf("Bad if clause at line %d:%s\n", lineno, opnt);
+  return NULL;
+}
+
+/*
+ * This function looks for a quoted string, from the input buffer, and
+ * returns a pointer to a copy of this string.  Any characters in
+ * the string that need to be "quoted" have a '\' character inserted
+ * in front - this way we can directly write these strings into
+ * wish scripts.
+ */
+static char * get_qstring(char *pnt, char ** labl)
+{
+  char quotechar;
+  char newlabel[1024];
+  char * pnt1;
+  char * pnt2;
+
+  while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
+  if (*pnt == '\0') return pnt;
+
+  quotechar = *pnt++;
+  pnt1 = newlabel;
+  while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
+    {
+      /*
+       * Quote the character if we need to.
+       */
+      if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
+	*pnt1++ = '\\';
+
+      *pnt1++ = *pnt++;
+    }
+  *pnt1++ = '\0';
+
+  pnt2 = (char *) malloc(strlen(newlabel) + 1);
+  strcpy(pnt2, newlabel);
+  *labl = pnt2;
+
+  /*
+   * Skip over last quote, and whitespace.
+   */
+  pnt++;
+  pnt = skip_whitespace(pnt);
+  return pnt;
+}
+
+/*
+ * This function grabs one text token from the input buffer
+ * and returns a pointer to a copy of just the identifier.
+ * This can be either a variable name (i.e. CONFIG_NET),
+ * or it could be the default value for the option.
+ */
+static char * get_string(char *pnt, char ** labl)
+{
+  char quotechar;
+  char newlabel[1024];
+  char * pnt1;
+  char * pnt2;
+
+  if (*pnt == '\0') return pnt;
+
+  pnt1 = newlabel;
+  while(*pnt && *pnt != ' ' && *pnt != '\t')
+    {
+      *pnt1++ = *pnt++;
+    }
+  *pnt1++ = '\0';
+
+  pnt2 = (char *) malloc(strlen(newlabel) + 1);
+  strcpy(pnt2, newlabel);
+  *labl = pnt2;
+
+  if( *pnt ) pnt++;
+  return pnt;
+}
+
+
+/*
+ * Top level parse function.  Input pointer is one complete line from config.in
+ * and the result is that we create a token that describes this line
+ * and insert it into our linked list.
+ */
+int parse(char * pnt) {
+  enum token tok;
+  struct kconfig * kcfg;
+  /*
+   * Ignore comments and leading whitespace.
+   */
+
+  pnt = skip_whitespace(pnt);
+  while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+  if(! *pnt ) return;
+  if( *pnt == '#' ) return;
+
+  /*
+   * Now categorize the next token.
+   */
+  tok = tok_unknown;
+  if      (strncmp(pnt, "mainmenu_name", 13) == 0) 
+    {
+      tok = tok_menuname;
+      pnt += 13;
+    }
+  else if (strncmp(pnt, "mainmenu_option", 15) == 0) 
+    {
+      tok = tok_menuoption;
+      pnt += 15;
+    }
+  else if (strncmp(pnt, "comment", 7) == 0) 
+    {
+      tok = tok_comment;
+      pnt += 7;
+    }
+  else if (strncmp(pnt, "bool", 4) == 0) 
+    {
+      tok = tok_bool;
+      pnt += 4;
+    }
+  else if (strncmp(pnt, "tristate", 8) == 0) 
+    {
+      tok = tok_tristate;
+      pnt += 8;
+    }
+  else if (strncmp(pnt, "dep_tristate", 12) == 0) 
+    {
+      tok = tok_dep_tristate;
+      pnt += 12;
+    }
+  else if (strncmp(pnt, "int", 3) == 0) 
+    {
+      tok = tok_int;
+      pnt += 3;
+    }
+  else if (strncmp(pnt, "if", 2) == 0) 
+    {
+      tok = tok_if;
+      pnt += 2;
+    }
+  else if (strncmp(pnt, "else", 4) == 0) 
+    {
+      tok = tok_else;
+      pnt += 4;
+    }
+  else if (strncmp(pnt, "fi", 2) == 0) 
+    {
+      tok = tok_fi;
+      pnt += 2;
+    }
+
+  if( tok == tok_unknown)
+    {
+      printf("unknown command=%s\n", pnt);
+      return 1;
+    }
+
+  /*
+   * Allocate memory for this item, and attach it to the end of the linked
+   * list.
+   */
+  kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
+  memset(kcfg, 0, sizeof(struct kconfig));
+  kcfg->tok = tok;
+  if( clast != NULL )
+    {
+      clast->next = kcfg;
+      clast = kcfg;
+    }
+  else
+    {
+      clast = config = kcfg;
+    }
+
+  pnt = skip_whitespace(pnt);
+
+  /*
+   * Now parse the remaining parts of the option, and attach the results
+   * to the structure.
+   */
+  switch (tok)
+    {
+    case tok_menuname:
+      pnt = get_qstring(pnt, &kcfg->label);
+      break;
+    case tok_bool:
+    case tok_tristate:
+    case tok_int:
+      pnt = get_qstring(pnt, &kcfg->label);
+      pnt = get_string(pnt, &kcfg->optionname);
+      pnt = get_string(pnt, &kcfg->dflt);
+      break;
+    case tok_dep_tristate:
+      pnt = get_qstring(pnt, &kcfg->label);
+      pnt = get_string(pnt, &kcfg->optionname);
+      pnt = get_string(pnt, &kcfg->dflt);
+      pnt = skip_whitespace(pnt);
+      if( *pnt == '$') pnt++;
+      pnt = get_string(pnt, &kcfg->depend.str);
+      break;
+    case tok_comment:
+      pnt = get_qstring(pnt, &kcfg->label);
+      if( koption != NULL )
+	{
+	  pnt = get_qstring(pnt, &kcfg->label);
+	  koption->label = kcfg->label;
+	  koption = NULL;
+	}
+      break;
+    case tok_menuoption:
+      if( strncmp(pnt, "next_comment", 12) == 0)
+	{
+	  koption = kcfg;
+	}
+      else
+	{
+	  pnt = get_qstring(pnt, &kcfg->label);
+	}
+      break;
+    case tok_else:
+    case tok_fi:
+      break;
+    case tok_if:
+      /*
+       * Conditionals are different.  For the first level parse, only
+       * tok_if items have a ->cond chain attached.
+       */
+      kcfg->cond = parse_if(pnt);
+      if(kcfg->cond == NULL )
+	{
+	  exit(1);
+	}
+      break;
+    default:
+      exit(0);
+
+    }
+}
+
+/*
+ * Simple function to dump to the screen what the condition chain looks like.
+ */
+dump_if(struct condition * cond)
+{
+  printf(" ");
+  while(cond != NULL )
+    {
+      switch(cond->op){
+      case op_eq:
+	printf(" = ");
+	break;
+      case op_bang:
+	printf(" ! ");
+	break;
+      case op_neq:
+	printf(" != ");
+	break;
+      case op_and:
+	printf(" -a ");
+	break;
+      case op_lparen:
+	printf("(");
+	break;
+      case op_rparen:
+	printf(")");
+	break;
+      case op_variable:
+	printf("$%s", cond->variable);
+	break;
+      case op_constant:
+	printf("'%s'", cond->variable);
+	break;
+      }
+      cond = cond->next;
+    }
+
+  printf("\n");
+}
+
+char buffer[1024];
+
+main(int argc, char * argv[])
+{
+  char * pnt;
+  struct kconfig * cfg;
+  int    i;
+
+  /*
+   * Loop over every input line, and parse it into the tables.
+   */
+  while(1)
+    {
+      fgets(buffer, sizeof(buffer), stdin);
+      if(feof(stdin)) break;
+
+      /*
+       * Strip the trailing return character.
+       */
+      pnt = buffer + strlen(buffer) - 1;
+      if( *pnt == '\n') *pnt = 0;
+      lineno++;
+      parse(buffer);
+    }
+
+
+  /*
+   * Input file is now parsed.  Next we need to go through and attach
+   * the correct conditions to each of the actual menu items and kill
+   * the if/else/endif tokens from the list.  We also flag the menu items
+   * that have other things that depend upon it's setting.
+   */
+  fix_conditionals(config);
+
+  /*
+   * Finally, we generate the wish script.
+   */
+  dump_tk_script(config);
+
+#if 0
+  /*
+   * Now dump what we have so far.  This is only for debugging so that
+   * we can display what we think we have in the list.
+   */
+  for(cfg = config; cfg; cfg = cfg->next)
+    {
+
+      if(cfg->cond != NULL && cfg->tok != tok_if)
+	dump_if(cfg->cond);
+
+      switch(cfg->tok)
+	{
+	case tok_menuname:
+	  printf("main_menuname ");
+	  break;
+	case tok_bool:
+	  printf("bool ");
+	  break;
+	case tok_tristate:
+	  printf("tristate ");
+	  break;
+	case tok_dep_tristate:
+	  printf("dep_tristate ");
+	  break;
+	case tok_int:
+	  printf("int ");
+	  break;
+	case tok_comment:
+	  printf("comment ");
+	  break;
+	case tok_menuoption:
+	  printf("menuoption ");
+	  break;
+	case tok_else:
+	  printf("else");
+	  break;
+	case tok_fi:
+	  printf("fi");
+	  break;
+	case tok_if:
+	  printf("if");
+	  break;
+	default:
+	}
+
+      switch(cfg->tok)
+	{
+	case tok_menuoption:
+	case tok_comment:
+	case tok_menuname:
+	  printf("%s\n", cfg->label);
+	  break;
+	case tok_bool:
+	case tok_tristate:
+	case tok_dep_tristate:
+	case tok_int:
+	  printf("%s %s %s\n", cfg->label, cfg->optionname, cfg->dflt);
+	  break;
+	case tok_if:
+	  dump_if(cfg->cond);
+	  break;
+	case tok_nop:
+	  break;
+	default:
+	  printf("\n");
+	}
+    }
+#endif
+
+  return 0;
+
+}
diff -u --recursive --new-file v1.3.34/linux/scripts/tkparse.h linux/scripts/tkparse.h
--- v1.3.34/linux/scripts/tkparse.h	Thu Jan  1 02:00:00 1970
+++ linux/scripts/tkparse.h	Sun Oct 15 18:57:01 1995
@@ -0,0 +1,64 @@
+
+enum token {
+  tok_menuname, 
+  tok_menuoption, 
+  tok_comment, 
+  tok_bool, 
+  tok_tristate, 
+  tok_dep_tristate,
+  tok_nop,
+  tok_if, 
+  tok_else, 
+  tok_fi, 
+  tok_int,
+  tok_unknown
+};
+
+enum operator {
+  op_eq,
+  op_neq,
+  op_and,
+  op_or,
+  op_bang,
+  op_lparen,
+  op_rparen,
+  op_variable,
+  op_kvariable,
+  op_constant,
+  op_nuked
+};
+
+union var
+{
+  char * str;
+  struct kconfig * cfg;
+};
+
+struct condition
+{
+  struct condition * next;
+  enum operator op;
+  union var variable;
+};
+
+#define GLOBAL_WRITTEN 1
+struct kconfig
+{
+  struct kconfig * next;
+  int flags;
+  enum token tok;
+  char   menu_number;
+  char   menu_line;
+  char   submenu_start;
+  char   submenu_end;
+  char * optionname;
+  char * dflt;
+  char * label;
+  union var depend;
+  struct condition * cond;
+};
+
+extern struct kconfig * config;
+extern struct kconfig * clast;
+extern struct kconfig * koption;
+
