lines    added  deleted
linux/CREDITS                             :      24       10        1
linux/Documentation/Configure.help        :      29       15        5
linux/Documentation/filesystems/hpfs.txt  :      39        8        7
linux/Documentation/mtrr.txt              :      30        7        3
linux/MAINTAINERS                         :      12        6        0
linux/arch/i386/Makefile                  :      30        8        3
linux/arch/i386/lib/checksum.S            :      32        8        4
linux/arch/m68k/atari/stdma.c             :       8        1        1
linux/arch/m68k/mac/adb-bus.c             :      29        4        4
linux/arch/mips/kernel/irixsig.c          :       8        1        1
linux/arch/ppc/8xx_io/uart.c              :      19        3        3
linux/arch/sparc/defconfig                :       7        1        0
linux/arch/sparc64/defconfig              :       7        1        0
linux/arch/sparc64/kernel/sys_sparc32.c   :     128      100        4
linux/arch/sparc64/solaris/fs.c           :       5        1        1
linux/arch/sparc64/solaris/ipc.c          :      13        2        1
linux/drivers/acorn/block/fd1772.c        :       8        1        1
linux/drivers/acorn/block/mfmhd.c         :       8        1        1
linux/drivers/ap1000/ap.c                 :       8        1        1
linux/drivers/ap1000/ddv.c                :      17        2        2
linux/drivers/block/Makefile              :       8        1        1
linux/drivers/block/acsi.c                :      44        9        9
linux/drivers/block/ataflop.c             :      44        7       17
linux/drivers/block/blkpg.c               :     288      288        0
linux/drivers/block/cmd646.c              :       5        1        1
linux/drivers/block/floppy.c              :      50        8       15
linux/drivers/block/genhd.c               :     114       19       29
linux/drivers/block/hd.c                  :      58       11       17
linux/drivers/block/ide.c                 :     169        7      124
linux/drivers/block/md.c                  :      91        7       49
linux/drivers/block/paride/pd.c           :      59        9       20
linux/drivers/block/paride/pf.c           :      45        7       19
linux/drivers/block/ps2esdi.c             :      53       10       18
linux/drivers/block/rd.c                  :      32        6        6
linux/drivers/block/xd.c                  :      46       10       13
linux/drivers/cdrom/gscd.c                :       8        1        1
linux/drivers/cdrom/sbpcd.c               :       8        1        1
linux/drivers/char/cyclades.c             :       8        1        1
linux/drivers/char/dn_keyb.c              :       8        1        1
linux/drivers/char/h8.c                   :      17        2        2
linux/drivers/char/keyboard.c             :      50       11        2
linux/drivers/char/pcxx.c                 :       8        1        1
linux/drivers/char/pcxx.h                 :      10        2        2
linux/drivers/char/planb.c                :       8        1        1
linux/drivers/char/planb.h                :      24        3        3
linux/drivers/char/serial167.c            :       8        1        1
linux/drivers/isdn/avmb1/capidev.h        :       8        1        1
linux/drivers/isdn/pcbit/pcbit.h          :       8        1        1
linux/drivers/macintosh/adb.c             :      17        2        2
linux/drivers/macintosh/mac_keyb.c        :       8        1        1
linux/drivers/macintosh/macserial.c       :       8        1        1
linux/drivers/macintosh/macserial.h       :      10        2        2
linux/drivers/misc/parport_init.c         :      21        3        2
linux/drivers/misc/parport_pc.c           :     396       63       50
linux/drivers/net/cosa.c                  :      27        4        3
linux/drivers/net/de620.c                 :       8        1        1
linux/drivers/net/sunhme.c                :       8        1        1
linux/drivers/net/z85230.h                :      10        2        2
linux/drivers/sbus/char/pcikbd.c          :      14        3        1
linux/drivers/scsi/sd_ioctl.c             :      55        7       28
linux/drivers/scsi/sr_ioctl.c             :      62        7       32
linux/drivers/scsi/st.h                   :       8        1        1
linux/drivers/sgi/char/sgiserial.c        :      17        2        2
linux/drivers/sgi/char/sgiserial.h        :      10        2        2
linux/drivers/sgi/char/shmiq.c            :       8        1        1
linux/drivers/sgi/char/usema.c            :       8        1        1
linux/drivers/sound/lowlevel/awe_compat.h :       8        1        1
linux/drivers/sound/lowlevel/awe_wave.c   :       8        1        1
linux/drivers/sound/msnd.h                :      11        3        2
linux/drivers/usb/Config.in               :      12        5        0
linux/drivers/usb/README.ohci             :      31       28        0
linux/drivers/usb/ohci-debug.c            :      48       11        8
linux/drivers/usb/ohci.c                  :    1247      486      226
linux/drivers/usb/ohci.h                  :     127       38       16
linux/fs/ChangeLog                        :      33        0       17
linux/fs/Config.in                        :       8        1        1
linux/fs/affs/namei.c                     :       8        1        1
linux/fs/devices.c                        :       8        1        1
linux/fs/ext2/namei.c                     :       8        1        1
linux/fs/ext2/truncate.c                  :      17        2        2
linux/fs/hfs/bnode.c                      :       8        1        1
linux/fs/hfs/catalog.c                    :      17        2        2
linux/fs/hpfs/alloc.c                     :      34        9        3
linux/fs/hpfs/dentry.c                    :      38        8        8
linux/fs/hpfs/dir.c                       :     159       31       60
linux/fs/hpfs/dnode.c                     :     114       15       23
linux/fs/hpfs/file.c                      :       7        0        1
linux/fs/hpfs/hpfs_fn.h                   :      34        6        2
linux/fs/hpfs/inode.c                     :      52       10        9
linux/fs/hpfs/name.c                      :      29        8        6
linux/fs/hpfs/namei.c                     :     334       61       96
linux/fs/hpfs/super.c                     :      53        7        5
linux/fs/minix/namei.c                    :       8        1        1
linux/fs/namei.c                          :      19        1        5
linux/fs/nfsd/vfs.c                       :       8        2        0
linux/fs/super.c                          :       9        2        1
linux/fs/sysv/namei.c                     :       8        1        1
linux/fs/ufs/namei.c                      :       8        1        1
linux/include/asm-alpha/processor.h       :       8        1        1
linux/include/asm-alpha/semaphore.h       :       8        1        1
linux/include/asm-arm/semaphore.h         :       8        1        1
linux/include/asm-m68k/adb_mouse.h        :       8        1        1
linux/include/asm-m68k/atari_joystick.h   :       8        1        1
linux/include/asm-m68k/mac_mouse.h        :       8        1        1
linux/include/asm-m68k/semaphore.h        :       8        1        1
linux/include/asm-mips/semaphore.h        :       8        1        1
linux/include/asm-ppc/adb_mouse.h         :       8        1        1
linux/include/asm-ppc/semaphore.h         :       8        1        1
linux/include/asm-sparc/io.h              :       5        1        1
linux/include/asm-sparc64/hdreg.h         :       5        1        1
linux/include/asm-sparc64/ide.h           :      14        3        1
linux/include/asm-sparc64/io.h            :       5        1        1
linux/include/linux/blk.h                 :      12        0        6
linux/include/linux/blkpg.h               :      64       64        0
linux/include/linux/fs.h                  :      30        8        2
linux/include/linux/genhd.h               :      38        7        9
linux/include/linux/hpfs_fs_sb.h          :      24        3        3
linux/include/linux/istallion.h           :      12        3        3
linux/include/linux/lp_m68k.h             :       8        1        1
linux/include/linux/netdevice.h           :       8        1        1
linux/include/linux/parport.h             :       7        1        0
linux/include/linux/parport_pc.h          :     126       24       24
linux/include/linux/rpcsock.h             :      19        3        3
linux/include/linux/serial167.h           :      10        2        2
linux/include/linux/stallion.h            :      10        2        2
linux/include/linux/swap.h                :       7        1        0
linux/include/linux/umsdos_fs_i.h         :       8        1        1
linux/kernel/ksyms.c                      :      15        2        0
linux/mm/mlock.c                          :      14        4        3
linux/mm/swapfile.c                       :      18       12        0
linux/net/core/filter.c                   :       8        1        1
linux/net/ipv4/tcp_timer.c                :      19        1        5
linux/net/ipv6/exthdrs.c                  :       8        1        1
linux/net/netlink/af_netlink.c            :       8        1        1
-- 
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.
#!/bin/sh
# this is part 2 of a 4 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.3 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.3'
else
echo 'x - continuing with patch-2.3.3'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.3' &&
@@ -279,7 +279,8 @@
X 		u_char type;
X 
X 		/* the XOR below used to be an OR */
-		int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
+		int shift_final = (shift_state | kbd->slockstate) ^
+		    kbd->lockstate;
X 		ushort *key_map = key_maps[shift_final];
X 
X 		if (key_map != NULL) {
@@ -311,6 +312,7 @@
X 			/* we have at least to update shift_state */
X #if 1			/* how? two almost equivalent choices follow */
X 			compute_shiftstate();
+			kbd->slockstate = 0; /* play it safe */
X #else
X 			keysym = U(plain_map[keycode]);
X 			type = KTYP(keysym);
@@ -472,6 +474,7 @@
X 
X static void boot_it(void)
X {
+	if (kbd->slockstate & ~shift_state) return;
X 	ctrl_alt_del();
X }
X 
@@ -741,7 +744,7 @@
X 	    for(j=0; j<BITS_PER_LONG; j++,k++)
X 	      if(test_bit(k, key_down)) {
X 		sym = U(plain_map[k]);
-		if(KTYP(sym) == KT_SHIFT) {
+		if(KTYP(sym) == KT_SHIFT || KTYP(sym) == KT_SLOCK) {
X 		  val = KVAL(sym);
X 		  if (val == KVAL(K_CAPSSHIFT))
X 		    val = KVAL(K_SHIFT);
@@ -793,9 +796,15 @@
X 
X static void do_slock(unsigned char value, char up_flag)
X {
+	do_shift(value,up_flag);
X 	if (up_flag || rep)
X 		return;
X 	chg_vc_kbd_slock(kbd, value);
+	/* try to make Alt, oops, AltGr and such work */
+	if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
+		kbd->slockstate = 0;
+		chg_vc_kbd_slock(kbd, value);
+	}
X }
X 
X /*
diff -u --recursive --new-file v2.3.2/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.3.2/linux/drivers/char/pcxx.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/char/pcxx.c	Sat May 15 15:05:36 1999
@@ -326,7 +326,7 @@
X 
X static int pcxx_waitcarrier(struct tty_struct *tty,struct file *filp,struct channel *info)
X {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 	int	retval = 0;
X 	int	do_clocal = 0;
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/char/pcxx.h linux/drivers/char/pcxx.h
--- v2.3.2/linux/drivers/char/pcxx.h	Sun Apr 13 10:18:20 1997
+++ linux/drivers/char/pcxx.h	Sat May 15 15:05:36 1999
@@ -88,8 +88,8 @@
X 	int							blocked_open;
X 	int							close_delay;
X 	int							event;
-	struct wait_queue			*open_wait;
-	struct wait_queue			*close_wait;
+	wait_queue_head_t			open_wait;
+	wait_queue_head_t			close_wait;
X 	struct tq_struct			tqueue;
X 							/* ------------ Async control data ------------- */
X 	unchar						modemfake;      /* Modem values to be forced */
diff -u --recursive --new-file v2.3.2/linux/drivers/char/planb.c linux/drivers/char/planb.c
--- v2.3.2/linux/drivers/char/planb.c	Mon May 10 10:17:28 1999
+++ linux/drivers/char/planb.c	Sat May 15 15:05:36 1999
@@ -379,7 +379,7 @@
X 
X static void __planb_wait(struct planb *pb)
X {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 
X 	add_wait_queue(&pb->lockq, &wait);
X repeat:
diff -u --recursive --new-file v2.3.2/linux/drivers/char/planb.h linux/drivers/char/planb.h
--- v2.3.2/linux/drivers/char/planb.h	Fri May  7 11:05:30 1999
+++ linux/drivers/char/planb.h	Sat May 15 15:05:36 1999
@@ -175,7 +175,7 @@
X 	unsigned int tab_size;
X 	int     maxlines;
X 	int lock;
-	struct wait_queue *lockq;
+	wait_queue_head_t lockq;
X 	unsigned int	irq;			/* interrupt number */
X 	volatile unsigned int intr_mask;
X 
@@ -190,13 +190,13 @@
X 	unsigned long ch1_cmd_phys;
X 	volatile unsigned char *mask;		/* Clipmask buffer */
X 	int suspend;
-	struct wait_queue *suspendq;
+	wait_queue_head_t suspendq;
X 	struct planb_suspend suspended;
X 	int	cmd_buff_inited;		/* cmd buffer inited? */
X 
X 	int grabbing;
X 	unsigned int gcount;
-	struct wait_queue *capq;
+	wait_queue_head_t capq;
X 	int last_fr;
X 	int prev_last_fr;
X         unsigned char *fbuffer;
diff -u --recursive --new-file v2.3.2/linux/drivers/char/serial167.c linux/drivers/char/serial167.c
--- v2.3.2/linux/drivers/char/serial167.c	Thu Nov  5 09:58:43 1998
+++ linux/drivers/char/serial167.c	Sat May 15 15:05:36 1999
@@ -2007,7 +2007,7 @@
X block_til_ready(struct tty_struct *tty, struct file * filp,
X                            struct cyclades_port *info)
X {
-  struct wait_queue wait = { current, NULL };
+  DECLARE_WAITQUEUE(wait, current);
X   unsigned long flags;
X   int channel;
X   int retval;
diff -u --recursive --new-file v2.3.2/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h
--- v2.3.2/linux/drivers/isdn/avmb1/capidev.h	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/avmb1/capidev.h	Sat May 15 15:05:36 1999
@@ -22,7 +22,7 @@
X 	int is_registered;
X 	__u16 applid;
X 	struct sk_buff_head recv_queue;
-	struct wait_queue *recv_wait;
+	wait_queue_head_t recv_wait;
X 	__u16 errcode;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/isdn/pcbit/pcbit.h linux/drivers/isdn/pcbit/pcbit.h
--- v2.3.2/linux/drivers/isdn/pcbit/pcbit.h	Tue Aug  4 10:31:59 1998
+++ linux/drivers/isdn/pcbit/pcbit.h	Sat May 15 15:05:36 1999
@@ -68,7 +68,7 @@
X 	struct frame_buf *write_queue;
X 
X 	/* Protocol start */
-	struct wait_queue *set_running_wq;
+	wait_queue_head_t set_running_wq;
X 	struct timer_list set_running_timer;
X 
X 	struct timer_list error_recover_timer;
diff -u --recursive --new-file v2.3.2/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.3.2/linux/drivers/macintosh/adb.c	Thu Apr 29 12:53:48 1999
+++ linux/drivers/macintosh/adb.c	Sat May 15 15:05:36 1999
@@ -375,7 +375,7 @@
X 	spinlock_t	lock;
X 	atomic_t	n_pending;
X 	struct adb_request *completed;
-	struct wait_queue *wait_queue;
+	wait_queue_head_t wait_queue;
X 	int		inuse;
X };
X 
@@ -458,7 +458,7 @@
X 	int ret;
X 	struct adbdev_state *state = file->private_data;
X 	struct adb_request *req;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 	unsigned long flags;
X 
X 	if (count < 2)
diff -u --recursive --new-file v2.3.2/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.3.2/linux/drivers/macintosh/mac_keyb.c	Thu Apr 29 12:53:48 1999
+++ linux/drivers/macintosh/mac_keyb.c	Sat May 15 15:05:36 1999
@@ -251,7 +251,7 @@
X extern int console_loglevel;
X 
X extern struct kbd_struct kbd_table[];
-extern struct wait_queue * keypress_wait;
+extern struct wait_queue_head_t keypress_wait;
X 
X extern void handle_scancode(unsigned char, int);
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.2/linux/drivers/macintosh/macserial.c	Thu Apr 29 12:53:48 1999
+++ linux/drivers/macintosh/macserial.c	Sat May 15 15:05:36 1999
@@ -1595,7 +1595,7 @@
X static int block_til_ready(struct tty_struct *tty, struct file * filp,
X 			   struct mac_serial *info)
X {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait,current);
X 	int		retval;
X 	int		do_clocal = 0;
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h
--- v2.3.2/linux/drivers/macintosh/macserial.h	Wed Mar 10 21:48:46 1999
+++ linux/drivers/macintosh/macserial.h	Sat May 15 15:05:36 1999
@@ -153,8 +153,8 @@
X 	struct tq_struct	tqueue_hangup;
X 	struct termios		normal_termios;
X 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
X };
X 
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- v2.3.2/linux/drivers/misc/parport_init.c	Tue May 11 09:55:49 1999
+++ linux/drivers/misc/parport_init.c	Sun May 16 10:55:21 1999
@@ -20,10 +20,11 @@
X 
X #ifndef MODULE
X static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
+static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
X static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
X static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
X 
-extern int parport_pc_init(int *io, int *irq, int *dma);
+extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
X extern int parport_ax_init(void);
X 
X static int parport_setup_ptr __initdata = 0;
@@ -121,7 +122,7 @@
X 	parport_proc_init();
X #endif
X #ifdef CONFIG_PARPORT_PC
-	parport_pc_init(io, irq, dma);
+	parport_pc_init(io, io_hi, irq, dma);
X #endif
X #ifdef CONFIG_PARPORT_AX
X 	parport_ax_init();
diff -u --recursive --new-file v2.3.2/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.3.2/linux/drivers/misc/parport_pc.c	Mon May 10 10:26:31 1999
+++ linux/drivers/misc/parport_pc.c	Sun May 16 10:10:00 1999
@@ -36,6 +36,7 @@
X 
X #include <linux/config.h>
X #include <linux/module.h>
+#include <linux/init.h>
X #include <linux/sched.h>
X #include <linux/delay.h>
X #include <linux/errno.h>
@@ -53,7 +54,7 @@
X    than PARPORT_MAX (in <linux/parport.h>).  */
X #define PARPORT_PC_MAX_PORTS  8
X 
-static int user_specified = 0;
+static int user_specified __initdata = 0;
X 
X static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
@@ -62,27 +63,27 @@
X 
X void parport_pc_write_epp(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+EPPDATA);
+	outb(d, EPPDATA(p));
X }
X 
X unsigned char parport_pc_read_epp(struct parport *p)
X {
-	return inb(p->base+EPPDATA);
+	return inb(EPPDATA(p));
X }
X 
X void parport_pc_write_epp_addr(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+EPPADDR);
+	outb(d, EPPADDR(p));
X }
X 
X unsigned char parport_pc_read_epp_addr(struct parport *p)
X {
-	return inb(p->base+EPPADDR);
+	return inb(EPPADDR(p));
X }
X 
X int parport_pc_check_epp_timeout(struct parport *p)
X {
-	if (!(inb(p->base+STATUS) & 1))
+	if (!(inb(STATUS(p)) & 1))
X 		return 0;
X 	parport_pc_epp_clear_timeout(p);
X 	return 1;
@@ -90,24 +91,24 @@
X 
X unsigned char parport_pc_read_configb(struct parport *p)
X {
-	return inb(p->base+CONFIGB);
+	return inb(CONFIGB(p));
X }
X 
X void parport_pc_write_data(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+DATA);
+	outb(d, DATA(p));
X }
X 
X unsigned char parport_pc_read_data(struct parport *p)
X {
-	return inb(p->base+DATA);
+	return inb(DATA(p));
X }
X 
X void parport_pc_write_control(struct parport *p, unsigned char d)
X {
X 	struct parport_pc_private *priv = p->private_data;
X 	priv->ctr = d;/* update soft copy */
-	outb(d, p->base+CONTROL);
+	outb(d, CONTROL(p));
X }
X 
X unsigned char parport_pc_read_control(struct parport *p)
@@ -121,34 +122,34 @@
X 	struct parport_pc_private *priv = p->private_data;
X 	unsigned char ctr = priv->ctr;
X 	ctr = (ctr & ~mask) ^ val;
-	outb (ctr, p->base+CONTROL);
+	outb (ctr, CONTROL(p));
X 	return priv->ctr = ctr; /* update soft copy */
X }
X 
X void parport_pc_write_status(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+STATUS);
+	outb(d, STATUS(p));
X }
X 
X unsigned char parport_pc_read_status(struct parport *p)
X {
-	return inb(p->base+STATUS);
+	return inb(STATUS(p));
X }
X 
X void parport_pc_write_econtrol(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+ECONTROL);
+	outb(d, ECONTROL(p));
X }
X 
X unsigned char parport_pc_read_econtrol(struct parport *p)
X {
-	return inb(p->base+ECONTROL);
+	return inb(ECONTROL(p));
X }
X 
X unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask,  unsigned char val)
X {
-	unsigned char old = inb(p->base+ECONTROL);
-	outb(((old & ~mask) ^ val), p->base+ECONTROL);
+	unsigned char old = inb(ECONTROL(p));
+	outb(((old & ~mask) ^ val), ECONTROL(p));
X 	return old;
X }
X 
@@ -159,12 +160,12 @@
X 
X void parport_pc_write_fifo(struct parport *p, unsigned char v)
X {
-	outb (v, p->base+CONFIGA);
+	outb (v, CONFIGA(p));
X }
X 
X unsigned char parport_pc_read_fifo(struct parport *p)
X {
-	return inb (p->base+CONFIGA);
+	return inb (CONFIGA(p));
X }
X 
X void parport_pc_disable_irq(struct parport *p)
@@ -183,7 +184,7 @@
X 		free_irq(p->irq, p);
X 	release_region(p->base, p->size);
X 	if (p->modes & PARPORT_MODE_PCECR)
-		release_region(p->base+0x400, 3);
+		release_region(p->base_hi, 3);
X }
X 
X int parport_pc_claim_resources(struct parport *p)
@@ -195,7 +196,7 @@
X 			return err;
X 	request_region(p->base, p->size, p->name);
X 	if (p->modes & PARPORT_MODE_PCECR)
-		request_region(p->base+0x400, 3, p->name);
+		request_region(p->base_hi, 3, p->name);
X 	return 0;
X }
X 
@@ -223,8 +224,8 @@
X {
X 	size_t got = 0;
X 	for (; got < length; got++) {
-		*((char*)buf)++ = inb (p->base+EPPDATA);
-		if (inb (p->base+STATUS) & 0x01)
+		*((char*)buf)++ = inb (EPPDATA(p));
+		if (inb (STATUS(p)) & 0x01)
X 			break;
X 	}
X 	return got;
@@ -234,8 +235,8 @@
X {
X 	size_t written = 0;
X 	for (; written < length; written++) {
-		outb (*((char*)buf)++, p->base+EPPDATA);
-		if (inb (p->base+STATUS) & 0x01)
+		outb (*((char*)buf)++, EPPDATA(p));
+		if (inb (STATUS(p)) & 0x01)
X 			break;
X 	}
X 	return written;
@@ -350,7 +351,7 @@
X /*
X  * Checks for port existence, all ports support SPP MODE
X  */
-static int parport_SPP_supported(struct parport *pb)
+static int __init parport_SPP_supported(struct parport *pb)
X {
X 	unsigned char r, w;
X 
@@ -370,11 +371,11 @@
X 	 * allow reads, so read_control just returns a software
X 	 * copy. Some ports _do_ allow reads, so bypass the software
X 	 * copy here.  In addition, some bits aren't writable. */
-	r = inb (pb->base+CONTROL);
+	r = inb (CONTROL (pb));
X 	if ((r & 0x3f) == w) {
X 		w = 0xe;
X 		parport_pc_write_control (pb, w);
-		r = inb (pb->base+CONTROL);
+		r = inb (CONTROL(pb));
X 		parport_pc_write_control (pb, 0xc);
X 		if ((r & 0x3f) == w)
X 			return PARPORT_MODE_PCSPP;
@@ -425,7 +426,7 @@
X  * We will write 0x2c to ECR and 0xcc to CTR since both of these
X  * values are "safe" on the CTR since bits 6-7 of CTR are unused.
X  */
-static int parport_ECR_present(struct parport *pb)
+static int __init parport_ECR_present(struct parport *pb)
X {
X 	unsigned char r;
X 
@@ -458,7 +459,7 @@
X 	return 0;
X }
X 
-static int parport_ECP_supported(struct parport *pb)
+static int __init parport_ECP_supported(struct parport *pb)
X {
X 	int i;
X 	unsigned char oecr;
@@ -493,7 +494,7 @@
X  *	or writing a 1 to the bit (SMC, UMC, WinBond), others ???
X  *	This bit is always high in non EPP modes.
X  */
-static int parport_EPP_supported(struct parport *pb)
+static int __init parport_EPP_supported(struct parport *pb)
X {
X 	/* If EPP timeout bit clear then EPP available */
X 	if (!parport_pc_epp_clear_timeout(pb))
@@ -514,7 +515,7 @@
X 	return 0;
X }
X 
-static int parport_ECPEPP_supported(struct parport *pb)
+static int __init parport_ECPEPP_supported(struct parport *pb)
X {
X 	int mode;
X 	unsigned char oecr;
@@ -550,7 +551,7 @@
X  * be misdetected here is rather academic. 
X  */
X 
-static int parport_PS2_supported(struct parport *pb)
+static int __init parport_PS2_supported(struct parport *pb)
X {
X 	int ok = 0;
X 	unsigned char octr = parport_pc_read_control(pb);
@@ -570,7 +571,7 @@
X 	return ok?PARPORT_MODE_PCPS2:0;
X }
X 
-static int parport_ECPPS2_supported(struct parport *pb)
+static int __init parport_ECPPS2_supported(struct parport *pb)
X {
X 	int mode;
X 	unsigned char oecr;
@@ -590,7 +591,7 @@
X /* --- IRQ detection -------------------------------------- */
X 
X /* Only if supports ECP mode */
-static int programmable_irq_support(struct parport *pb)
+static int __init programmable_irq_support(struct parport *pb)
X {
X 	int irq, intrLine;
X 	unsigned char oecr = parport_pc_read_econtrol(pb);
@@ -607,7 +608,7 @@
X 	return irq;
X }
X 
-static int irq_probe_ECP(struct parport *pb)
+static int __init irq_probe_ECP(struct parport *pb)
X {
X 	int irqs, i;
X 
@@ -634,7 +635,7 @@
X  * This detection seems that only works in National Semiconductors
X  * This doesn't work in SMC, LGS, and Winbond 
X  */
-static int irq_probe_EPP(struct parport *pb)
+static int __init irq_probe_EPP(struct parport *pb)
X {
X 	int irqs;
X 	unsigned char octr = parport_pc_read_control(pb);
@@ -675,7 +676,7 @@
X 	return pb->irq;
X }
X 
-static int irq_probe_SPP(struct parport *pb)
+static int __init irq_probe_SPP(struct parport *pb)
X {
X 	int irqs;
X 	unsigned char octr = parport_pc_read_control(pb);
@@ -723,7 +724,7 @@
X  * When ECP is available we can autoprobe for IRQs.
X  * NOTE: If we can autoprobe it, we can register the IRQ.
X  */
-static int parport_irq_probe(struct parport *pb)
+static int __init parport_irq_probe(struct parport *pb)
X {
X 	if (pb->modes & PARPORT_MODE_PCECR) {
X 		pb->irq = programmable_irq_support(pb);
@@ -754,7 +755,9 @@
X 
X /* --- Initialisation code -------------------------------- */
X 
-static int probe_one_port(unsigned long int base, int irq, int dma)
+static int __init probe_one_port(unsigned long int base,
+				 unsigned long int base_hi,
+				 int irq, int dma)
X {
X 	struct parport *p;
X 	int probedirq = PARPORT_IRQ_NONE;
@@ -770,8 +773,9 @@
X 		return 0;
X 	}
X 	((struct parport_pc_private *) (p->private_data))->ctr = 0xc;
+	p->base_hi = base_hi;
X 	if (p->base != 0x3bc) {
-		if (!check_region(base+0x400,3)) {
+		if (base_hi && !check_region(base_hi,3)) {
X 			p->modes |= parport_ECR_present(p);	
X 			p->modes |= parport_ECP_supported(p);
X 			p->modes |= parport_ECPPS2_supported(p);
@@ -791,6 +795,8 @@
X 	p->size = (p->modes & (PARPORT_MODE_PCEPP 
X 			       | PARPORT_MODE_PCECPEPP))?8:3;
X 	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+	if (p->base_hi && (p->modes & PARPORT_MODE_PCECR))
+		printk (" (0x%lx)", p->base_hi);
X 	if (p->irq == PARPORT_IRQ_AUTO) {
X 		p->irq = PARPORT_IRQ_NONE;
X 		parport_irq_probe(p);
@@ -829,11 +835,14 @@
X 	/* Done probing.  Now put the port into a sensible start-up state. */
X 	if (p->modes & PARPORT_MODE_PCECR)
X 		/*
-		 * Put the ECP detected port in the more SPP like mode.
+		 * Put the ECP detected port in PS2 mode.
X 		 */
-		parport_pc_write_econtrol(p, 0x0);
-	parport_pc_write_control(p, 0xc);
+		parport_pc_write_econtrol(p, 0x24);
X 	parport_pc_write_data(p, 0);
+	parport_pc_write_control(p, 0x8);
+	udelay (50);
+	parport_pc_write_control(p, 0xc);
+	udelay (50);
X 
X 	if (parport_probe_hook)
X 		(*parport_probe_hook)(p);
@@ -841,20 +850,22 @@
X 	return 1;
X }
X 
-int parport_pc_init(int *io, int *irq, int *dma)
+int __init parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
X {
X 	int count = 0, i = 0;
X 	if (io && *io) {
X 		/* Only probe the ports we were given. */
X 		user_specified = 1;
X 		do {
-			count += probe_one_port(*(io++), *(irq++), *(dma++));
+			if (!*io_hi) *io_hi = 0x400 + *io;
+			count += probe_one_port(*(io++), *(io_hi++),
+						*(irq++), *(dma++));
X 		} while (*io && (++i < PARPORT_PC_MAX_PORTS));
X 	} else {
X 		/* Probe all the likely ports. */
-		count += probe_one_port(0x3bc, irq[0], dma[0]);
-		count += probe_one_port(0x378, irq[0], dma[0]);
-		count += probe_one_port(0x278, irq[0], dma[0]);
+		count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
+		count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
+		count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
X 	}
X 
X 	return count;
@@ -862,10 +873,12 @@
X 
X #ifdef MODULE
X static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
X static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
X static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
X static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
X MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(io_hi, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
X MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
X MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
X 
@@ -877,7 +890,7 @@
X 	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
X 	parport_parse_irqs(i, irq, irqval);
X 
-	return (parport_pc_init(io, irqval, dma)?0:1);
+	return (parport_pc_init(io, io_hi, irqval, dma)?0:1);
X }
X 
X void cleanup_module(void)
diff -u --recursive --new-file v2.3.2/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.3.2/linux/drivers/net/cosa.c	Sun Mar  7 15:47:46 1999
+++ linux/drivers/net/cosa.c	Sat May 15 15:05:36 1999
@@ -126,7 +126,8 @@
X 	struct semaphore rsem, wsem;
X 	char *rxdata;
X 	int rxsize;
-	struct wait_queue *txwaitq, *rxwaitq;
+	wait_queue_head_t txwaitq; 
+	wait_queue_head_t rxwaitq;
X 	int tx_status, rx_status;
X 
X 	/* SPPP/HDLC device parts */
@@ -762,7 +763,7 @@
X static ssize_t cosa_read(struct file *file,
X 	char *buf, size_t count, loff_t *ppos)
X {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 	int flags;
X 	struct channel_data *chan = (struct channel_data *)file->private_data;
X 	struct cosa_data *cosa = chan->cosa;
@@ -833,7 +834,7 @@
X 	const char *buf, size_t count, loff_t *ppos)
X {
X 	struct channel_data *chan = (struct channel_data *)file->private_data;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 	struct cosa_data *cosa = chan->cosa;
X 	unsigned int flags;
X 	char *kbuf;
diff -u --recursive --new-file v2.3.2/linux/drivers/net/de620.c linux/drivers/net/de620.c
--- v2.3.2/linux/drivers/net/de620.c	Mon Mar  2 11:55:41 1998
+++ linux/drivers/net/de620.c	Sat May 15 23:43:04 1999
@@ -664,7 +664,7 @@
X 	if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
X 		/* Ouch... Forget it! Skip all and start afresh... */
X 		printk("%s: Ring overrun? Restoring...\n", dev->name);
-		/* You win some, you loose some. And sometimes plenty... */
+		/* You win some, you lose some. And sometimes plenty... */
X 		adapter_init(dev);
X 		((struct net_device_stats *)(dev->priv))->rx_over_errors++;
X 		return 0;
diff -u --recursive --new-file v2.3.2/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.2/linux/drivers/net/sunhme.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/net/sunhme.c	Sat May 15 11:12:09 1999
@@ -1834,7 +1834,7 @@
X #define RXD(x)
X #endif
X 
-/* Originally I use to handle the allocation failure by just giving back just
+/* Originally I used to handle the allocation failure by just giving back just
X  * that one ring buffer to the happy meal.  Problem is that usually when that
X  * condition is triggered, the happy meal expects you to do something reasonable
X  * with all of the packets it has DMA'd in.  So now I just drop the entire
diff -u --recursive --new-file v2.3.2/linux/drivers/net/z85230.h linux/drivers/net/z85230.h
--- v2.3.2/linux/drivers/net/z85230.h	Sat Oct 17 15:33:45 1998
+++ linux/drivers/net/z85230.h	Sat May 15 15:05:36 1999
@@ -331,8 +331,8 @@
X 	int			line;		/* Minor number */
X 	struct termios		normal_termios;	/* Terminal settings */
X 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;	/* Tasks waiting to open */
-	struct wait_queue	*close_wait;	/* and for close to end */
+	wait_queue_head_t	open_wait;	/* Tasks waiting to open */
+	wait_queue_head_t	close_wait;	/* and for close to end */
X 	unsigned long		event;		/* Pending events */
X 	int			fdcount;    	/* # of fd on device */
X 	int			blocked_open;	/* # of blocked opens */
diff -u --recursive --new-file v2.3.2/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.2/linux/drivers/sbus/char/pcikbd.c	Fri May 14 18:55:21 1999
+++ linux/drivers/sbus/char/pcikbd.c	Sun May 16 19:15:57 1999
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.28 1999/05/12 11:15:05 davem Exp $
+/* $Id: pcikbd.c,v 1.29 1999/05/16 13:47:53 ecd Exp $
X  * pcikbd.c: Ultra/AX PC keyboard support.
X  *
X  * Copyright (C) 1997  Eddie C. Dost  (e...@skynet.be)
@@ -982,6 +982,8 @@
X 		return -ENOMEM;
X 	}
X 	memset(queue, 0, sizeof(*queue));
+
+	init_waitqueue_head(&queue->proc_list);
X 
X 	if (request_irq(pcimouse_irq, &pcimouse_interrupt,
X 		        SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
diff -u --recursive --new-file v2.3.2/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v2.3.2/linux/drivers/scsi/sd_ioctl.c	Wed Feb 24 16:27:54 1999
+++ linux/drivers/scsi/sd_ioctl.c	Sat May 15 23:43:04 1999
@@ -15,6 +15,7 @@
X 
X #define MAJOR_NR	SCSI_DISK0_MAJOR
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X #include "scsi.h"
X #include <scsi/scsi_ioctl.h>
X #include "hosts.h"
@@ -79,41 +80,19 @@
X 		 (long *) arg);
X 	return 0;
X 
+    case BLKROSET:
+    case BLKROGET:
X     case BLKRASET:
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-	if(!(inode->i_rdev)) return -EINVAL;
-	if(arg > 0xff) return -EINVAL;
-	read_ahead[MAJOR(inode->i_rdev)] = arg;
-	return 0;
-
X     case BLKRAGET:
-	if (!arg)
-		return -EINVAL;
-	error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-	if (error)
-	    return error;
-	put_user(read_ahead[MAJOR(inode->i_rdev)], (long *) arg);
-	return 0;
-
X     case BLKFLSBUF:
-	if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-	if(!(inode->i_rdev)) return -EINVAL;
-	fsync_dev(inode->i_rdev);
-	invalidate_buffers(inode->i_rdev);
-	return 0;
-	
+    case BLKSSZGET:
+    case BLKPG:
+	return blk_ioctl(inode->i_rdev, cmd, arg);
+
X     case BLKRRPART: /* Re-read partition tables */
X         if (!capable(CAP_SYS_ADMIN))
X                 return -EACCES;
X 	return revalidate_scsidisk(dev, 1);
-
-    case BLKSSZGET:
-	/* Block size of media */
-	return put_user(blksize_size[MAJOR(dev)][MINOR(dev)&0x0F],
-		(int *)arg);
-				
-    RO_IOCTLS(dev, arg);
X 
X     default:
X 	return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
diff -u --recursive --new-file v2.3.2/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.3.2/linux/drivers/scsi/sr_ioctl.c	Sat May 15 23:46:03 1999
+++ linux/drivers/scsi/sr_ioctl.c	Sat May 15 23:43:04 1999
@@ -7,6 +7,7 @@
X #include <linux/string.h>
X 
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X #include "scsi.h"
X #include "hosts.h"
X #include <scsi/scsi_ioctl.h>
@@ -768,7 +769,7 @@
X int sr_dev_ioctl(struct cdrom_device_info *cdi,
X                  unsigned int cmd, unsigned long arg)
X {
-    int target, err;
+    int target;
X     
X     target = MINOR(cdi->dev);
X     
@@ -855,40 +856,14 @@
X         spin_unlock_irqrestore(&io_request_lock, flags);
X         return rc;
X     }
-    case BLKRAGET:
-	if (!arg)
-		return -EINVAL;
-	err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-	if (err)
-		return err;
-	put_user(read_ahead[MAJOR(cdi->dev)], (long *) arg);
-	return 0;
X 
+    case BLKROSET:
+    case BLKROGET:
X     case BLKRASET:
-	if(!capable(CAP_SYS_ADMIN))
-        	return -EACCES;
-	if(!(cdi->dev))
-        	return -EINVAL;
-	if(arg > 0xff)
-        	return -EINVAL;
-	read_ahead[MAJOR(cdi->dev)] = arg;
-	return 0;
-
-    case BLKSSZGET:
-	/* Block size of media */
-	return put_user(blksize_size[MAJOR(cdi->dev)][MINOR(cdi->dev)],
-		(int *)arg);
-
-    RO_IOCTLS(cdi->dev,arg);
-
+    case BLKRAGET:
X     case BLKFLSBUF:
-	if(!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-	if(!(cdi->dev))
-		return -EINVAL;
-	fsync_dev(cdi->dev);
-	invalidate_buffers(cdi->dev);
-	return 0;
+    case BLKSSZGET:
+	return blk_ioctl(cdi->dev, cmd, arg);
X 
X     default:
X 	return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
diff -u --recursive --new-file v2.3.2/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v2.3.2/linux/drivers/scsi/st.h	Sun Sep  6 09:48:30 1998
+++ linux/drivers/scsi/st.h	Sat May 15 15:05:36 1999
@@ -65,7 +65,7 @@
X typedef struct {
X   kdev_t devt;
X   unsigned capacity;
-  struct wait_queue * waiting;
+  wait_queue_head_t waiting;
X   Scsi_Device* device;
X   struct semaphore sem;
X   ST_buffer * buffer;
diff -u --recursive --new-file v2.3.2/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c
--- v2.3.2/linux/drivers/sgi/char/sgiserial.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/sgi/char/sgiserial.c	Sat May 15 15:05:36 1999
@@ -33,7 +33,7 @@
X #define NUM_SERIAL 1     /* One chip on board. */
X #define NUM_CHANNELS (NUM_SERIAL * 2)
X 
-extern struct wait_queue * keypress_wait;
+extern struct wait_queue_head_t keypress_wait;
X 
X struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, };
X struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, };
@@ -1519,7 +1519,7 @@
X static int block_til_ready(struct tty_struct *tty, struct file * filp,
X 			   struct sgi_serial *info)
X {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 	int		retval;
X 	int		do_clocal = 0;
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/sgi/char/sgiserial.h linux/drivers/sgi/char/sgiserial.h
--- v2.3.2/linux/drivers/sgi/char/sgiserial.h	Wed Dec 10 10:31:11 1997
+++ linux/drivers/sgi/char/sgiserial.h	Sat May 15 15:05:36 1999
@@ -158,8 +158,8 @@
X 	struct tq_struct	tqueue_hangup;
X 	struct termios		normal_termios;
X 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
X };
X 
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c
--- v2.3.2/linux/drivers/sgi/char/shmiq.c	Mon Aug 24 13:14:10 1998
+++ linux/drivers/sgi/char/shmiq.c	Sat May 15 15:05:36 1999
@@ -82,7 +82,7 @@
X 	int    events;
X 	int    mapped;
X 	
-	struct wait_queue    *proc_list;
+	wait_queue_head_t     proc_list;
X 	struct fasync_struct *fasync;
X } shmiqs [MAX_SHMI_QUEUES];
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c
--- v2.3.2/linux/drivers/sgi/char/usema.c	Mon Aug 24 13:02:44 1998
+++ linux/drivers/sgi/char/usema.c	Sat May 15 15:05:36 1999
@@ -39,7 +39,7 @@
X 
X struct irix_usema {
X 	struct file *filp;
-	struct wait_queue *proc_list;
+	wait_queue_head_t proc_list;
X };
X 
X static int
diff -u --recursive --new-file v2.3.2/linux/drivers/sound/lowlevel/awe_compat.h linux/drivers/sound/lowlevel/awe_compat.h
--- v2.3.2/linux/drivers/sound/lowlevel/awe_compat.h	Sun Mar  7 15:22:06 1999
+++ linux/drivers/sound/lowlevel/awe_compat.h	Sat May 15 15:05:36 1999
@@ -245,7 +245,7 @@
X #endif /* AWE_MODULE_SUPPORT */
X 
X #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
-inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+inline static void interruptible_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout)
X {
X 	current->timeout = jiffies + timeout;
X 	interruptible_sleep_on(q);
diff -u --recursive --new-file v2.3.2/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.3.2/linux/drivers/sound/lowlevel/awe_wave.c	Sun Mar  7 15:22:06 1999
+++ linux/drivers/sound/lowlevel/awe_wave.c	Sat May 15 15:05:36 1999
@@ -979,7 +979,7 @@
X }
X #else
X 
-static struct wait_queue *awe_sleeper = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(awe_sleeper);
X static void awe_wait(unsigned short delay)
X {
X 	interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
diff -u --recursive --new-file v2.3.2/linux/drivers/sound/msnd.h linux/drivers/sound/msnd.h
--- v2.3.2/linux/drivers/sound/msnd.h	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/msnd.h	Sat May 15 15:05:37 1999
@@ -231,8 +231,9 @@
X #define F_EXT_MIDI_INUSE		9
X #define F_INT_MIDI_INUSE		10
X #define F_DISABLE_WRITE_NDELAY		11
-	struct wait_queue *writeblock, *readblock;
-	struct wait_queue *writeflush;
+	wait_queue_head_t writeblock;
+	wait_queue_head_t readblock;
+	wait_queue_head_t writeflush;
X #ifndef LINUX20
X 	spinlock_t lock;
X #endif
diff -u --recursive --new-file v2.3.2/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.2/linux/drivers/usb/Config.in	Sat May 15 23:46:03 1999
+++ linux/drivers/usb/Config.in	Sun May 16 22:23:31 1999
@@ -14,7 +14,12 @@
X tristate 'Support for USB (EXPERIMENTAL!)' CONFIG_USB
X if [ ! "$CONFIG_USB" = "n" ]; then
X   bool 'UHCI (intel PIIX4 and others) support?' CONFIG_USB_UHCI
+
X   bool 'OHCI (compaq and some others) support?' CONFIG_USB_OHCI
+  if [ "$CONFIG_USB_OHCI" = "y" ]; then
+     bool '  Enable tons of OHCI debugging output?' CONFIG_USB_OHCI_DEBUG
+  fi
+
X   bool 'OHCI-HCD (other OHCI opt. Virt. Root Hub) support?' CONFIG_USB_OHCI_HCD
X   if [ "$CONFIG_USB_OHCI_HCD" = "y" ]; then
X      bool 'OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB
diff -u --recursive --new-file v2.3.2/linux/drivers/usb/README.ohci linux/drivers/usb/README.ohci
--- v2.3.2/linux/drivers/usb/README.ohci	Tue May 11 10:04:03 1999
+++ linux/drivers/usb/README.ohci	Sun May 16 22:23:31 1999
@@ -1,3 +1,31 @@
+May 16, 1999 16:20:54
+
+EDs are now allocated dynamically from their device's pool.  Root hub
+status changes should stop the infinite "no device connected" messages
+that occurred after removing a device.
+
+TODO:
+
+~ Add the concept of a td_group to lump TDs associated with a single
+  data transfer request from the higher layers.  This will be needed
+  for bulk and all larger transfers that will span multiple TDs but
+  which need to allocate/free them as a group as things happen.  I
+  am thinking about create_td_group and free_td_group functions...
+~ Add bulk transfer support.
+~ Add Isochronous transfer support.  These have their own special
+  format TDs to allow for several DMA data pointers.  Kinda neat, but
+  likely harder to use through a generic interface in practice.
+~ Support dynamic allocation & growth of the TD/ED pools.  Merge them
+  into global pools rather than a today's static per device allocation.
+
+KNOWN BUGS:
+
+~ Unplugging a hub causes khubd to Oops.  I don't think this is
+  directly related to OHCI, but due to the fact that the interrupt TD
+  for the hub is never stopped.  We need a usb_release_irq() that gets
+  called using the "IRQ handle" that should be returned by
+  usb_request_irq().
+
X May 09, 1999 16:25:58
X 
X Cool, things are working "well" now.  (I'm not getting oops's from the
diff -u --recursive --new-file v2.3.2/linux/drivers/usb/ohci-debug.c linux/drivers/usb/ohci-debug.c
--- v2.3.2/linux/drivers/usb/ohci-debug.c	Tue May 11 10:04:03 1999
+++ linux/drivers/usb/ohci-debug.c	Sun May 16 22:23:31 1999
@@ -80,17 +80,18 @@
X 
X 	printk(KERN_DEBUG "   ohci ED:\n");
X 	printk(KERN_DEBUG "     status     =  0x%x\n", stat);
-	printk(KERN_DEBUG "       %sMPS %d%s%s%s%s tc%d e%d fa%d\n",
+	printk(KERN_DEBUG "       %sMPS %d%s%s%s%s tc%d e%d fa%d%s\n",
X 			skip ? "Skip " : "",
X 			mps,
-			isoc ? "Isoc. " : "",
+			isoc ? " Isoc." : "",
X 			low_speed ? " LowSpd" : "",
X 			(dir == OHCI_ED_D_IN) ? " Input" :
X 			(dir == OHCI_ED_D_OUT) ? " Output" : "",
X 			halted ? " Halted" : "",
X 			toggle,
X 			endnum,
-			funcaddr);
+			funcaddr,
+			(stat & ED_ALLOCATED) ? " Allocated" : "");
X 	printk(KERN_DEBUG "     tail_td    =  0x%x\n", ed->tail_td);
X 	printk(KERN_DEBUG "     head_td    =  0x%x\n", ed_head_td(ed));
X 	printk(KERN_DEBUG "     next_ed    =  0x%x\n", ed->next_ed);
@@ -108,19 +109,21 @@
X 
X 	printk(KERN_DEBUG "   ohci TD hardware fields:\n");
X 	printk(KERN_DEBUG "      info     =  0x%x\n", td->info);
-	printk(KERN_DEBUG "        %s%s%s%d %s\n",
+	printk(KERN_DEBUG "        %s%s%s%d %s %s%d\n",
X 		td_round ? "Rounding " : "",
X 		(td_dir == OHCI_TD_D_IN) ? "Input " :
X 		(td_dir == OHCI_TD_D_OUT) ? "Output " :
X 		(td_dir == OHCI_TD_D_SETUP) ? "Setup " : "",
X 		"IntDelay ", td_int_delay,
X 		(td_toggle < 2) ? " " :
-		(td_toggle & 1) ? "Data1 " : "Data0 ");
-	printk(KERN_DEBUG "        %s%d %s0x%x, %sAccessed, %sActive\n",
-		"ErrorCnt ", td_errcnt,
-		"ComplCode ", td_cc,
+		(td_toggle & 1) ? "Data1" : "Data0",
+		"ErrorCnt ", td_errcnt);
+	printk(KERN_DEBUG "        ComplCode 0x%x, %sAccessed, %sActive\n",
+		td_cc,
X 		td_cc_accessed(*td) ? "" : "Not ",
X 		td_active(*td) ? "" : "Not ");
+
+	printk(KERN_DEBUG "        %s\n", td_allocated(*td) ? "Allocated" : "Free");
X 
X 	printk(KERN_DEBUG "      cur_buf  =  0x%x\n", td->cur_buf);
X 	printk(KERN_DEBUG "      next_td  =  0x%x\n", td->next_td);
diff -u --recursive --new-file v2.3.2/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
--- v2.3.2/linux/drivers/usb/ohci.c	Sat May 15 23:46:03 1999
+++ linux/drivers/usb/ohci.c	Sun May 16 22:23:31 1999
@@ -29,7 +29,7 @@
X  *
X  * No filesystems were harmed in the development of this code.
X  *
- * $Id: ohci.c,v 1.26 1999/05/11 07:34:47 greg Exp $
+ * $Id: ohci.c,v 1.43 1999/05/16 22:35:24 greg Exp $
X  */
X 
X #include <linux/config.h>
@@ -59,31 +59,30 @@
X 
X static DECLARE_WAIT_QUEUE_HEAD(ohci_configure);
X 
-#ifdef OHCI_TIMER
-static struct timer_list ohci_timer;	/* timer for root hub polling */
+#ifdef CONFIG_USB_OHCI_DEBUG
+#define OHCI_DEBUG    /* to make typing it easier.. */
X #endif
X 
+#ifdef OHCI_DEBUG
+int MegaDebug = 0;	/* SIGUSR2 to the control thread toggles this */
+#endif
X 
-static int ohci_td_result(struct ohci_device *dev, struct ohci_td *td)
-{
-	unsigned int status;
-
-	status = td->info & OHCI_TD_CC;
-
-	/* TODO Debugging code for TD failures goes here */
-
-	return status;
-} /* ohci_td_result() */
X 
+#ifdef OHCI_TIMER
+static struct timer_list ohci_timer;	/* timer for root hub polling */
+#endif
X 
X static spinlock_t ohci_edtd_lock = SPIN_LOCK_UNLOCKED;
X 
X /*
- * Add a TD to the end of the TD list on a given ED.  If td->next_td
- * points to any more TDs, they will be added as well (naturally).
- * Otherwise td->next_td must be 0.
+ * Add a TD to the end of the TD list on a given ED.  This function
+ * does NOT advance the ED's tail_td pointer beyond the given TD.  To
+ * add multiple TDs, call this function once for each TD.  Do not
+ * "simply" update tail_td yourself... This function does more than
+ * that.
X  * 
- * The SKIP flag will be cleared after this function.
+ * If this ED is on the controller, you MUST set its SKIP flag before
+ * calling this function.
X  *
X  * Important!  This function needs locking and atomicity as it works
X  * in parallel with the HC's DMA.  Locking ohci_edtd_lock while using
@@ -93,54 +92,62 @@
X  */
X static void ohci_add_td_to_ed(struct ohci_td *td, struct ohci_ed *ed)
X {
-	/* don't let the HC pull anything from underneath us */
-	ed->status |= OHCI_ED_SKIP;
+	struct ohci_td *dummy_td, *prev_td;
+
+	if (ed->tail_td == 0) {
+		printk("eek! an ED without a dummy_td\n");
+	}
+
+	/* The ED's tail_td is constant, always pointing to the
+	 * dummy_td.  The reason the ED never processes the dummy is
+	 * that it stops processing TDs as soon as head_td == tail_td.
+	 * When it advances to this last dummy TD it conveniently stops. */
+	dummy_td = bus_to_virt(ed->tail_td);
X 
-	if (ed_head_td(ed) == 0) {	/* empty list, put it on the head */
-		set_ed_head_td(ed, virt_to_bus(td));
-		ed->tail_td = 0;
+	/* Dummy's data pointer is used to point to the previous TD */
+	if (ed_head_td(ed) != ed->tail_td) {
+		prev_td = (struct ohci_td *) dummy_td->data;
X 	} else {
-		struct ohci_td *tail, *head;
-		head = (ed_head_td(ed) == 0) ? NULL : bus_to_virt(ed_head_td(ed));
-		tail = (ed->tail_td == 0) ? NULL : bus_to_virt(ed->tail_td);
-		if (!tail) {	/* no tail, single element list */
-			td->next_td = head->next_td;
-			head->next_td = virt_to_bus(td);
-			ed->tail_td = virt_to_bus(td);
-		} else {	/* append to the list */
-			td->next_td = tail->next_td;
-			tail->next_td = virt_to_bus(td);
-			ed->tail_td = virt_to_bus(td);
-		}
+		/* if the ED is empty, previous is meaningless */
+		/* We'll be inserting into the head of the list */
+		prev_td = NULL;
X 	}
X 
-	/* save the ED link in each of the TDs added */
+	/* Store the new back pointer and set up this TD's next */
+	dummy_td->data = td;
+	td->next_td = ed->tail_td;
+
+	/* Store the TD pointer back to the ED */
X 	td->ed = ed;
-	while (td->next_td != 0) {
-		td = bus_to_virt(td->next_td);
-		td->ed = ed;
-	}
X 
-	/* turn off the SKIP flag */
-	ed->status &= ~OHCI_ED_SKIP;
+	if (!prev_td) { /* No previous TD? then insert us at the head */
+		if (ed_head_td(ed) != ed->tail_td)
+			printk(KERN_DEBUG "Suspicious ED...\n");
+		set_ed_head_td(ed, virt_to_bus(td));	/* put it on the ED */
+	} else {
+		/* add the TD to the end */
+		prev_td->next_td = virt_to_bus(td);
+	}
X } /* ohci_add_td_to_ed() */
X 
X 
X inline void ohci_start_control(struct ohci *ohci)
X {
X 	/* tell the HC to start processing the control list */
-	writel(OHCI_CMDSTAT_CLF, &ohci->regs->cmdstatus);
+	writel_set(OHCI_USB_CLE, &ohci->regs->control);
+	writel_set(OHCI_CMDSTAT_CLF, &ohci->regs->cmdstatus);
X }
X 
X inline void ohci_start_bulk(struct ohci *ohci)
X {
X 	/* tell the HC to start processing the bulk list */
-	writel(OHCI_CMDSTAT_BLF, &ohci->regs->cmdstatus);
+	writel_set(OHCI_USB_BLE, &ohci->regs->control);
+	writel_set(OHCI_CMDSTAT_BLF, &ohci->regs->cmdstatus);
X }
X 
X inline void ohci_start_periodic(struct ohci *ohci)
X {
-	/* enable processing periodc transfers starting next frame */
+	/* enable processing periodic (intr) transfers starting next frame */
X 	writel_set(OHCI_USB_PLE, &ohci->regs->control);
X }
X 
@@ -152,6 +159,7 @@
X 
X /*
X  * Add an ED to the hardware register ED list pointed to by hw_listhead_p
+ * This function only makes sense for Control and Bulk EDs.
X  */
X static void ohci_add_ed_to_hw(struct ohci_ed *ed, void* hw_listhead_p)
X {
@@ -172,11 +180,11 @@
X 	writel(virt_to_bus(ed), hw_listhead_p);
X 
X 	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
-} /* ohci_add_ed() */
+} /* ohci_add_ed_to_hw() */
X 
X 
X /*
- *  Put another control ED on the controller's list
+ *  Put a control ED on the controller's list
X  */
X void ohci_add_control_ed(struct ohci *ohci, struct ohci_ed *ed)
X {
@@ -184,37 +192,146 @@
X 	ohci_start_control(ohci);
X } /* ohci_add_control_ed() */
X 
+/*
+ *  Put a bulk ED on the controller's list
+ */
+void ohci_add_bulk_ed(struct ohci *ohci, struct ohci_ed *ed)
+{
+	ohci_add_ed_to_hw(ed, &ohci->regs->ed_bulkhead);
+	ohci_start_bulk(ohci);
+} /* ohci_add_bulk_ed() */
X 
-#if 0
X /*
- *  Put another control ED on the controller's list
+ *  Put a periodic ED on the appropriate list given the period.
X  */
X void ohci_add_periodic_ed(struct ohci *ohci, struct ohci_ed *ed, int period)
X {
-	ohci_add_ed_to_hw(ed, /* XXX */);
+	struct ohci_ed *int_ed;
+	unsigned long flags;
+
+	/*
+	 * Pick a good frequency endpoint based on the requested period
+	 */
+	int_ed = &ohci->root_hub->ed[ms_to_ed_int(period)];
+#ifdef OHCI_DEBUG
+	printk("usb-ohci: Using INT ED queue %d for %dms period\n",
+			ms_to_ed_int(period), period);
+#endif
+
+	spin_lock_irqsave(&ohci_edtd_lock, flags);
+	/*
+	 * Insert this ED at the front of the list.
+	 */
+	ed->next_ed = int_ed->next_ed;
+	int_ed->next_ed = virt_to_bus(ed);
+
+	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+
X 	ohci_start_periodic(ohci);
-} /* ohci_add_control_ed() */
+} /* ohci_add_periodic_ed() */
+
+/*
+ *  Put an isochronous ED on the controller's list
+ */
+inline void ohci_add_isoc_ed(struct ohci *ohci, struct ohci_ed *ed)
+{
+	ohci_add_periodic_ed(ohci, ed, 1);
+}
+
+
+/*
+ * This will be used for the interrupt to wake us up on the next SOF
+ */
+DECLARE_WAIT_QUEUE_HEAD(start_of_frame_wakeup);
+
+/*
+ * Guarantee that an ED is safe to be modified by the HCD (us).
+ *
+ * This function can NOT be called from an interrupt.
+ */
+void ohci_wait_for_ed_safe(struct ohci_regs *regs, struct ohci_ed *ed, int ed_type)
+{
+	__u32 hw_listcurrent;
+
+	/* tell the controller to skip this ED */
+	ed->status |= OHCI_ED_SKIP;
+
+	switch (ed_type) {
+	case HCD_ED_CONTROL:
+		hw_listcurrent = readl(regs->ed_controlcurrent);
+		break;
+	case HCD_ED_BULK:
+		hw_listcurrent = readl(regs->ed_bulkcurrent);
+		break;
+	case HCD_ED_ISOC:
+	case HCD_ED_INT:
+		hw_listcurrent = readl(regs->ed_periodcurrent);
+		break;
+	default:
+		return;
+	}
+
+	/* 
+	 * If the HC is processing this ED we need to wait until the
+	 * at least the next frame.
+	 */
+	if (virt_to_bus(ed) == hw_listcurrent) {
+		DECLARE_WAITQUEUE(wait, current);
+
+#ifdef OHCI_DEBUG
+		printk("Waiting a frame for OHC to finish with ED %p\n", ed);
X #endif
X 
+		add_wait_queue(&start_of_frame_wakeup, &wait);
+
+		/* clear the SOF interrupt status and enable it */
+		writel(OHCI_INTR_SF, ®s->intrstatus);
+		writel(OHCI_INTR_SF, ®s->intrenable);
+
+		schedule_timeout(HZ/10);
+
+		remove_wait_queue(&start_of_frame_wakeup, &wait);
+	}
+
+	return; /* The ED is now safe */
+} /* ohci_wait_for_ed_safe() */
+
X 
X /*
- *  Remove an ED from the HC list whos bus headpointer is pointed to
- *  by hw_listhead_p
+ *  Remove an ED from the HC's list.
+ *  This function can ONLY be used for Control or Bulk EDs.
X  *  
X  *  Note that the SKIP bit is left on in the removed ED.
X  */
-void ohci_remove_ed_from_hw(struct ohci_ed *ed, __u32* hw_listhead_p)
+void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_type)
X {
X 	unsigned long flags;
+	struct ohci_regs *regs = ohci->regs;
X 	struct ohci_ed *cur;
X 	__u32 bus_ed = virt_to_bus(ed);
X 	__u32 bus_cur;
+	__u32 *hw_listhead_p;
X 
X 	if (ed == NULL || !bus_ed)
X 		return;
X 
-	/* tell the controller this skip ED */
-	ed->status |= OHCI_ED_SKIP;
+	switch (ed_type) {
+	case HCD_ED_CONTROL:
+		hw_listhead_p = ®s->ed_controlhead;
+		break;
+	case HCD_ED_BULK:
+		hw_listhead_p = ®s->ed_bulkhead;
+		break;
+	default:
+		printk("Unknown HCD ED type %d.\n", ed_type);
+		return;
+	}
+
+	/*
+	 * Tell the controller to this skip ED and make sure it is not the
+	 * being accessed by the HC as we speak.
+	 */
+	ohci_wait_for_ed_safe(regs, ed, ed_type);
X 
X 	bus_cur = readl(hw_listhead_p);
X 
@@ -232,7 +349,7 @@
X 		struct ohci_ed *prev;
X 
X 		/* walk the list and unlink the ED if found */
-		for (;;) {
+		do {
X 			prev = cur;
X 			cur = bus_to_virt(cur->next_ed);
X 
@@ -241,17 +358,14 @@
X 				prev->next_ed = cur->next_ed;
X 				break;
X 			}
-
-			if (cur->next_ed == 0)
-				break;
-		}
+		} while (cur->next_ed != 0);
X 	}
X 
X 	/* clear any links from the ED for safety */
X 	ed->next_ed = 0;
X 
X 	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
-} /* ohci_remove_ed_from_hw() */
+} /* ohci_remove_norm_ed_from_hw() */
X 
X /*
X  *  Remove an ED from the controller's control list.  Note that the SKIP bit
@@ -259,7 +373,7 @@
X  */
X inline void ohci_remove_control_ed(struct ohci *ohci, struct ohci_ed *ed)
X {
-	ohci_remove_ed_from_hw(ed, &ohci->regs->ed_controlhead);
+	ohci_remove_norm_ed_from_hw(ohci, ed, HCD_ED_CONTROL);
X }
X 
X /*
@@ -268,7 +382,7 @@
X  */
X inline void ohci_remove_bulk_ed(struct ohci *ohci, struct ohci_ed *ed)
X {
-	ohci_remove_ed_from_hw(ed, &ohci->regs->ed_bulkhead);
+	ohci_remove_norm_ed_from_hw(ohci, ed, HCD_ED_BULK);
X }
X 
X 
@@ -321,7 +435,8 @@
X 	td->next_td = 0;  /* remove the TDs links */
X 	td->ed = NULL;
X 
-	/* TODO return this TD to the pool of free TDs */
+	/* return this TD to the pool of free TDs */
+	ohci_free_td(td);
X 
X 	/* unset the "skip me bit" in this ED */
X 	ed->status &= ~OHCI_ED_SKIP;
@@ -332,15 +447,21 @@
X 
X /*
X  * Get a pointer (virtual) to an available TD from the given device's
- * pool.
- *
- * Return NULL if none are left.
+ * pool.  Return NULL if none are left.
X  */
X static struct ohci_td *ohci_get_free_td(struct ohci_device *dev)
X {
X 	int idx;
X 
+#if 0
+	printk(KERN_DEBUG "in ohci_get_free_td()\n");
+#endif
+
+	/* FIXME: this is horribly inefficient */
X 	for (idx=0; idx < NUM_TDS; idx++) {
+#if 0
+		show_ohci_td(&dev->td[idx]);
+#endif
X 		if (!td_allocated(dev->td[idx])) {
X 			struct ohci_td *new_td = &dev->td[idx];
X 			/* zero out the TD */
@@ -353,12 +474,53 @@
X 		}
X 	}
X 
-	printk("usb-ohci error: unable to allocate a TD\n");
+	printk("usb-ohci: unable to allocate a TD\n");
X 	return NULL;
X } /* ohci_get_free_td() */
X 
X 
X /*
+ * Get a pointer (virtual) to an available TD from the given device's
+ * pool.  Return NULL if none are left.
+ */
+static struct ohci_ed *ohci_get_free_ed(struct ohci_device *dev)
+{
+	int idx;
+
+	/* FIXME: this is horribly inefficient */
+	for (idx=0; idx < NUM_EDS; idx++) {
+		if (!ed_allocated(dev->ed[idx])) {
+			struct ohci_ed *new_ed = &dev->ed[idx];
+			/* zero out the ED */
+			memset(new_ed, 0, sizeof(*new_ed));
+			/* all new EDs start with the SKIP bit set */
+			new_ed->status |= OHCI_ED_SKIP;
+			/* mark it as allocated */
+			allocate_ed(new_ed);
+			return new_ed;
+		}
+	}
+
+	printk("usb-ohci: unable to allocate an ED\n");
+	return NULL;
+} /* ohci_get_free_ed() */
+
+
+void ohci_free_ed(struct ohci_ed *ed)
+{
+	if (!ed)
+		return;
+
+	if (ed->tail_td == 0) {
+		printk("yikes! an ED without a dummy_td\n");
+	} else
+		ohci_free_td((struct ohci_td *)bus_to_virt(ed->tail_td));
+
+	ed->status &= ~(__u32)ED_ALLOCATED;
+} /* ohci_free_ed() */
+
+
+/*
X  *  Initialize a TD
X  *
X  * 	dir = OHCI_TD_D_IN, OHCI_TD_D_OUT, or OHCI_TD_D_SETUP
@@ -379,10 +541,58 @@
X 	td->dev_id = dev_id;
X 	td->completed = completed;
X 
+#if 0
+	printk(KERN_DEBUG "ohci_fill_new_td created:\n");
+	show_ohci_td(td);
+#endif
+
X 	return td;
X } /* ohci_fill_new_td() */
X 
X 
+/*
+ *  Initialize a new ED on device dev, including allocating and putting the
+ *  dummy tail_td on its queue if it doesn't already have one.  Any
+ *  TDs on this ED other than the dummy will be lost (so there better
+ *  not be any!).  This assumes that the ED is Allocated and will
+ *  force the Allocated bit on.
+ */
+struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed, int maxpacketsize, int lowspeed, int endp_id, int isoc_tds)
+{
+	struct ohci_td *dummy_td;
+
+	if (ed_head_td(ed) != ed->tail_td)
+		printk("Reusing a non-empty ED %p!\n", ed);
+
+	if (!ed->tail_td) {
+		dummy_td = ohci_get_free_td(dev);
+		if (dummy_td == NULL) {
+			printk("Error allocating dummy TD for ED %p\n", ed);
+			return NULL;	/* no dummy available! */
+		}
+		make_dumb_td(dummy_td);	/* flag it as a dummy */
+		ed->tail_td = virt_to_bus(dummy_td);
+	} else {
+		dummy_td = bus_to_virt(ed->tail_td);
+		if (!td_dummy(*dummy_td))
+			printk("ED %p's dummy %p is screwy\n", ed, dummy_td);
+	}
+
+	/* set the head TD to the dummy and clear the Carry & Halted bits */
+	ed->_head_td = ed->tail_td;
+
+	ed->status = \
+		ed_set_maxpacket(maxpacketsize) |
+		ed_set_speed(lowspeed) |
+		(endp_id & 0x7ff) |
+		((isoc_tds == 0) ? OHCI_ED_F_NORM : OHCI_ED_F_ISOC);
+	allocate_ed(ed);
+	ed->next_ed = 0;
+
+	return ed;
+} /* ohci_fill_ed() */
+
+
X /**********************************
X  * OHCI interrupt list operations *
X  **********************************/
@@ -404,26 +614,26 @@
X 	struct ohci_td *td;
X 	struct ohci_ed *interrupt_ed;	/* endpoint descriptor for this irq */
X 
-	/*
-	 * Pick a good frequency endpoint based on the requested period
-	 */
-	interrupt_ed = &dev->ohci->root_hub->ed[ms_to_ed_int(period)];
+	/* Get an ED and TD */
+	interrupt_ed = ohci_get_free_ed(dev);
+	if (!interrupt_ed) {
+		printk("Out of EDs on device %p in ohci_request_irq\n", dev);
+		return -1;
+	}
+
+	td = ohci_get_free_td(dev);
+	if (!td) {
+		printk("Out of TDs in ohci_request_irq\n");
+		ohci_free_ed(interrupt_ed);
+		return -1;
+	}
X 
X 	/*
X 	 * Set the max packet size, device speed, endpoint number, usb
X 	 * device number (function address), and type of TD.
-	 *
-	 * FIXME: Isochronous transfers need a pool of special 32 byte
-	 * TDs (32 byte aligned) in order to be supported.
X 	 */
-	interrupt_ed->status = \
-		ed_set_maxpacket(usb_maxpacket(pipe)) |
-		ed_set_speed(usb_pipeslow(pipe)) |
-		usb_pipe_endpdev(pipe) |
-		OHCI_ED_F_NORM;
-
-	td = ohci_get_free_td(dev);
-	/* FIXME: check for NULL */
+	ohci_fill_ed(dev, interrupt_ed, usb_maxpacket(pipe), usb_pipeslow(pipe),
+		usb_pipe_endpdev(pipe), 0 /* normal TDs */);
X 
X 	/* Fill in the TD */
X 	ohci_fill_new_td(td, td_set_dir_out(usb_pipeout(pipe)),
@@ -432,42 +642,23 @@
X 			&dev->data, DATA_BUF_LEN,
X 			dev_id, handler);
X 	/*
-	 * TODO: be aware that OHCI won't advance out of the 4kb
-	 * page cur_buf started in.  It'll wrap around to the start
-	 * of the page...  annoying or useful? you decide.
-	 *
-	 * We should make sure dev->data doesn't cross a page...
+	 * TODO: be aware of how the OHCI controller deals with DMA
+	 * spanning more than one page.
X 	 */
X 
-	/* FIXME: this just guarantees that its the end of the list */
-	td->next_td = 0;
+	/*
+	 *  Put the TD onto our ED and make sure its ready to run
+	 */
+	ohci_add_td_to_ed(td, interrupt_ed);
+	interrupt_ed->status &= ~OHCI_ED_SKIP;
+	ohci_unhalt_ed(interrupt_ed);
X 
X 	/* Linus did this. see asm/system.h; scary concept... I don't
X 	 * know if its needed here or not but it won't hurt. */
X 	wmb();
X 
-	/*
-	 *  Put the TD onto our ED
-	 */
-	{
-		unsigned long flags;
-		spin_lock_irqsave(&ohci_edtd_lock, flags);
-		ohci_add_td_to_ed(td, interrupt_ed);
-		spin_unlock_irqrestore(&ohci_edtd_lock, flags);
-	}
-
-#if 0
X 	/* Assimilate the new ED into the collective */
-	/*
-	 *  When dynamic ED allocation is done, this call will be
-	 *  useful.  For now, the correct ED already on the
-	 *  controller's proper periodic ED lists was chosen above.
-	 */
X 	ohci_add_periodic_ed(dev->ohci, interrupt_ed, period);
-#else
-	/* enable periodic (interrupt) transfers on the HC */
-	ohci_start_periodic(dev->ohci);
-#endif
X 
X 	return 0;
X } /* ohci_request_irq() */
@@ -486,6 +677,12 @@
X  */
X static int ohci_control_completed(int stats, void *buffer, void *dev_id)
X {
+	/* pass the TDs completion status back to control_msg */
+	if (dev_id) {
+		int *completion_status = (int *)dev_id;
+		*completion_status = stats;
+	}
+
X 	wake_up(&control_wakeup);
X 	return 0;
X } /* ohci_control_completed() */
@@ -502,44 +699,46 @@
X  *   - The command itself
X  *   - An optional data phase (if len > 0)
X  *   - Status complete phase
+ *
+ * This function can NOT be called from an interrupt.
X  */
X static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, void *cmd, void *data, int len)
X {
X 	struct ohci_device *dev = usb_to_ohci(usb);
-	/*
-	 * ideally dev->ed should be linked into the root hub's
-	 * control_ed list and used instead of just using it directly.
-	 * This could present a problem as is with more than one
-	 * device.  (but who wants to use a keyboard AND a mouse
-	 * anyways? ;)
-	 */
-	struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL];
+	struct ohci_ed *control_ed = ohci_get_free_ed(dev);
X 	struct ohci_td *setup_td, *data_td, *status_td;
X 	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int completion_status = -1;
X 
-#if 0
-	printk(KERN_DEBUG "entering ohci_control_msg %p (ohci_dev: %p) pipe 0x%x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
+#ifdef OHCI_DEBUG 
+	printk(KERN_DEBUG "ohci_control_msg %p (ohci_dev: %p) pipe %x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
X #endif
+	if (!control_ed) {
+		printk("usb-ohci: couldn't get ED for dev %p\n", dev);
+		return -1;
+	}
+
+	/* get a TD to send this control message with */
+	setup_td = ohci_get_free_td(dev);
+	if (!setup_td) {
+		printk("usb-ohci: couldn't get TD for dev %p [cntl setup]\n", dev);
+		ohci_free_ed(control_ed);
+		return -1;
+	}
X 
X 	/*
X 	 * Set the max packet size, device speed, endpoint number, usb
X 	 * device number (function address), and type of TD.
X 	 *
X 	 */
-	control_ed->status = \
-		ed_set_maxpacket(usb_maxpacket(pipe)) |
-		ed_set_speed(usb_pipeslow(pipe)) |
-		usb_pipe_endpdev(pipe) |
-		OHCI_ED_F_NORM;
+	ohci_fill_ed(dev, control_ed, usb_maxpacket(pipe), usb_pipeslow(pipe),
+		usb_pipe_endpdev(pipe), 0 /* normal TDs */);
X 
X 	/*
X 	 * Build the control TD
X 	 */
X 
-	/* get a TD to send this control message with */
-	setup_td = ohci_get_free_td(dev);
-	/* TODO check for NULL */
-
X 	/*
X 	 * Set the not accessed condition code, allow odd sized data,
X 	 * and set the data transfer type to SETUP.  Setup DATA always
@@ -555,7 +754,13 @@
X 			NULL, NULL);
X 
X 	/* allocate the next TD */
-	data_td = ohci_get_free_td(dev);  /* TODO check for NULL */
+	data_td = ohci_get_free_td(dev);
+	if (!data_td) {
+		printk("usb-ohci: couldn't get TD for dev %p [cntl data]\n", dev);
+		ohci_free_td(setup_td);
+		ohci_free_ed(control_ed);
+		return -1;
+	}
X 
X 	/* link to the next TD */
X 	setup_td->next_td = virt_to_bus(data_td);
@@ -570,48 +775,59 @@
X 				NULL, NULL);
X 
X 		/*
-		 * XXX we should check that the data buffer doesn't
-		 * cross a 4096 byte boundary.  If so, it needs to be
-		 * copied into a single 4096 byte aligned area for the
-		 * OHCI's TD logic to see it all, or multiple TDs need
-		 * to be made for each page.
+		 * TODO: Normal TDs can transfer up to 8192 bytes on OHCI.
+		 * However, for that to happen, the data must -start-
+		 * on a nice 4kb page.  We need to check for data
+		 * sizes > 4096 and, if they cross more than two 4096
+		 * byte pages of memory one or more additional TDs
+		 * will need to be created.  (repeat doing this in a
+		 * loop until all of the DATA is on a TD)
X 		 *
-		 * It's not likely a control transfer will run into
-		 * this problem.. (famous last words)
+		 * Control transfers are -highly unlikely- to need to
+		 * transfer this much data.. but who knows.. sadistic
+		 * hardware is sure to exist.
X 		 */
X 
X 		status_td = ohci_get_free_td(dev);  /* TODO check for NULL */
+		if (!status_td) {
+			printk("usb-ohci: couldn't get TD for dev %p [cntl status]\n", dev);
+			ohci_free_td(setup_td);
+			ohci_free_td(data_td);
+			ohci_free_ed(control_ed);
+			return -1;
+		}
+
X 		data_td->next_td = virt_to_bus(status_td);
X 	} else {
X 		status_td = data_td; /* no data_td, use it for status */
X 	}
X 
-	/* The control status packet always uses a DATA1 */
+	/* The control status packet always uses a DATA1
+	 * Give "dev_id" the address of completion_status so that the
+	 * TDs status can be passed back to us from the IRQ. */
X 	ohci_fill_new_td(status_td,
X 			td_set_dir_in(usb_pipeout(pipe) | (len == 0)),
X 			TOGGLE_DATA1,
-			0,
-			NULL, 0,
-			NULL, ohci_control_completed);
+			0 /* flags */,
+			NULL /* data */, 0 /* data len */,
+			&completion_status, ohci_control_completed);
X 	status_td->next_td = 0; /* end of TDs */
X 
X 	/*
-	 * Start the control transaction..
-	 */
-	current->state = TASK_UNINTERRUPTIBLE;
-	add_wait_queue(&control_wakeup, &wait);
-
-	/*
X 	 * Add the chain of 2-3 control TDs to the control ED's TD list
X 	 */
SHAR_EOF
true || echo 'restore of patch-2.3.3 failed'
fi
echo 'End of  part 2'
echo 'File patch-2.3.3 is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a 4 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
if test -r _shar_seq_.tmp; then
        echo 'Must unpack archives in sequence!'
        echo Please unpack part `cat _shar_seq_.tmp` next
        exit 1
fi
# ============= patch-2.3.3 ==============
if test -f 'patch-2.3.3' -a X"$1" != X"-c"; then
        echo 'x - skipping patch-2.3.3 (File already exists)'
        rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.3.3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.3.3' &&
diff -u --recursive --new-file v2.3.2/linux/CREDITS linux/CREDITS
--- v2.3.2/linux/CREDITS	Sat May 15 23:46:02 1999
+++ linux/CREDITS	Sun May 16 10:26:44 1999
@@ -1534,6 +1534,15 @@
X E: o...@pell.chi.il.us
X D: improved memory detection code.
X 
+N: Mikulas Patocka
+E: mik...@artax.karlin.mff.cuni.cz
+W: http://artax.karlin.mff.cuni.cz/~mikulas/
+P: 1024/BB11D2D5 A0 F1 28 4A C4 14 1E CF  92 58 7A 8F 69 BC A4 D3
+D: Read/write HPFS filesystem
+S: Weissova 8
+S: 644 00 Brno
+S: Czech Republic
+
X N: Vojtech Pavlik
X E: voj...@ucw.cz
X D: Joystick driver
@@ -1839,7 +1848,7 @@
X 
X N: Chris Smith
X E: csm...@convex.com
-D: HPFS filesystem
+D: Read only HPFS filesystem
X S: Richardson, Texas
X S: USA
X 
diff -u --recursive --new-file v2.3.2/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.2/linux/Documentation/Configure.help	Sat May 15 23:46:02 1999
+++ linux/Documentation/Configure.help	Sun May 16 10:26:44 1999
@@ -7322,14 +7322,24 @@
X   directories that are mount points on the local filesystem (this is
X   how nfsd behaves on Sun systems), say yes here. If unsure, say N.
X 
-OS/2 HPFS filesystem support (read only)
+OS/2 HPFS filesystem support (read/write)
X CONFIG_HPFS_FS
X   OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
X   is the filesystem used for organizing files on OS/2 hard disk
-  partitions. Say Y if you want to be able to read files from an OS/2
-  HPFS partition of your hard drive. OS/2 floppies however are in
-  regular MSDOS format, so you don't need this option in order to be
-  able to read them. Read Documentation/filesystems/hpfs.txt. 
+  partitions. Say Y if you want to be able to read and write files
+  on an OS/2 HPFS partition of your hard drive. OS/2 floppies however
+  are in regular MSDOS format, so you don't need this option in order
+  to be able to read them. Read Documentation/filesystems/hpfs.txt. 
+  
+  Write support is new and experimental. I don't think it's so
+  "experimental" that it corrupts disks. (but you know: "There's no
+  warranty") There are many checks and filesystem is remounted read-only
+  if any inconsistency found. I use it quite long time and it works.
+
+  This driver may not be able to write to HPFS386 disks on Warp server.
+  HPFS386 on Warp client seems to work ok. If some unknown HPFS386
+  structures are deteced, they are not destroyed and filesystem is
+  remounted read-only.
X 
X   This filesystem is also available as a module ( = code which can be
X   inserted in and removed from the running kernel whenever you want).
diff -u --recursive --new-file v2.3.2/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt
--- v2.3.2/linux/Documentation/filesystems/hpfs.txt	Sat May 15 23:46:02 1999
+++ linux/Documentation/filesystems/hpfs.txt	Sun May 16 10:26:44 1999
@@ -1,4 +1,4 @@
-Read/Write HPFS 1.98b
+Read/Write HPFS 1.99b
X 1998-1999, Mikulas Patocka
X 
X email: mik...@artax.karlin.mff.cuni.cz
@@ -58,9 +58,9 @@
X because kernel creates different files with names like bootsect.S and
X bootsect.s. When searching for file thats name has characters >= 128, codepages
X are used - see below.
-OS/2 ignores dots and spaces at the end of file name, so this driver does. If
-you create 'a. ...', the file 'a' will be created, but you can still access it
-under names 'a.', 'a..', 'a .  . . ' etc.
+OS/2 ignores dots and spaces at the end of file name, so this driver does as
+well. If you create 'a. ...', the file 'a' will be created, but you can still
+access it under names 'a.', 'a..', 'a .  . . ' etc.
X 
X 
X Extended attributes
@@ -162,9 +162,6 @@
X Renaming files so that only case changes doesn't work. This driver supports it
X but vfs doesn't. Something like 'mv file FILE' won't work.
X 
-When you try to create file with bad filename (too long or containing forbidden
-characters), you get ENOENT error instead of EINVAL or ENAMETOOLONG.
-
X All atimes and directory mtimes are not updated. That's because of performance
X reasons. If you extremely wish to update them, let me know, I'll write it (but
X it will be slow).
@@ -266,6 +263,10 @@
X        Fixed a bug when chmoding or chowning root directory
X 1.98 Fixed a deadlock when using old_readdir
X      Better directory handling; workaround for "unbalanced tree" bug in OS/2
+1.99 Corrected a possible problem when there's not enough space while deleting
+	file
+     Now it tries to truncate the file if there's not enough space when deleting
+     Removed a lot of redundat code
X 
X 
X  vim: set textwidth=80:
diff -u --recursive --new-file v2.3.2/linux/Documentation/mtrr.txt linux/Documentation/mtrr.txt
--- v2.3.2/linux/Documentation/mtrr.txt	Mon May 10 10:32:45 1999
+++ linux/Documentation/mtrr.txt	Sun May 16 10:13:20 1999
@@ -1,5 +1,5 @@
X MTRR (Memory Type Range Register) control
-2 May 1998
+16 May 1999
X Richard Gooch
X <rgo...@atnf.csiro.au>
X 
@@ -31,8 +31,10 @@
X reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
X reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
X ===============================================================================
-Creating MTRRs from the shell:
+Creating MTRRs from the C-shell:
X # echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr
+or if you use bash:
+# echo "base=0xf8000000 size=0x400000 type=write-combining" >| /proc/mtrr
X 
X And the result thereof:
X % cat /proc/mtrr
@@ -79,8 +81,10 @@
X NOTE: You can only create type=uncachable region, if the first
X region that you created is type=write-combining.
X ===============================================================================
-Removing MTRRs from the shell:
+Removing MTRRs from the C-shell:
X % echo "disable=2" >! /proc/mtrr
+or using bash:
+% echo "disable=2" >| /proc/mtrr
X ===============================================================================
X Reading MTRRs from a C programme using ioctl()'s:
X 
diff -u --recursive --new-file v2.3.2/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.2/linux/MAINTAINERS	Sat May  8 12:49:46 1999
+++ linux/MAINTAINERS	Sun May 16 10:26:44 1999
@@ -361,6 +361,12 @@
X W:	http://www.uni-mainz.de/~langm000/linux.html
X S:	Maintained
X 
+HPFS FILESYSTEM
+P:	Mikulas Patocka
+M:	mik...@artax.karlin.mff.cuni.cz
+W:	http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
+S:	Maintained
+
X IDE DRIVER [GENERAL]
X P:	Andre Hedrick
X M:	hed...@astro.dyer.vanderbilt.edu
diff -u --recursive --new-file v2.3.2/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.3.2/linux/arch/i386/Makefile	Wed Dec 30 14:17:25 1998
+++ linux/arch/i386/Makefile	Sun May 16 13:17:22 1999
@@ -25,22 +25,27 @@
X 
X ifdef CONFIG_M386
X CFLAGS := $(CFLAGS) -m386 -DCPU=386
+AFLAGS := $(AFLAGS) -DCPU=386
X endif
X 
X ifdef CONFIG_M486
X CFLAGS := $(CFLAGS) -m486 -DCPU=486
+AFLAGS := $(AFLAGS) -DCPU=486
X endif
X 
X ifdef CONFIG_M586
-CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=586
+CFLAGS := $(CFLAGS) -DCPU=586
+AFLAGS := $(AFLAGS) -DCPU=586
X endif
X 
X ifdef CONFIG_M586TSC
-CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=586
+CFLAGS := $(CFLAGS) -DCPU=586
+AFLAGS := $(AFLAGS) -DCPU=586
X endif
X 
X ifdef CONFIG_M686
-CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686
+CFLAGS := $(CFLAGS) -DCPU=686
+AFLAGS := $(AFLAGS) -DCPU=686
X endif
X 
X HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
diff -u --recursive --new-file v2.3.2/linux/arch/i386/lib/checksum.S linux/arch/i386/lib/checksum.S
--- v2.3.2/linux/arch/i386/lib/checksum.S	Fri Jan 15 14:36:20 1999
+++ linux/arch/i386/lib/checksum.S	Sun May 16 13:17:22 1999
@@ -117,9 +117,11 @@
X #else /* CPU==686 */
X 
X csum_partial:
-	movl 12(%esp),%eax	# Function arg: unsigned int sum
-	movl 8(%esp),%ecx	# Function arg: int len
-	movl 4(%esp),%esi	# Function arg:	const unsigned char *buf
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
X 
X 	testl $2, %esi         
X 	jnz 30f                 
@@ -204,6 +206,8 @@
X 	addl %ebx,%eax
X 	adcl $0,%eax
X 80: 
+	popl %ebx
+	popl %esi
X 	ret
X 				
X #endif /* CPU==686 */ 
@@ -369,7 +373,7 @@
X 
X #define ROUND1(x) \
X 	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax\n		;	\
+	addl %ebx, %eax			;	\
X 	DST(movl %ebx, x(%edi)	)	; 
X 
X #define ROUND(x) \
diff -u --recursive --new-file v2.3.2/linux/arch/m68k/atari/stdma.c linux/arch/m68k/atari/stdma.c
--- v2.3.2/linux/arch/m68k/atari/stdma.c	Thu Feb 12 16:30:12 1998
+++ linux/arch/m68k/atari/stdma.c	Sat May 15 15:05:35 1999
@@ -43,7 +43,7 @@
X 						/* int func to be called */
X static void (*stdma_isr)(int, void *, struct pt_regs *) = NULL;
X static void	*stdma_isr_data = NULL;		/* data passed to isr */
-static struct wait_queue *stdma_wait = NULL;	/* wait queue for ST-DMA */
+static DECLARE_WAIT_QUEUE_HEAD(stdma_wait);	/* wait queue for ST-DMA */
X 
X 
X 
diff -u --recursive --new-file v2.3.2/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
--- v2.3.2/linux/arch/m68k/mac/adb-bus.c	Mon Oct  5 13:54:39 1998
+++ linux/arch/m68k/mac/adb-bus.c	Sat May 15 15:05:35 1999
@@ -2328,12 +2328,12 @@
X 	struct adb_request req;
X };
X 
-static struct wait_queue *adb_wait;
+static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
X 
X static int adb_wait_reply(struct adbdev_state *state, struct file *file)
X {
X 	int ret = 0;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait,current);
X 
X 	add_wait_queue(&adb_wait, &wait);
X 	current->state = TASK_INTERRUPTIBLE;
@@ -2552,12 +2552,12 @@
X 	struct adb_request req;
X };
X 
-static struct wait_queue *adb_wait;
+static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
X 
X static int adb_wait_reply(struct adbdev_state *state, struct file *file)
X {
X 	int ret = 0;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X 
X #if (ADBDEBUG & ADBDEBUG_DEVICE)
X 	printk("ADB request: wait_reply (blocking ... \n");
diff -u --recursive --new-file v2.3.2/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.3.2/linux/arch/mips/kernel/irixsig.c	Thu Nov  5 09:58:29 1998
+++ linux/arch/mips/kernel/irixsig.c	Sat May 15 15:05:35 1999
@@ -666,7 +666,7 @@
X 			    int options, struct rusage *ru)
X {
X 	int flag, retval;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait,current);
X 	struct task_struct *p;
X 
X 	lock_kernel();
diff -u --recursive --new-file v2.3.2/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.3.2/linux/arch/ppc/8xx_io/uart.c	Wed Dec 23 09:44:40 1998
+++ linux/arch/ppc/8xx_io/uart.c	Sat May 15 15:05:35 1999
@@ -155,8 +155,8 @@
X 	long			pgrp; /* pgrp of opening process */
X 	struct tq_struct	tqueue;
X 	struct tq_struct	tqueue_hangup;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
X 
X 	/* CPM Buffer Descriptor pointers.
X 	*/
@@ -1733,7 +1733,7 @@
X 			   ser_info_t *info)
X {
X #ifdef DO_THIS_LATER
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
X #endif
X 	struct serial_state *state = info->state;
X 	int		retval;
diff -u --recursive --new-file v2.3.2/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.2/linux/arch/sparc/defconfig	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/defconfig	Sat May 15 11:12:09 1999
@@ -229,6 +229,7 @@
X CONFIG_MSDOS_FS=m
X # CONFIG_UMSDOS_FS is not set
X CONFIG_VFAT_FS=m
+CONFIG_EFS_FS=m
X CONFIG_ISO9660_FS=m
X # CONFIG_JOLIET is not set
X CONFIG_MINIX_FS=m
diff -u --recursive --new-file v2.3.2/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.2/linux/arch/sparc64/defconfig	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/defconfig	Sat May 15 11:12:09 1999
@@ -267,6 +267,7 @@
X CONFIG_MSDOS_FS=m
X # CONFIG_UMSDOS_FS is not set
X CONFIG_VFAT_FS=m
+CONFIG_EFS_FS=m
X CONFIG_ISO9660_FS=m
X # CONFIG_JOLIET is not set
X CONFIG_MINIX_FS=m
diff -u --recursive --new-file v2.3.2/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.2/linux/arch/sparc64/kernel/sys_sparc32.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Sun May 16 10:39:51 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107 1999/03/05 13:21:02 davem Exp $
+/* $Id: sys_sparc32.c,v 1.108 1999/05/16 10:50:32 davem Exp $
X  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
X  *
X  * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -2363,6 +2363,94 @@
X 	__scm_destroy(scm);
X }
X 
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
+		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG32 is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg32->cmsg_len;
+		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+		kcmsg32->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
X asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
X {
X 	struct socket *sock;
@@ -2455,6 +2543,14 @@
X 				if(scm.fp)
X 					__scm_destroy(&scm);
X 			} else {
+				/* If recvmsg processing itself placed some
+				 * control messages into user space, it's is
+				 * using 64-bit CMSG processing, so we need
+				 * to fix it up before we tack on more stuff.
+				 */
+				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
+					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
+
X 				/* Wheee... */
X 				if(sock->passcred)
X 					put_cmsg32(&kern_msg,
@@ -2471,9 +2567,9 @@
X 	if(uaddr != NULL && err >= 0)
X 		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
X 	if(cmsg_ptr != 0 && err >= 0) {
-		u32 ucmsg_ptr = ((u32)(unsigned long)kern_msg.msg_control);
-		err  = __put_user(ucmsg_ptr, &user_msg->msg_control);
-		err |= __put_user(kern_msg.msg_controllen, &user_msg->msg_controllen);
+		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
+		__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
+		err |= __put_user(uclen, &user_msg->msg_controllen);
X 	}
X 	if(err >= 0)
X 		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
diff -u --recursive --new-file v2.3.2/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.2/linux/arch/sparc64/solaris/fs.c	Fri May 14 18:55:13 1999
+++ linux/arch/sparc64/solaris/fs.c	Sat May 15 11:12:09 1999
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.12 1999/01/02 16:46:06 davem Exp $
+/* $Id: fs.c,v 1.13 1999/05/14 07:24:37 davem Exp $
X  * fs.c: fs related syscall emulation for Solaris
X  *
X  * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.3.2/linux/arch/sparc64/solaris/ipc.c linux/arch/sparc64/solaris/ipc.c
--- v2.3.2/linux/arch/sparc64/solaris/ipc.c	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/solaris/ipc.c	Sat May 15 11:12:09 1999
@@ -1,4 +1,4 @@
-/* $Id: ipc.c,v 1.3 1998/07/30 11:29:47 davem Exp $
+/* $Id: ipc.c,v 1.4 1999/05/13 07:11:37 jj Exp $
X  * ipc.c: Solaris IPC emulation
X  *
X  * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -7,6 +7,7 @@
X #include <linux/kernel.h>
X #include <linux/types.h>
X #include <linux/smp_lock.h>
+#include <linux/wait.h>
X #include <linux/shm.h>
X #include <linux/sem.h>
X #include <linux/msg.h>
diff -u --recursive --new-file v2.3.2/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c
--- v2.3.2/linux/drivers/acorn/block/fd1772.c	Thu Jan  7 08:46:58 1999
+++ linux/drivers/acorn/block/fd1772.c	Sat May 15 15:05:35 1999
@@ -267,7 +267,7 @@
X 
X /* Synchronization of FDC1772 access. */
X static volatile int fdc_busy = 0;
-static struct wait_queue *fdc_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
X 
X 
X static unsigned int changed_floppies = 0xff, fake_change = 0;
diff -u --recursive --new-file v2.3.2/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.3.2/linux/drivers/acorn/block/mfmhd.c	Mon Aug 24 13:14:09 1998
+++ linux/drivers/acorn/block/mfmhd.c	Sat May 15 15:05:35 1999
@@ -195,7 +195,7 @@
X static int mfm_sizes[MFM_MAXDRIVES << 6];
X static int mfm_blocksizes[MFM_MAXDRIVES << 6];
X static int mfm_sectsizes[MFM_MAXDRIVES << 6];
-static struct wait_queue *mfm_wait_open = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(mfm_wait_open);
X 
X /* Stuff from the assembly routines */
X extern unsigned int hdc63463_baseaddress;	/* Controller base address */
diff -u --recursive --new-file v2.3.2/linux/drivers/ap1000/ap.c linux/drivers/ap1000/ap.c
--- v2.3.2/linux/drivers/ap1000/ap.c	Mon Aug 24 13:45:51 1998
+++ linux/drivers/ap1000/ap.c	Sat May 15 15:05:35 1999
@@ -36,7 +36,7 @@
X #define NUM_APDEVS 8
X #define MAX_REQUESTS 1
X 
-static struct wait_queue * busy_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
X 
X static int ap_blocksizes[NUM_APDEVS];
X static int ap_length[NUM_APDEVS];
diff -u --recursive --new-file v2.3.2/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c
--- v2.3.2/linux/drivers/ap1000/ddv.c	Mon Aug 24 13:02:44 1998
+++ linux/drivers/ap1000/ddv.c	Sat May 15 15:05:35 1999
@@ -84,7 +84,7 @@
X static char *ddv_opcodep = NULL;
X static struct request *next_request = NULL;
X 
-static struct wait_queue * busy_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
X 
X static int ddv_blocksizes[NUM_DDVDEVS]; /* in bytes */
X int ddv_sect_length[NUM_DDVDEVS]; /* in sectors */
@@ -93,7 +93,7 @@
X /* these are used by the ddv_daemon, which services remote disk requests */
X static struct remote_request *rem_queue = NULL;
X static struct remote_request *rem_queue_end;
-static struct wait_queue *ddv_daemon_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(ddv_daemon_wait);
X 
X static int opiu_kernel_loaded = 0;
X 
diff -u --recursive --new-file v2.3.2/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.2/linux/drivers/block/Makefile	Fri May 14 18:55:13 1999
+++ linux/drivers/block/Makefile	Sat May 15 23:43:04 1999
@@ -20,7 +20,7 @@
X 
X 
X L_TARGET := block.a
-L_OBJS   := genhd.o
+L_OBJS   := genhd.o blkpg.o
X M_OBJS   :=
X MOD_LIST_NAME := BLOCK_MODULES
X LX_OBJS := ll_rw_blk.o
diff -u --recursive --new-file v2.3.2/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.3.2/linux/drivers/block/acsi.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/acsi.c	Sat May 15 23:43:04 1999
@@ -64,6 +64,7 @@
X typedef void Scsi_Device; /* hack to avoid including scsi.h */
X #include <scsi/scsi_ioctl.h>
X #include <linux/hdreg.h> /* for HDIO_GETGEO */
+#include <linux/blkpg.h>
X 
X #include <asm/setup.h>
X #include <asm/pgtable.h>
@@ -1125,8 +1126,8 @@
X 		return -EINVAL;
X 	switch (cmd) {
X 	  case HDIO_GETGEO:
-		/* HDIO_GETGEO is supported more for getting the partition's start
-		 * sector... */
+		/* HDIO_GETGEO is supported more for getting the partition's
+		 * start sector... */
X 	  { struct hd_geometry *geo = (struct hd_geometry *)arg;
X 	    /* just fake some geometry here, it's nonsense anyway; to make it
X 		 * easy, use Adaptec's usual 64/32 mapping */
@@ -1147,19 +1148,18 @@
X 	  case BLKGETSIZE:   /* Return device size */
X 		return put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
X 				(long *) arg);
-		
+
+	  case BLKROSET:
+	  case BLKROGET:
X 	  case BLKFLSBUF:
-		if(!capable(CAP_SYS_ADMIN))  return -EACCES;
- if(!inode->i_rdev) return -EINVAL;
-		fsync_dev(inode->i_rdev);
-		invalidate_buffers(inode->i_rdev);
-		return 0;
+	  case BLKPG:
+		return blk_ioctl(inode->i_rdev, cmd, arg);
X 
X 	  case BLKRRPART: /* Re-read partition tables */
X 	        if (!capable(CAP_SYS_ADMIN)) 
X 			return -EACCES;
X 		return revalidate_acsidisk(inode->i_rdev, 1);
-	  RO_IOCTLS(inode->i_rdev,arg);
+
X 	  default:
X 		return -EINVAL;
X 	}
diff -u --recursive --new-file v2.3.2/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.3.2/linux/drivers/block/ataflop.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/ataflop.c	Sat May 15 23:43:04 1999
@@ -93,6 +93,7 @@
X 
X #define MAJOR_NR FLOPPY_MAJOR
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X 
X #define	FD_MAX_UNITS 2
X 
@@ -1584,7 +1585,12 @@
X 
X 	device = inode->i_rdev;
X 	switch (cmd) {
-		RO_IOCTLS (device, param);
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKFLSBUF:
+			return blk_ioctl(device, cmd, param);
X 	}
X 	drive = MINOR (device);
X 	type  = drive >> 2;
@@ -1620,22 +1626,6 @@
X 		getprm.stretch = dtp->stretch;
X 		if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
X 			return -EFAULT;
-		return 0;
-	case BLKRASET:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
-		if (param > 0xff)
-			return -EINVAL;
-		read_ahead[MAJOR(inode->i_rdev)] = param;
-		return 0;
-	case BLKRAGET:
-		return put_user(read_ahead[MAJOR(inode->i_rdev)],
-				(int *) param);
-	case BLKFLSBUF:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
-		fsync_dev(inode->i_rdev);
-		invalidate_buffers(inode->i_rdev);
X 		return 0;
X 	}
X 	if (!IOCTL_ALLOWED)
diff -u --recursive --new-file v2.3.2/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- v2.3.2/linux/drivers/block/blkpg.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/blkpg.c	Sat May 15 23:43:04 1999
@@ -0,0 +1,288 @@
+/*
+ * Partition table and disk geometry handling
+ *
+ * This obsoletes the partition-handling code in genhd.c:
+ * Userspace can look at a disk in arbitrary format and tell
+ * the kernel what partitions there are on the disk, and how
+ * these should be numbered.
+ * It also allows one to repartition a disk that is being used.
+ *
+ * A single ioctl with lots of subfunctions:
+ *
+ * Device number stuff:
+ *    get_whole_disk()          (given the device number of a partition, find
+ *                               the device number of the encompassing disk)
+ *    get_all_partitions()      (given the device number of a disk, return the
+ *                               device numbers of all its known partitions)
+ *
+ * Partition stuff:
+ *    add_partition()
+ *    delete_partition()
+ *    test_partition_in_use()   (also for test_disk_in_use)
+ *
+ * Geometry stuff:
+ *    get_geometry()
+ *    set_geometry()
+ *    get_bios_drivedata()
+ *
+ * For today, only the partition stuff - aeb, 990515
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>			/* for BLKRASET, ... */
+#include <linux/sched.h>		/* for capable() */
+#include <linux/blk.h>			/* for set_device_ro() */
+#include <linux/blkpg.h>
+#include <linux/genhd.h>
+#include <linux/swap.h>			/* for is_swap_partition() */
+
+#include <asm/uaccess.h>
+
+/*
+ * What is the data describing a partition?
+ *
+ * 1. a device number (kdev_t)
+ * 2. a starting sector and number of sectors (hd_struct)
+ *    given in the part[] array of the gendisk structure for the drive.
+ *
+ * The number of sectors is replicated in the sizes[] array of
+ * the gendisk structure for the major, which again is copied to
+ * the blk_size[][] array.
+ * (However, hd_struct has the number of 512-byte sectors,
+ *  g->sizes[] and blk_size[][] have the number of 1024-byte blocks.)
+ * Note that several drives may have the same major.
+ */
+
+/* a linear search, superfluous when dev is a pointer */
+static struct gendisk *get_gendisk(kdev_t dev) {
+	struct gendisk *g;
+	int m = MAJOR(dev);
+
+	for (g = gendisk_head; g; g = g->next)
+		if (g->major == m)
+			break;
+	return g;
+}
+
+/* moved here from md.c - will be discarded later */
+char *partition_name (kdev_t dev) {
+	static char name[40];		/* kdevname returns 32 bytes */
+					/* disk_name requires 32 bytes */
+	struct gendisk *hd = get_gendisk (dev);
+
+	if (!hd) {
+		sprintf (name, "[dev %s]", kdevname(dev));
+		return (name);
+	}
+
+	return disk_name (hd, MINOR(dev), name);  /* routine in genhd.c */
+}
+
+/*
+ * Add a partition.
+ *
+ * returns: EINVAL: bad parameters
+ *          ENXIO: cannot find drive
+ *          EBUSY: proposed partition overlaps an existing one
+ *                 or has the same number as an existing one
+ *          0: all OK.
+ */
+int add_partition(kdev_t dev, struct blkpg_partition *p) {
+	struct gendisk *g;
+	long long ppstart, pplength;
+	long pstart, plength;
+	int i, drive, first_minor, end_minor, minor;
+
+	/* convert bytes to sectors, check for fit in a hd_struct */
+	ppstart = (p->start >> 9);
+	pplength = (p->length >> 9);
+	pstart = ppstart;
+	plength = pplength;
+	if (pstart != ppstart || plength != pplength
+	    || pstart < 0 || plength < 0)
+		return -EINVAL;
+
+	/* find the drive major */
+	g = get_gendisk(dev);
+	if (!g)
+		return -ENXIO;
+
+	/* existing drive? */
+	drive = (MINOR(dev) >> g->minor_shift);
+	first_minor = (drive << g->minor_shift);
+	end_minor   = first_minor + g->max_p;
+	if (drive >= g->nr_real)
+		return -ENXIO;
+
+	/* drive and partition number OK? */
+	if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
+		return -EINVAL;
+
+	/* partition number in use? */
+	minor = first_minor + p->pno;
+	if (g->part[minor].nr_sects != 0)
+		return -EBUSY;
+
+	/* overlap? */
+	for (i=first_minor+1; i<end_minor; i++)
+		if (!(pstart+plength <= g->part[i].start_sect ||
+		      pstart >= g->part[i].start_sect + g->part[i].nr_sects))
+			return -EBUSY;
+
+	/* all seems OK */
+	g->part[minor].start_sect = pstart;
+	g->part[minor].nr_sects = plength;
+	if (g->sizes)
+		g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9));
+	return 0;
+}
+
+/*
+ * Delete a partition given by partition number
+ *
+ * returns: EINVAL: bad parameters
+ *          ENXIO: cannot find partition
+ *          EBUSY: partition is busy
+ *          0: all OK.
+ *
+ * Note that the dev argument refers to the entire disk, not the partition.
+ */
+int del_partition(kdev_t dev, struct blkpg_partition *p) {
+	struct gendisk *g;
+	kdev_t devp;
+	int drive, first_minor, minor;
+
+	/* find the drive major */
+	g = get_gendisk(dev);
+	if (!g)
+		return -ENXIO;
+
+	/* drive and partition number OK? */
+	drive = (MINOR(dev) >> g->minor_shift);
+	first_minor = (drive << g->minor_shift);
+	if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
+		return -EINVAL;
+
+	/* existing drive and partition? */
+	minor = first_minor + p->pno;
+	if (drive >= g->nr_real || g->part[minor].nr_sects == 0)
+		return -ENXIO;
+
+	/* partition in use? Incomplete check for now. */
+	devp = MKDEV(MAJOR(dev), minor);
+	if (get_super(devp) ||		/* mounted? */
+	    is_swap_partition(devp))
+		return -EBUSY;
+
+	/* all seems OK */
+	fsync_dev(devp);
+	invalidate_buffers(devp);
+
+	g->part[minor].start_sect = 0;
+	g->part[minor].nr_sects = 0;
+	if (g->sizes)
+		g->sizes[minor] = 0;
+
+	return 0;
+}
+
+int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg)
+{
+	struct blkpg_ioctl_arg a;
+	struct blkpg_partition p;
+	int len;
+
+	if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
+		return -EFAULT;
+
+	switch (a.op) {
+		case BLKPG_ADD_PARTITION:
+		case BLKPG_DEL_PARTITION:
+			len = a.datalen;
+			if (len < sizeof(struct blkpg_partition))
+				return -EINVAL;
+			if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+				return -EFAULT;
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (a.op == BLKPG_ADD_PARTITION)
+				return add_partition(dev, &p);
+			else
+				return del_partition(dev, &p);
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ * Common ioctl's for block devices
+ */
+
+int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
+{
+	int intval;
+
+	switch (cmd) {
+		case BLKROSET:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (get_user(intval, (int *)(arg)))
+				return -EFAULT;
+			set_device_ro(dev, intval);
+			return 0;
+		case BLKROGET:
+			intval = (is_read_only(dev) != 0);
+			return put_user(intval, (int *)(arg));
+
+		case BLKRASET:
+			if(!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if(!dev || arg > 0xff)
+				return -EINVAL;
+			read_ahead[MAJOR(dev)] = arg;
+			return 0;
+		case BLKRAGET:
+			if (!arg)
+				return -EINVAL;
+			return put_user(read_ahead[MAJOR(dev)], (long *) arg);
+
+		case BLKFLSBUF:
+			if(!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (!dev)
+				return -EINVAL;
+			fsync_dev(dev);
+			invalidate_buffers(dev);
+			return 0;
+
+		case BLKSSZGET:
+			/* get block device sector size as needed e.g. by fdisk */
+			intval = get_hardsect_size(dev);
+			return put_user(intval, (int *) arg);
+
+#if 0
+		case BLKGETSIZE:
+			/* Today get_gendisk() requires a linear scan;
+			   add this when dev has pointer type. */
+			g = get_gendisk(dev);
+			if (!g)
+				longval = 0;
+			else
+				longval = g->part[MINOR(dev)].nr_sects;
+			return put_user(longval, (long *) arg);
+#endif
+#if 0
+		case BLKRRPART: /* Re-read partition tables */
+			if (!capable(CAP_SYS_ADMIN)) 
+				return -EACCES;
+			return reread_partitions(dev, 1);
+#endif
+
+		case BLKPG:
+			return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg);
+			
+		default:
+			return -EINVAL;
+	}
+}
+
diff -u --recursive --new-file v2.3.2/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- v2.3.2/linux/drivers/block/cmd646.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/cmd646.c	Sat May 15 11:12:09 1999
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $
+/* $Id: cmd646.c,v 1.12 1999/05/14 07:21:01 davem Exp $
X  * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
X  *           Note, this driver is not used at all on other systems because
X  *           there the "BIOS" has done all of the following already.
diff -u --recursive --new-file v2.3.2/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.2/linux/drivers/block/floppy.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/floppy.c	Sat May 15 23:43:04 1999
@@ -198,6 +198,7 @@
X #define MAJOR_NR FLOPPY_MAJOR
X 
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X #include <linux/cdrom.h> /* for the compatibility eject ioctl */
X 
X #ifndef fd_get_dma_residue
@@ -3293,7 +3294,7 @@
X 		LOCK_FDC(drive,1);
X 		if (cmd != FDDEFPRM)
X 			/* notice a disk change immediately, else
-			 * we loose our settings immediately*/
+			 * we lose our settings immediately*/
X 			CALL(poll_drive(1, FD_RAW_NEED_DISK));
X 		user_params[drive] = *g;
X 		if (buffer_drive == drive)
@@ -3402,7 +3403,12 @@
X 
X 	device = inode->i_rdev;
X 	switch (cmd) {
-		RO_IOCTLS(device,param);
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKFLSBUF:
+			return blk_ioctl(device, cmd, param);
X 	}
X 	type = TYPE(device);
X 	drive = DRIVE(device);
@@ -3432,19 +3438,6 @@
X 			loc.start = 0;
X 			return _COPYOUT(loc);
X 		}
-		case BLKRASET:
-			if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-			if(param > 0xff) return -EINVAL;
-			read_ahead[MAJOR(inode->i_rdev)] = param;
-			return 0;
-                case BLKRAGET:
-			return put_user(read_ahead[MAJOR(inode->i_rdev)],
-					(long *) param);
-		case BLKFLSBUF:
-			if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-			fsync_dev(inode->i_rdev);
-			invalidate_buffers(inode->i_rdev);
-			return 0;
X 
X 		case BLKGETSIZE:
X 			ECALL(get_floppy_geometry(drive, type, &g));
diff -u --recursive --new-file v2.3.2/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.3.2/linux/drivers/block/genhd.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/genhd.c	Sat May 15 23:43:04 1999
@@ -66,10 +66,10 @@
X #endif
X 
X /*
- * disk_name() is used by genhd.c and md.c.
- * It formats the devicename of the indicated disk
- * into the supplied buffer, and returns a pointer
- * to that same buffer (for convenience).
+ * disk_name() is used by genhd.c and blkpg.c.
+ * It formats the devicename of the indicated disk into
+ * the supplied buffer (of size at least 32), and returns
+ * a pointer to that same buffer (for convenience).
X  */
X char *disk_name (struct gendisk *hd, int minor, char *buf)
X {
@@ -121,7 +121,7 @@
X 
X static void add_partition (struct gendisk *hd, int minor, int start, int size)
X {
-	char buf[8];
+	char buf[32];
X 	hd->part[minor].start_sect = start;
X 	hd->part[minor].nr_sects   = size;
X 	printk(" %s", disk_name(hd, minor, buf));
@@ -134,12 +134,12 @@
X 		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
X }
X 
-static int sector_partition_scale(kdev_t dev)
+int get_hardsect_size(kdev_t dev)
X {
-       if (hardsect_size[MAJOR(dev)] != NULL)
-               return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512);
-       else
-               return (1);
+	if (hardsect_size[MAJOR(dev)] != NULL)
+		return hardsect_size[MAJOR(dev)][MINOR(dev)];
+	else
+		return 512;
X }
X 
X static unsigned int get_ptable_blocksize(kdev_t dev)
@@ -209,7 +209,7 @@
X 	struct partition *p;
X 	unsigned long first_sector, first_size, this_sector, this_size;
X 	int mask = (1 << hd->minor_shift) - 1;
-	int sector_size = sector_partition_scale(dev);
+	int sector_size = get_hardsect_size(dev) / 512;
X 	int i;
X 
X 	first_sector = hd->part[MINOR(dev)].start_sect;
@@ -453,7 +453,7 @@
X 	struct partition *p;
X 	unsigned char *data;
X 	int mask = (1 << hd->minor_shift) - 1;
-	int sector_size = sector_partition_scale(dev);
+	int sector_size = get_hardsect_size(dev) / 512;
X #ifdef CONFIG_BSD_DISKLABEL
X 	/* no bsd disklabel as a default */
X 	kdev_t bsd_kdev = 0;
@@ -883,10 +883,7 @@
X 	int			 blocksize;
X 
X 	old_blocksize = get_ptable_blocksize(dev);
-	if (hardsect_size[MAJOR(dev)] != NULL)
-		blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
-	else
-		blocksize = 512;
+	blocksize = get_hardsect_size(dev);
X 
X 	set_blocksize(dev,blocksize);
X 	res = 0;
@@ -1223,7 +1220,7 @@
X {
X 	static int first_time = 1;
X 	unsigned long first_sector;
-	char buf[8];
+	char buf[32];
X 
X 	if (first_time)
X 		printk("Partition check:\n");
@@ -1307,28 +1304,21 @@
X 	int end_minor	= dev->max_nr * dev->max_p;
X 
X 	blk_size[dev->major] = NULL;
-	for (i = 0 ; i < end_minor; i++) {
+	for (i = 0; i < end_minor; i++) {
X 		dev->part[i].start_sect = 0;
X 		dev->part[i].nr_sects = 0;
+		dev->sizes[i] = 0;
X 	}
X 	dev->init(dev);	
-	for (drive = 0 ; drive < dev->nr_real ; drive++) {
-		int first_minor	= drive << dev->minor_shift;
-		current_minor = 1 + first_minor;
-		check_partition(dev, MKDEV(dev->major, first_minor));
-	}
-	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
-		for (i = 0; i < end_minor; i++)
-			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
-		blk_size[dev->major] = dev->sizes;
-	}
+	for (drive = 0; drive < dev->nr_real; drive++)
+		resetup_one_dev(dev, drive);
X }
X 
X __initfunc(void device_setup(void))
X {
X 	extern void console_map_init(void);
X #ifdef CONFIG_PARPORT
-	extern int parport_init(void);
+	extern int parport_init(void) __init;
X #endif
X #ifdef CONFIG_MD_BOOT
X         extern void md_setup_drive(void) __init;
diff -u --recursive --new-file v2.3.2/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.3.2/linux/drivers/block/hd.c	Fri May 14 18:55:13 1999
+++ linux/drivers/block/hd.c	Sat May 15 23:43:04 1999
@@ -604,31 +604,25 @@
X 			g.start = hd[MINOR(inode->i_rdev)].start_sect;
X 			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
X 		}
-		case BLKRASET:
-			if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-			if(arg > 0xff) return -EINVAL;
-			read_ahead[MAJOR(inode->i_rdev)] = arg;
-			return 0;
-		case BLKRAGET:
-			if (!arg)  return -EINVAL;
-			return put_user(read_ahead[MAJOR(inode->i_rdev)],
-					(long *) arg); 
+
X          	case BLKGETSIZE:   /* Return device size */
X 			if (!arg)  return -EINVAL;
X 			return put_user(hd[MINOR(inode->i_rdev)].nr_sects, 
X 					(long *) arg);
-		case BLKFLSBUF:
-			if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-			fsync_dev(inode->i_rdev);
-			invalidate_buffers(inode->i_rdev);
-			return 0;
X 
X 		case BLKRRPART: /* Re-read partition tables */
X 			if (!capable(CAP_SYS_ADMIN)) 
X 				return -EACCES;
X 			return revalidate_hddisk(inode->i_rdev, 1);
X 
-		RO_IOCTLS(inode->i_rdev,arg);
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKFLSBUF:
+		case BLKPG:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
+
X 		default:
X 			return -EINVAL;
X 	}
@@ -836,7 +830,7 @@
X 	if (DEVICE_BUSY || USAGE > maxusage) {
X 		restore_flags(flags);
X 		return -EBUSY;
-	};
+	}
X 	DEVICE_BUSY = 1;
X 	restore_flags(flags);
X 
@@ -854,7 +848,7 @@
X 		invalidate_buffers(devi);
X 		gdev->part[minor].start_sect = 0;
X 		gdev->part[minor].nr_sects = 0;
-	};
+	}
X 
X #ifdef MAYBE_REINIT
X 	MAYBE_REINIT;
diff -u --recursive --new-file v2.3.2/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.2/linux/drivers/block/ide.c	Fri May 14 18:55:14 1999
+++ linux/drivers/block/ide.c	Sun May 16 10:56:16 1999
@@ -122,6 +122,7 @@
X #include <linux/major.h>
X #include <linux/errno.h>
X #include <linux/genhd.h>
+#include <linux/blkpg.h>
X #include <linux/malloc.h>
X #include <linux/pci.h>
X #include <linux/delay.h>
@@ -2232,17 +2233,6 @@
X 				(unsigned long *) &loc->start)) return -EFAULT;
X 			return 0;
X 		}
-		case BLKSSZGET:
-			/* Block size of media */
-			return put_user(blksize_size[HWIF(drive)->major]
-						    [minor&PARTN_MASK],
-						    (int *)arg);
-		
-		case BLKFLSBUF:
-			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-			fsync_dev(inode->i_rdev);
-			invalidate_buffers(inode->i_rdev);
-			return 0;
X 
X 	 	case BLKGETSIZE:   /* Return device size */
X 			return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);
@@ -2383,7 +2373,12 @@
X 			drive->nice1 = (arg >> IDE_NICE_1) & 1;
X 			return 0;
X 
-		RO_IOCTLS(inode->i_rdev, arg);
+		case BLKROSET:
+		case BLKROGET:
+ case BLKFLSBUF:
+		case BLKSSZGET:
+		case BLKPG:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
X 
X 		default:
X 			if (drive->driver != NULL)
@@ -2917,121 +2912,10 @@
X  * Returns 1 if the geometry translation was successful.
X  */
X 
-#define ANDRIES_GEOMETRY	0
-
X int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
X {
X 	ide_drive_t *drive;
X 
-#if ANDRIES_GEOMETRY
-	/*
-	 * This is the documented list of values (some version of)
-	 * OnTrack DM uses.
-	 */
-
-	static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
-
-	/*
-	 * This is a pure phantasy list - known to be incorrect.
-	 *
-	 * In fact it seems that EZD does not do anything to the CHS
-	 * values in the partition table, so whether EZD is present
-	 * or not should probably not influence the geometry.
-	 */
-
-	static const byte ez_head_vals[] = {4, 8, 16, 32, 64, 128, 240, 255, 0};        const byte *heads;
-	unsigned long tracks;
-
-	drive = get_info_ptr(i_rdev);
-	if (!drive)
-		return 0;
-
-	if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) {
-		/*
-		 * Update the current 3D drive values.
-		 */
-		drive->id->cur_cyls	= drive->bios_cyl;
-		drive->id->cur_heads	= drive->bios_head;
-		drive->id->cur_sectors	= drive->bios_sect;
-		return 0;	/* we already have a translation */
-	}
-
-	if (xparm == -1) {
-		int ret = 0;
-#if FAKE_FDISK_FOR_EZDRIVE
-		if (drive->remap_0_to_1 == 0) {
-			drive->remap_0_to_1 = 1;
-			printk("%s [remap 0->1]", msg);
-			msg = NULL;
-			ret = 1;
-		}
-		if (drive->bios_head > 16)
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
-		{
-			/*
-			 * Update the current 3D drive values.
-			 */
-			drive->id->cur_cyls	= drive->bios_cyl;
-			drive->id->cur_heads	= drive->bios_head;
-			drive->id->cur_sectors	= drive->bios_sect;
-			return ret;	/* we already have a translation */
-		}
-	}
-
-	if (msg)
-		printk("%s ", msg);
-
-	if (drive->forced_geom) {
-		/*
-		 * Update the current 3D drive values.
-		 */
-		drive->id->cur_cyls	= drive->bios_cyl;
-		drive->id->cur_heads	= drive->bios_head;
-		drive->id->cur_sectors	= drive->bios_sect;
-		return 0;
-	}
-
-#if 1
-	/* There used to be code here that assigned drive->id->CHS
-	   to drive->CHS and that to drive->bios_CHS. However,
-	   some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.
-	   In such cases that code was wrong.  Moreover,
-	   there seems to be no reason to do any of these things. */
-#else
-	if (drive->id) {
-		drive->cyl  = drive->id->cyls;
-		drive->head = drive->id->heads;
-		drive->sect = drive->id->sectors;
-	}
-	drive->bios_cyl  = drive->cyl;
-	drive->bios_head = drive->head;
-	drive->bios_sect = drive->sect;
-	drive->special.b.set_geometry = 1;
-
-#endif
-
-	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
-	drive->bios_sect = 63;
-	if (xparm > 1) {
-		drive->bios_head = xparm;
-		drive->bios_cyl = tracks / drive->bios_head;
-	} else {
-		heads = (xparm == -1) ? ez_head_vals : dm_head_vals;
-		while (drive->bios_cyl >= 1024) {
-			drive->bios_head = *heads;
-			drive->bios_cyl = tracks / drive->bios_head;
-			if (0 == *++heads)
-				break;
-		}
-		if (xparm == 1) {
-			drive->sect0 = 63;
-			drive->bios_cyl = (tracks - 1) / drive->bios_head;
-			printk("[remap +63] ");
-		}
-	}
-
-#else /* ANDRIES_GEOMETRY */
-
X 	static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
X 	const byte *heads = head_vals;
X 	unsigned long tracks;
@@ -3106,7 +2990,6 @@
X 			printk("[remap +63] ");
X 		}
X 	}
-#endif /* ANDRIES_GEOMETRY */
X 
X 	drive->part[0].nr_sects = current_capacity(drive);
X 	printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
diff -u --recursive --new-file v2.3.2/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.2/linux/drivers/block/md.c	Fri May 14 18:55:14 1999
+++ linux/drivers/block/md.c	Sat May 15 23:43:04 1999
@@ -59,6 +59,7 @@
X #define MD_DRIVER
X 
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X #include <asm/uaccess.h>
X #include <asm/bitops.h>
X #include <asm/atomic.h>
@@ -98,36 +99,6 @@
X 
X int md_thread(void * arg);
X 
-static struct gendisk *find_gendisk (kdev_t dev)
-{
-  struct gendisk *tmp=gendisk_head;
-
-  while (tmp != NULL)
-  {
-    if (tmp->major==MAJOR(dev))
-      return (tmp);
-    
-    tmp=tmp->next;
-  }
-
-  return (NULL);
-}
-
-char *partition_name (kdev_t dev)
-{
-  static char name[40];		/* This should be long
-				   enough for a device name ! */
-  struct gendisk *hd = find_gendisk (dev);
-
-  if (!hd)
-  {
-    sprintf (name, "[dev %s]", kdevname(dev));
-    return (name);
-  }
-
-  return disk_name (hd, MINOR(dev), name);  /* routine in genhd.c */
-}
-
X static int legacy_raid_sb (int minor, int pnum)
X {
X 	int i, factor;
@@ -653,24 +624,7 @@
X       return err;
X     break;
X 
-    case BLKFLSBUF:
-    fsync_dev (inode->i_rdev);
-    invalidate_buffers (inode->i_rdev);
-    break;
-
-    case BLKRASET:
-    if (arg > 0xff)
-      return -EINVAL;
-    read_ahead[MAJOR(inode->i_rdev)] = arg;
-    return 0;
X     
-    case BLKRAGET:
-    if  (!arg)  return -EINVAL;
-    err = put_user (read_ahead[MAJOR(inode->i_rdev)], (long *) arg);
-    if (err)
-      return err;
-    break;
-
X     /* We have a problem here : there is no easy way to give a CHS
X        virtual geometry. We currently pretend that we have a 2 heads
X        4 sectors (with a BIG number of cylinders...). This drives dosfs
@@ -693,7 +647,12 @@
X       return err;
X     break;
X     
-    RO_IOCTLS(inode->i_rdev,arg);
+    case BLKROSET:
+    case BLKROGET:
+    case BLKRAGET:
+    case BLKRASET:
+    case BLKFLSBUF:
+	  return blk_ioctl(inode->i_rdev, cmd, arg);
X     
X     default:
X     return -EINVAL;
@@ -901,7 +860,6 @@
X EXPORT_SYMBOL(md_maxreadahead);
X EXPORT_SYMBOL(register_md_personality);
X EXPORT_SYMBOL(unregister_md_personality);
-EXPORT_SYMBOL(partition_name);
X EXPORT_SYMBOL(md_dev);
X EXPORT_SYMBOL(md_error);
X EXPORT_SYMBOL(md_register_thread);
diff -u --recursive --new-file v2.3.2/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.3.2/linux/drivers/block/paride/pd.c	Mon Sep 28 10:51:16 1998
+++ linux/drivers/block/paride/pd.c	Sat May 15 23:43:04 1999
@@ -208,6 +208,7 @@
X #define DEVICE_OFF(device)
X 
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X 
X #include "pseudo.h"
X 
@@ -331,7 +332,7 @@
X static int pd_poffs;			/* partition offset of current minor */
X static char * pd_buf;                   /* buffer for request in progress */
X 
-static struct wait_queue *pd_wait_open = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open);
X 
X static char *pd_errs[17] = { "ERR","INDEX","ECC","DRQ","SEEK","WRERR",
X                              "READY","BUSY","AMNF","TK0NF","ABRT","MCR",
@@ -483,35 +484,23 @@
X 		}
X                 put_user(pd_hd[dev].start_sect,(long *)&geo->start);
X                 return 0;
-            case BLKRASET:
-                if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-                if(!(inode->i_rdev)) return -EINVAL;
-                if(arg > 0xff) return -EINVAL;
-                read_ahead[MAJOR(inode->i_rdev)] = arg;
-                return 0;
-            case BLKRAGET:
-                if (!arg) return -EINVAL;
-                err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
-                if (err) return (err);
-                put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
-                return (0);
X             case BLKGETSIZE:
X                 if (!arg) return -EINVAL;
X                 err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
X                 if (err) return (err);
X                 put_user(pd_hd[dev].nr_sects,(long *) arg);
X                 return (0);
-            case BLKFLSBUF:
-                if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-                if(!(inode->i_rdev)) return -EINVAL;
-                fsync_dev(inode->i_rdev);
-                invalidate_buffers(inode->i_rdev);
-                return 0;
X case BLKRRPART:
X 		if (!capable(CAP_SYS_ADMIN))
X 			return -EACCES;
X                 return pd_revalidate(inode->i_rdev);
-            RO_IOCTLS(inode->i_rdev,arg);
+	    case BLKROSET:
+	    case BLKROGET:
+	    case BLKRASET:
+	    case BLKRAGET:
+	    case BLKFLSBUF:
+	    case BLKPG:
+		return blk_ioctl(inode->i_rdev, cmd, arg);
X             default:
X                 return -EINVAL;
X         }
diff -u --recursive --new-file v2.3.2/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.3.2/linux/drivers/block/paride/pf.c	Wed Nov  4 10:04:43 1998
+++ linux/drivers/block/paride/pf.c	Sat May 15 23:43:04 1999
@@ -205,6 +205,7 @@
X #define DEVICE_OFF(device)
X 
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X 
X #include "pseudo.h"
X 
@@ -433,31 +434,18 @@
X                 }
X                 put_user(0,(long *)&geo->start);
X                 return 0;
-            case BLKRASET:
-                if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-                if(!(inode->i_rdev)) return -EINVAL;
-                if(arg > 0xff) return -EINVAL;
-                read_ahead[MAJOR(inode->i_rdev)] = arg;
-                return 0;
-            case BLKRAGET:
-                if (!arg) return -EINVAL;
-                err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
-                if (err) return (err);
-                put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
-                return (0);
X             case BLKGETSIZE:
X                 if (!arg) return -EINVAL;
X                 err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
X                 if (err) return (err);
X                 put_user(PF.capacity,(long *) arg);
X                 return (0);
-            case BLKFLSBUF:
-                if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-                if(!(inode->i_rdev)) return -EINVAL;
-                fsync_dev(inode->i_rdev);
-                invalidate_buffers(inode->i_rdev);
-                return 0;
- RO_IOCTLS(inode->i_rdev,arg);
+	    case BLKROSET:
+	    case BLKROGET:
+	    case BLKRASET:
+	    case BLKRAGET:
+	    case BLKFLSBUF:
+		return blk_ioctl(inode->i_rdev, cmd, arg);
X             default:
X                 return -EINVAL;
X         }
diff -u --recursive --new-file v2.3.2/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.3.2/linux/drivers/block/ps2esdi.c	Fri May 14 18:55:14 1999
+++ linux/drivers/block/ps2esdi.c	Sat May 15 23:43:04 1999
@@ -42,6 +42,7 @@
X #include <linux/genhd.h>
X #include <linux/ps2esdi.h>
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X #include <linux/mca.h>
X #include <linux/init.h>
X #include <linux/ioport.h>
@@ -1140,15 +1141,7 @@
X 				return (0);
X 			}
X 			break;
-		case BLKRASET:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-			if (!inode->i_rdev)
-				return -EINVAL;
-			if (arg > 0xff)
-				return -EINVAL;
-			read_ahead[MAJOR(inode->i_rdev)] = arg;
-			return 0;
+
X 		case BLKGETSIZE:
X 			if (arg) {
X 				if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
@@ -1158,20 +1151,19 @@
X 				return (0);
X 			}
X 			break;
-		case BLKFLSBUF:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-			if (!inode->i_rdev)
-				return -EINVAL;
-			fsync_dev(inode->i_rdev);
-			invalidate_buffers(inode->i_rdev);
-			return 0;
X 
X 		case BLKRRPART:
X                         if (!capable(CAP_SYS_ADMIN)) 
X 				return -EACCES;
X 			return (ps2esdi_reread_partitions(inode->i_rdev));
-			RO_IOCTLS(inode->i_rdev, arg);
+
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKFLSBUF:
+		case BLKPG:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
X 		}
X 	return (-EINVAL);
X }
diff -u --recursive --new-file v2.3.2/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.2/linux/drivers/block/rd.c	Fri May 14 18:55:14 1999
+++ linux/drivers/block/rd.c	Sat May 15 23:43:04 1999
@@ -72,6 +72,7 @@
X  */
X #define MAJOR_NR RAMDISK_MAJOR
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X 
X /*
X  * We use a block size of 512 bytes in comparision to BLOCK_SIZE
@@ -198,11 +199,10 @@
X 			if (!arg)  return -EINVAL;
X 			return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg);
X 
-		case BLKSSZGET:	   /* Block size of media */
-			if (!arg)  return -EINVAL;
-			return put_user(rd_blocksizes[minor], (int *)arg);
-
-		RO_IOCTLS(inode->i_rdev, arg);
+		case BLKROSET:
+		case BLKROGET:
+		case BLKSSZGET:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
X 
X 		default:
X 			return -EINVAL;
@@ -519,7 +519,7 @@
X 	}
X 
X 	if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
-		printk("RAMDISK: image too big! (%d/%d blocks)\n",
+		printk("RAMDISK: image too big! (%d/%ld blocks)\n",
X 		       nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
X 		goto done;
X 	}
diff -u --recursive --new-file v2.3.2/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.3.2/linux/drivers/block/xd.c	Fri May 14 18:55:15 1999
+++ linux/drivers/block/xd.c	Sat May 15 23:43:04 1999
@@ -49,6 +49,7 @@
X 
X #define MAJOR_NR XT_DISK_MAJOR
X #include <linux/blk.h>
+#include <linux/blkpg.h>
X 
X #include "xd.h"
X 
@@ -337,21 +338,9 @@
X 			g.start = xd_struct[MINOR(inode->i_rdev)].start_sect;
X 			return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
X 		}
-		case BLKRASET:
-			if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-			if(arg > 0xff) return -EINVAL;
-			read_ahead[MAJOR(inode->i_rdev)] = arg;
-			return 0;
-		case BLKRAGET:
-			return put_user(read_ahead[MAJOR(inode->i_rdev)], (long*) arg);
X 		case BLKGETSIZE:
X 			if (!arg) return -EINVAL;
X 			return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
-		case BLKFLSBUF:   /* Return devices size */
-			if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-			fsync_dev(inode->i_rdev);
-			invalidate_buffers(inode->i_rdev);
-			return 0;
X 		case HDIO_SET_DMA:
X 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
X 			if (xdc_busy) return -EBUSY;
@@ -369,7 +358,15 @@
X 			if (!capable(CAP_SYS_ADMIN)) 
X 				return -EACCES;
X 			return xd_reread_partitions(inode->i_rdev);
-		RO_IOCTLS(inode->i_rdev,arg);
+
+		case BLKFLSBUF:
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKPG:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
+
X 		default:
X 			return -EINVAL;
X 	}
diff -u --recursive --new-file v2.3.2/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.3.2/linux/drivers/cdrom/gscd.c	Sat Oct 31 10:28:25 1998
+++ linux/drivers/cdrom/gscd.c	Sat May 15 15:05:36 1999
@@ -76,7 +76,7 @@
X MODULE_PARM(gscd, "h");
X 
X /* Kommt spaeter vielleicht noch mal dran ...
- *    static struct wait_queue *gscd_waitq = NULL;
+ *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
X  */ 
X 
X static void gscd_transfer         (void);
diff -u --recursive --new-file v2.3.2/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.3.2/linux/drivers/cdrom/sbpcd.c	Fri May 14 18:55:15 1999
+++ linux/drivers/cdrom/sbpcd.c	Sat May 15 15:05:36 1999
@@ -585,7 +585,7 @@
X /*==========================================================================*/
X 
X #if FUTURE
-static struct wait_queue *sbp_waitq = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
X #endif FUTURE
X 
X static int teac=SBP_TEAC_SPEED;
diff -u --recursive --new-file v2.3.2/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.3.2/linux/drivers/char/cyclades.c	Fri May 14 18:55:15 1999
+++ linux/drivers/char/cyclades.c	Sat May 15 23:43:04 1999
@@ -1264,7 +1264,7 @@
X 							    TTY_OVERRUN;
X                                         *tty->flip.char_buf_ptr++ = 0;
X                                         /* If the flip buffer itself is
-                                           overflowing, we still loose
+                                           overflowing, we still lose
X                                            the next incoming character.
X                                          */
X                                         if(tty->flip.count
diff -u --recursive --new-file v2.3.2/linux/drivers/char/dn_keyb.c linux/drivers/char/dn_keyb.c
--- v2.3.2/linux/drivers/char/dn_keyb.c	Mon Apr 26 13:28:07 1999
+++ linux/drivers/char/dn_keyb.c	Sat May 15 15:05:36 1999
@@ -47,7 +47,7 @@
X static unsigned int kbd_mode=APOLLO_KBD_MODE_KEYB;
X static short mouse_dx,mouse_dy,mouse_buttons;
X static int mouse_ready=0,mouse_update_allowed=0,mouse_active=0;
-static struct wait_queue *mouse_wait=NULL;
+static DECLARE_WAIT_QUEUE_HEAD(mouse_wait);
X static struct fasync_struct *mouse_fasyncptr=NULL;
X 
X #if 0
diff -u --recursive --new-file v2.3.2/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.3.2/linux/drivers/char/h8.c	Mon Aug 24 13:02:44 1998
+++ linux/drivers/char/h8.c	Sat May 15 15:05:36 1999
@@ -160,7 +160,7 @@
X  */
X int cpu_speed_divisor = -1;			
X int h8_event_mask = 0;			
-struct wait_queue *h8_monitor_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(h8_monitor_wait);
X unsigned int h8_command_mask = 0;
X int h8_uthermal_threshold = DEFAULT_UTHERMAL_THRESHOLD;
X int h8_uthermal_window = UTH_HYSTERESIS;		      
@@ -170,7 +170,7 @@
X u_char h8_current_temp = 0;
X u_char h8_system_temp = 0;
X int h8_sync_channel = 0;
-struct wait_queue *h8_sync_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(h8_sync_wait);
X int h8_init_performed;
X 
X /* CPU speeds and clock divisor values */
diff -u --recursive --new-file v2.3.2/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.2/linux/drivers/char/keyboard.c	Fri May 14 18:55:16 1999
+++ linux/drivers/char/keyboard.c	Sun May 16 10:12:38 1999
SHAR_EOF
true || echo 'restore of patch-2.3.3 failed'
fi
echo 'End of  part 1'
echo 'File patch-2.3.3 is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 4 of a 4 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.3 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 4; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.3'
else
echo 'x - continuing with patch-2.3.3'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.3' &&
X 		inode->i_mode |= S_ISGID;
X 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.2/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.3.2/linux/include/asm-alpha/processor.h	Mon Jan 18 09:55:30 1999
+++ linux/include/asm-alpha/processor.h	Sat May 15 23:43:04 1999
@@ -85,7 +85,7 @@
X  * is the frame pointer in schedule() and $15 is saved at offset 48 by
X  * entry.S:do_switch_stack).
X  *
- * Under heavy swap load I've seen this loose in an ugly way.  So do
+ * Under heavy swap load I've seen this lose in an ugly way.  So do
X  * some extra sanity checking on the ranges we expect these pointers
X  * to be in so that we can fail gracefully.  This is just for ps after
X  * all.  -- r~
diff -u --recursive --new-file v2.3.2/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.3.2/linux/include/asm-alpha/semaphore.h	Fri May  7 10:55:26 1999
+++ linux/include/asm-alpha/semaphore.h	Sat May 15 15:05:37 1999
@@ -16,7 +16,7 @@
X 	/* Careful, inline assembly knows about the position of these two.  */
X 	atomic_t count;
X 	atomic_t waking;		/* biased by -1 */
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X };
X 
X #define MUTEX ((struct semaphore) \
diff -u --recursive --new-file v2.3.2/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.3.2/linux/include/asm-arm/semaphore.h	Fri May 14 18:55:27 1999
+++ linux/include/asm-arm/semaphore.h	Sat May 15 15:05:37 1999
@@ -10,7 +10,7 @@
X struct semaphore {
X 	atomic_t count;
X 	int waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
X };
X 
X #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
diff -u --recursive --new-file v2.3.2/linux/include/asm-m68k/adb_mouse.h linux/include/asm-m68k/adb_mouse.h
--- v2.3.2/linux/include/asm-m68k/adb_mouse.h	Wed Sep  2 09:39:18 1998
+++ linux/include/asm-m68k/adb_mouse.h	Sat May 15 15:05:37 1999
@@ -16,7 +16,7 @@
X 	short		dy;
X 	int		ready;
X 	int		active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X 	struct fasync_struct *fasyncptr;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/include/asm-m68k/atari_joystick.h linux/include/asm-m68k/atari_joystick.h
--- v2.3.2/linux/include/asm-m68k/atari_joystick.h	Sat Mar 30 04:11:24 1996
+++ linux/include/asm-m68k/atari_joystick.h	Sat May 15 15:05:37 1999
@@ -16,7 +16,7 @@
X 	char		dir;
X 	int		ready;
X 	int		active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X };
X 
X #endif
diff -u --recursive --new-file v2.3.2/linux/include/asm-m68k/mac_mouse.h linux/include/asm-m68k/mac_mouse.h
--- v2.3.2/linux/include/asm-m68k/mac_mouse.h	Thu Feb 12 16:30:13 1998
+++ linux/include/asm-m68k/mac_mouse.h	Sat May 15 15:05:37 1999
@@ -16,7 +16,7 @@
X 	short		dy;
X 	int		ready;
X 	int		active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X 	struct fasync_struct *fasyncptr;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.3.2/linux/include/asm-m68k/semaphore.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-m68k/semaphore.h	Sat May 15 15:05:37 1999
@@ -18,7 +18,7 @@
X struct semaphore {
X 	atomic_t count;
X 	atomic_t waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
X };
X 
X #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
diff -u --recursive --new-file v2.3.2/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- v2.3.2/linux/include/asm-mips/semaphore.h	Thu Jan 14 15:53:25 1999
+++ linux/include/asm-mips/semaphore.h	Sat May 15 15:05:37 1999
@@ -17,7 +17,7 @@
X struct semaphore {
X 	atomic_t count;
X 	atomic_t waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
X };
X 
X #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
diff -u --recursive --new-file v2.3.2/linux/include/asm-ppc/adb_mouse.h linux/include/asm-ppc/adb_mouse.h
--- v2.3.2/linux/include/asm-ppc/adb_mouse.h	Mon Jan 12 15:18:13 1998
+++ linux/include/asm-ppc/adb_mouse.h	Sat May 15 15:05:37 1999
@@ -16,7 +16,7 @@
X 	short		dy;
X 	int		ready;
X 	int		active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X 	struct fasync_struct *fasyncptr;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.3.2/linux/include/asm-ppc/semaphore.h	Wed Mar 10 21:30:32 1999
+++ linux/include/asm-ppc/semaphore.h	Sat May 15 15:05:37 1999
@@ -13,7 +13,7 @@
X struct semaphore {
X 	atomic_t count;
X 	atomic_t waking;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
X };
X 
X #define sema_init(sem, val)	atomic_set(&((sem)->count), (val))
diff -u --recursive --new-file v2.3.2/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v2.3.2/linux/include/asm-sparc/io.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-sparc/io.h	Sat May 15 11:12:09 1999
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.18 1998/09/21 05:07:17 jj Exp $ */
+/* $Id: io.h,v 1.19 1999/05/14 07:26:09 davem Exp $ */
X #ifndef __SPARC_IO_H
X #define __SPARC_IO_H
X 
diff -u --recursive --new-file v2.3.2/linux/include/asm-sparc64/hdreg.h linux/include/asm-sparc64/hdreg.h
--- v2.3.2/linux/include/asm-sparc64/hdreg.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-sparc64/hdreg.h	Sat May 15 11:12:09 1999
@@ -1,4 +1,4 @@
-/* $Id: hdreg.h,v 1.9 1998/05/08 21:05:28 davem Exp $
+/* $Id: hdreg.h,v 1.1 1999/05/14 07:23:13 davem Exp $
X  * hdreg.h: Ultra/PCI specific IDE glue.
X  *
X  * Copyright (C) 1997  David S. Miller (da...@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.2/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.3.2/linux/include/asm-sparc64/ide.h	Fri May 14 18:55:28 1999
+++ linux/include/asm-sparc64/ide.h	Sat May 15 11:12:10 1999
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.12 1999/04/17 14:25:29 davem Exp $
+/* $Id: ide.h,v 1.14 1999/05/15 05:02:35 davem Exp $
X  * ide.h: Ultra/PCI specific IDE glue.
X  *
X  * Copyright (C) 1997  David S. Miller (da...@caip.rutgers.edu)
@@ -11,6 +11,8 @@
X #ifdef __KERNEL__
X 
X #include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/hdreg.h>
X 
X #undef  MAX_HWIFS
X #define MAX_HWIFS	2
diff -u --recursive --new-file v2.3.2/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.3.2/linux/include/asm-sparc64/io.h	Fri May 14 18:55:29 1999
+++ linux/include/asm-sparc64/io.h	Sat May 15 11:12:10 1999
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.19 1998/08/23 05:41:46 ecd Exp $ */
+/* $Id: io.h,v 1.20 1999/05/14 07:23:18 davem Exp $ */
X #ifndef __SPARC64_IO_H
X #define __SPARC64_IO_H
X 
diff -u --recursive --new-file v2.3.2/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.3.2/linux/include/linux/blk.h	Tue May 11 13:05:32 1999
+++ linux/include/linux/blk.h	Sun May 16 13:19:06 1999
@@ -85,12 +85,6 @@
X 
X #endif
X 
-#define RO_IOCTLS(dev,where) \
-  case BLKROSET: { int __val;  if (!capable(CAP_SYS_ADMIN)) return -EACCES; \
-		   if (get_user(__val, (int *)(where))) return -EFAULT; \
-		   set_device_ro((dev),__val); return 0; } \
-  case BLKROGET: { int __val = (is_read_only(dev) != 0) ; \
-		    return put_user(__val,(int *) (where)); }
X 		 
X #if defined(MAJOR_NR) || defined(IDE_DRIVER)
X 
diff -u --recursive --new-file v2.3.2/linux/include/linux/blkpg.h linux/include/linux/blkpg.h
--- v2.3.2/linux/include/linux/blkpg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/blkpg.h	Sat May 15 23:43:04 1999
@@ -0,0 +1,64 @@
+#ifndef _LINUX_BLKPG_H
+#define _LINUX_BLKPG_H
+
+/*
+ * Partition table and disk geometry handling
+ *
+ * A single ioctl with lots of subfunctions:
+ *
+ * Device number stuff:
+ *    get_whole_disk()		(given the device number of a partition,
+ * find the device number of the encompassing disk)
+ *    get_all_partitions()	(given the device number of a disk, return the
+ *				 device numbers of all its known partitions)
+ *
+ * Partition stuff:
+ *    add_partition()
+ *    delete_partition()
+ *    test_partition_in_use()	(also for test_disk_in_use)
+ *
+ * Geometry stuff:
+ *    get_geometry()
+ *    set_geometry()
+ *    get_bios_drivedata()
+ *
+ * For today, only the partition stuff - aeb, 990515
+ */
+#include <linux/ioctl.h>
+
+#define BLKPG      _IO(0x12,105)
+
+/* The argument structure */
+struct blkpg_ioctl_arg {
+        int op;
+        int flags;
+        int datalen;
+        void *data;
+} *p;
+
+/* The subfunctions (for the op field) */
+#define BLKPG_ADD_PARTITION	1
+#define BLKPG_DEL_PARTITION	2
+
+/* Sizes of name fields. Unused at present. */
+#define BLKPG_DEVNAMELTH	64
+#define BLKPG_VOLNAMELTH	64
+
+/* The data structure for ADD_PARTITION and DEL_PARTITION */
+struct blkpg_partition {
+	long long start;		/* starting offset in bytes */
+	long long length;		/* length in bytes */
+	int pno;			/* partition number */
+	char devname[BLKPG_DEVNAMELTH];	/* partition name, like sda5 or c0d1p2,
+					   to be used in kernel messages */
+	char volname[BLKPG_VOLNAMELTH];	/* volume label */
+};
+
+#ifdef __KERNEL__
+
+extern char * partition_name(kdev_t dev);
+extern int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_BLKPG_H */
diff -u --recursive --new-file v2.3.2/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.2/linux/include/linux/fs.h	Sat May 15 23:46:05 1999
+++ linux/include/linux/fs.h	Sun May 16 13:18:20 1999
@@ -140,6 +140,7 @@
X #define IS_NOATIME(inode)	__IS_FLG(inode, MS_NOATIME)
X #define IS_NODIRATIME(inode)	__IS_FLG(inode, MS_NODIRATIME)
X 
+
X /* the read-only stuff doesn't really belong here, but any other place is
X    probably as bad and I don't want to create yet another include file. */
X 
@@ -154,7 +155,13 @@
X #define BLKFRAGET  _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
X #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
X #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
-#define BLKSSZGET  _IO(0x12,104)/* get block device sector size (reserved for) */
+#define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
+#if 0
+#define BLKPG      _IO(0x12,105)/* See blkpg.h */
+/* This was here just to show that the number is taken -
+   probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
+#endif
+
X 
X #define BMAP_IOCTL 1		/* obsolete - kept for compatibility */
X #define FIBMAP	   _IO(0x00,1)	/* bmap access */
@@ -724,7 +731,6 @@
X extern char * cdevname(kdev_t dev);
X extern char * kdevname(kdev_t dev);
X extern void init_special_inode(struct inode *, umode_t, int);
-
X 
X extern void init_fifo(struct inode * inode);
X extern struct inode_operations fifo_inode_operations;
diff -u --recursive --new-file v2.3.2/linux/include/linux/genhd.h linux/include/linux/genhd.h
--- v2.3.2/linux/include/linux/genhd.h	Sat May 15 23:46:05 1999
+++ linux/include/linux/genhd.h	Sun May 16 13:18:19 1999
@@ -39,7 +39,7 @@
X #endif
X 
X #define DM6_PARTITION		0x54	/* has DDO: use xlated geom & offset */
-#define EZD_PARTITION		0x55	/* EZ-DRIVE:  same as DM6 (we think) */
+#define EZD_PARTITION		0x55	/* EZ-DRIVE */
X #define DM6_AUX1PARTITION	0x51	/* no DDO:  use xlated geom */
X #define DM6_AUX3PARTITION	0x53	/* no DDO:  use xlated geom */
X 	
@@ -70,8 +70,8 @@
X 	int max_nr;			/* maximum number of real devices */
X 
X 	void (*init)(struct gendisk *);	/* Initialization called before we do our thing */
-	struct hd_struct *part;		/* partition table */
-	int *sizes;			/* device size in blocks, copied to blk_size[] */
+	struct hd_struct *part;		/* [indexed by minor] */
+	int *sizes;			/* [idem], device size in blocks */
X 	int nr_real;			/* number of real devices */
X 
X 	void *real_devices;		/* internal use */
@@ -226,14 +226,12 @@
X 
X #endif /* CONFIG_UNIXWARE_DISKLABEL */
X 
+#ifdef __KERNEL__
X extern struct gendisk *gendisk_head;	/* linked list of disks */
X 
-/*
- * disk_name() is used by genhd.c and md.c.
- * It formats the devicename of the indicated disk
- * into the supplied buffer, and returns a pointer
- * to that same buffer (for convenience).
- */
X char *disk_name (struct gendisk *hd, int minor, char *buf);
+
+int get_hardsect_size(kdev_t dev);
+#endif
X 
X #endif
diff -u --recursive --new-file v2.3.2/linux/include/linux/hpfs_fs_sb.h linux/include/linux/hpfs_fs_sb.h
--- v2.3.2/linux/include/linux/hpfs_fs_sb.h	Sat May 15 23:46:05 1999
+++ linux/include/linux/hpfs_fs_sb.h	Sun May 16 10:33:30 1999
@@ -24,13 +24,13 @@
X 	unsigned sb_rd_inode : 2;	/* lookup tells read_inode: 1-read fnode
X 					   2-don't read fnode, file
X 					   3-don't read fnode, direcotry */
-	struct wait_queue *sb_iget_q;
+	wait_queue_head_t sb_iget_q;
X 	unsigned char *sb_cp_table;	/* code page tables: */
X 					/* 	128 bytes uppercasing table & */
X 					/*	128 bytes lowercasing table */
X 	unsigned *sb_bmp_dir;		/* main bitmap directory */
X 	unsigned sb_c_bitmap;		/* current bitmap */
-	struct wait_queue *sb_creation_de;/* when creating dirents, nobody else
+	wait_queue_head_t sb_creation_de;/* when creating dirents, nobody else
X 					   can alloc blocks */
X 	unsigned sb_creation_de_lock : 1;
X 	/*unsigned sb_mounting : 1;*/
@@ -55,7 +55,7 @@
X #define s_hpfs_chk u.hpfs_sb.sb_chk
X #define s_hpfs_was_error u.hpfs_sb.sb_was_error
X #define s_hpfs_chkdsk u.hpfs_sb.sb_chkdsk
-#define s_hpfs_rd_fnode u.hpfs_sb.sb_rd_fnode
+/*#define s_hpfs_rd_fnode u.hpfs_sb.sb_rd_fnode*/
X #define s_hpfs_rd_inode u.hpfs_sb.sb_rd_inode
X #define s_hpfs_cp_table u.hpfs_sb.sb_cp_table
X #define s_hpfs_bmp_dir u.hpfs_sb.sb_bmp_dir
diff -u --recursive --new-file v2.3.2/linux/include/linux/istallion.h linux/include/linux/istallion.h
--- v2.3.2/linux/include/linux/istallion.h	Wed Feb  4 14:52:16 1998
+++ linux/include/linux/istallion.h	Sat May 15 15:05:37 1999
@@ -70,9 +70,9 @@
X 	long			pgrp;
X 	unsigned int		rxmarkmsk;
X 	struct tty_struct	*tty;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
- struct wait_queue *raw_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	raw_wait;
X 	struct tq_struct	tqhangup;
X 	struct termios		normaltermios;
X 	struct termios		callouttermios;
diff -u --recursive --new-file v2.3.2/linux/include/linux/lp_m68k.h linux/include/linux/lp_m68k.h
--- v2.3.2/linux/include/linux/lp_m68k.h	Fri Nov 20 11:44:06 1998
+++ linux/include/linux/lp_m68k.h	Sat May 15 15:05:37 1999
@@ -116,7 +116,7 @@
X 	unsigned int chars;	/*busy timeout */
X 	unsigned int time;	/*wait time */
X 	unsigned int wait;
-	struct wait_queue *lp_wait_q; /*strobe wait */
+	struct wait_queue_head_t lp_wait_q; /*strobe wait */
X 	void *base;			/* hardware drivers internal use*/
X 	enum lp_type type;
X 	char lp_buffer[LP_BUFFER_SIZE];
diff -u --recursive --new-file v2.3.2/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.2/linux/include/linux/netdevice.h	Tue May 11 13:05:03 1999
+++ linux/include/linux/netdevice.h	Sun May 16 18:28:33 1999
@@ -405,7 +405,7 @@
X extern __inline__ void dev_lock_wait(void)
X {
X 	while (atomic_read(&dev_lockct)) {
-		current->counter = 0;
+		current->policy |= SCHED_YIELD;
X 		schedule();
X 	}
X }
diff -u --recursive --new-file v2.3.2/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.2/linux/include/linux/parport.h	Fri May 14 18:55:29 1999
+++ linux/include/linux/parport.h	Sun May 16 13:19:20 1999
@@ -184,6 +184,7 @@
X /* A parallel port */
X struct parport {
X 	unsigned long base;	/* base address */
+	unsigned long base_hi;	/* base address (ECR) */
X 	unsigned int size;	/* IO extent */
X 	const char *name;
X 	int irq;		/* interrupt (or -1 for none) */
diff -u --recursive --new-file v2.3.2/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h
--- v2.3.2/linux/include/linux/parport_pc.h	Tue May 11 13:04:45 1999
+++ linux/include/linux/parport_pc.h	Sun May 16 13:18:35 1999
@@ -5,14 +5,14 @@
X 
X /* --- register definitions ------------------------------- */
X 
-#define ECONTROL 0x402
-#define CONFIGB  0x401
-#define CONFIGA  0x400
-#define EPPDATA  0x4
-#define EPPADDR  0x3
-#define CONTROL  0x2
-#define STATUS   0x1
-#define DATA     0
+#define ECONTROL(p)	((p)->base_hi + 0x02)
+#define CONFIGB(p)	((p)->base_hi + 0x01)
+#define CONFIGA(p)	((p)->base_hi + 0x00)
+#define EPPDATA(p)	((p)->base    + 0x04)
+#define EPPADDR(p)	((p)->base    + 0x03)
+#define CONTROL(p)	((p)->base    + 0x02)
+#define STATUS(p)	((p)->base    + 0x01)
+#define DATA(p)		((p)->base    + 0x00)
X 
X /* Private data for PC low-level driver. */
X struct parport_pc_private {
@@ -26,27 +26,27 @@
X 
X extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+EPPDATA);
+	outb(d, EPPDATA(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_epp(struct parport *p)
X {
-	return inb(p->base+EPPDATA);
+	return inb(EPPDATA(p));
X }
X 
X extern __inline__ void parport_pc_write_epp_addr(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+EPPADDR);
+	outb(d, EPPADDR(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_epp_addr(struct parport *p)
X {
-	return inb(p->base+EPPADDR);
+	return inb(EPPADDR(p));
X }
X 
X extern __inline__ int parport_pc_check_epp_timeout(struct parport *p)
X {
-	if (!(inb(p->base+STATUS) & 1))
+	if (!(inb(STATUS(p)) & 1))
X 		return 0;
X 	parport_pc_epp_clear_timeout(p);
X 	return 1;
@@ -54,24 +54,24 @@
X 
X extern __inline__ unsigned char parport_pc_read_configb(struct parport *p)
X {
-	return inb(p->base+CONFIGB);
+	return inb(CONFIGB(p));
X }
X 
X extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+DATA);
+	outb(d, DATA(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_data(struct parport *p)
X {
-	return inb(p->base+DATA);
+	return inb(DATA(p));
X }
X 
X extern __inline__ void parport_pc_write_control(struct parport *p, unsigned char d)
X {
X 	struct parport_pc_private *priv = p->private_data;
X 	priv->ctr = d;/* update soft copy */
-	outb(d, p->base+CONTROL);
+	outb(d, CONTROL(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_control(struct parport *p)
@@ -85,34 +85,34 @@
X 	struct parport_pc_private *priv = p->private_data;
X 	unsigned char ctr = priv->ctr;
X 	ctr = (ctr & ~mask) ^ val;
-	outb (ctr, p->base+CONTROL);
+	outb (ctr, CONTROL(p));
X 	return priv->ctr = ctr; /* update soft copy */
X }
X 
X extern __inline__ void parport_pc_write_status(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+STATUS);
+	outb(d, STATUS(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_status(struct parport *p)
X {
-	return inb(p->base+STATUS);
+	return inb(STATUS(p));
X }
X 
X extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned char d)
X {
-	outb(d, p->base+ECONTROL);
+	outb(d, ECONTROL(p));
X }
X 
X extern __inline__ unsigned char parport_pc_read_econtrol(struct parport *p)
X {
-	return inb(p->base+ECONTROL);
+	return inb(ECONTROL(p));
X }
X 
X extern __inline__ unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val)
X {
-	unsigned char old = inb(p->base+ECONTROL);
-	outb(((old & ~mask) ^ val), p->base+ECONTROL);
+	unsigned char old = inb(ECONTROL(p));
+	outb(((old & ~mask) ^ val), ECONTROL(p));
X 	return old;
X }
X 
diff -u --recursive --new-file v2.3.2/linux/include/linux/rpcsock.h linux/include/linux/rpcsock.h
--- v2.3.2/linux/include/linux/rpcsock.h	Thu Dec 12 06:54:20 1996
+++ linux/include/linux/rpcsock.h	Sat May 15 15:05:37 1999
@@ -77,7 +77,7 @@
X 	struct rpc_wait *	w_next;
X 	struct rpc_ioreq *	w_req;
X 	int			w_result;
-	struct wait_queue *	w_wait;
+	wait_queue_head_t 	w_wait;
X 	rpc_callback_fn_t	w_handler;
X 	void *			w_cdata;
X 	char			w_queued;
@@ -94,8 +94,8 @@
X 	unsigned long		cwnd;
X 	struct rpc_wait *	pending;
X 	struct rpc_wait *	free;
-	struct wait_queue *	backlog;
-	struct wait_queue *	shutwait;
+	wait_queue_head_t	backlog;
+	wait_queue_head_t	shutwait;
X 	int			shutdown;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/include/linux/serial167.h linux/include/linux/serial167.h
--- v2.3.2/linux/include/linux/serial167.h	Mon Oct  5 14:12:12 1998
+++ linux/include/linux/serial167.h	Sat May 15 15:05:37 1999
@@ -54,8 +54,8 @@
X 	struct tq_struct	tqueue;
X 	struct termios		normal_termios;
X 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
X         struct cyclades_monitor mon;
X };
X 
diff -u --recursive --new-file v2.3.2/linux/include/linux/stallion.h linux/include/linux/stallion.h
--- v2.3.2/linux/include/linux/stallion.h	Wed Feb  4 14:52:16 1998
+++ linux/include/linux/stallion.h	Sat May 15 15:05:37 1999
@@ -95,8 +95,8 @@
X 	unsigned long		hwid;
X 	void			*uartp;
X 	struct tty_struct	*tty;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
X 	struct termios		normaltermios;
X 	struct termios		callouttermios;
X 	struct tq_struct	tqueue;
diff -u --recursive --new-file v2.3.2/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.2/linux/include/linux/swap.h	Tue May 11 13:03:58 1999
+++ linux/include/linux/swap.h	Sun May 16 13:18:20 1999
@@ -113,6 +113,7 @@
X /* linux/mm/swapfile.c */
X extern unsigned int nr_swapfiles;
X extern struct swap_info_struct swap_info[];
+extern int is_swap_partition(kdev_t);
X void si_swapinfo(struct sysinfo *);
X unsigned long get_swap_page(void);
X extern void FASTCALL(swap_free(unsigned long));
diff -u --recursive --new-file v2.3.2/linux/include/linux/umsdos_fs_i.h linux/include/linux/umsdos_fs_i.h
--- v2.3.2/linux/include/linux/umsdos_fs_i.h	Sun Dec 27 22:18:28 1998
+++ linux/include/linux/umsdos_fs_i.h	Sat May 15 15:05:37 1999
@@ -47,7 +47,7 @@
X  */
X 
X struct dir_locking_info {
-	struct wait_queue *p;
+	wait_queue_head_t p;
X 	short int looking;	/* How many process doing a lookup */
X 	short int creating;	/* Is there any creation going on here
X 				 *  Only one at a time, although one
diff -u --recursive --new-file v2.3.2/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.2/linux/kernel/ksyms.c	Sat May 15 23:46:05 1999
+++ linux/kernel/ksyms.c	Sat May 15 23:43:04 1999
@@ -32,6 +32,7 @@
X #include <linux/hdreg.h>
X #include <linux/skbuff.h>
X #include <linux/genhd.h>
+#include <linux/blkpg.h>
X #include <linux/swap.h>
X #include <linux/ctype.h>
X #include <linux/file.h>
@@ -327,6 +328,7 @@
X EXPORT_SYMBOL(kdevname);
X EXPORT_SYMBOL(bdevname);
X EXPORT_SYMBOL(cdevname);
+EXPORT_SYMBOL(partition_name);		/* md.c only */
X EXPORT_SYMBOL(simple_strtoul);
X EXPORT_SYMBOL(system_utsname);	/* UTS data */
X EXPORT_SYMBOL(uts_sem);		/* UTS semaphore */
diff -u --recursive --new-file v2.3.2/linux/mm/mlock.c linux/mm/mlock.c
--- v2.3.2/linux/mm/mlock.c	Fri Nov 20 11:43:19 1998
+++ linux/mm/mlock.c	Sun May 16 21:45:23 1999
@@ -115,10 +115,11 @@
X 	if (!retval) {
X 		/* keep track of amount of locked VM */
X 		pages = (end - start) >> PAGE_SHIFT;
-		if (!(newflags & VM_LOCKED))
+		if (newflags & VM_LOCKED) {
X 			pages = -pages;
-		vma->vm_mm->locked_vm += pages;
-		make_pages_present(start, end);
+			make_pages_present(start, end);
+		}
+		vma->vm_mm->locked_vm -= pages;
X 	}
X 	return retval;
X }
diff -u --recursive --new-file v2.3.2/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.2/linux/mm/swapfile.c	Sun Mar  7 15:49:14 1999
+++ linux/mm/swapfile.c	Sat May 15 23:43:05 1999
@@ -473,6 +473,18 @@
X 	return len;
X }
X 
+int is_swap_partition(kdev_t dev) {
+	struct swap_info_struct *ptr = swap_info;
+	int i;
+
+	for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
+		if (ptr->flags & SWP_USED)
+			if (ptr->swap_device == dev)
+				return 1;
+	}
+	return 0;
+}
+
X /*
X  * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
X  *
diff -u --recursive --new-file v2.3.2/linux/net/core/filter.c linux/net/core/filter.c
--- v2.3.2/linux/net/core/filter.c	Thu Mar 25 09:23:34 1999
+++ linux/net/core/filter.c	Sat May 15 17:43:46 1999
@@ -106,7 +106,7 @@
X 				continue;
X 
X 			case BPF_ALU|BPF_MUL|BPF_K:
-				A *= X;
+				A *= fentry->k;
X 				continue;
X 
X 			case BPF_ALU|BPF_DIV|BPF_X:
diff -u --recursive --new-file v2.3.2/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.3.2/linux/net/ipv4/tcp_timer.c	Mon May 10 09:55:25 1999
+++ linux/net/ipv4/tcp_timer.c	Sat May 15 16:58:06 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_timer.c,v 1.62 1999/05/08 21:09:55 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.63 1999/05/15 23:02:21 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -541,10 +541,6 @@
X 						prev = conn; 
X 						continue; 
X 					}
-
-					if ((long)(now - conn->expires) <= 0)
-						break;
-
X 
X 					tcp_synq_unlink(tp, conn, prev);
X 					if (conn->retrans >= sysctl_tcp_retries1) {
diff -u --recursive --new-file v2.3.2/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c
--- v2.3.2/linux/net/ipv6/exthdrs.c	Sun Oct  4 10:19:40 1998
+++ linux/net/ipv6/exthdrs.c	Sat May 15 23:43:05 1999
@@ -369,7 +369,7 @@
X    Certainly, it is possible only for udp and raw sockets, but not for tcp.
X 
X    AUTH header has 4byte granular length, which kills all the idea
-   behind AUTOMATIC 64bit alignment of IPv6. Now we will loose
+   behind AUTOMATIC 64bit alignment of IPv6. Now we will lose
X    cpu ticks, checking that sender did not something stupid
X    and opt->hdrlen is even. Shit!		--ANK (980730)
X  */
diff -u --recursive --new-file v2.3.2/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.3.2/linux/net/netlink/af_netlink.c	Fri May 14 18:55:32 1999
+++ linux/net/netlink/af_netlink.c	Sun May 16 18:28:33 1999
@@ -203,7 +203,7 @@
X 	 */
X 
X 	while (netlink_locked(sk)) {
-		current->counter = 0;
+		current->policy |= SCHED_YIELD;
X 		schedule();
X 	}
X 
SHAR_EOF
true || echo 'restore of patch-2.3.3 failed'
echo 'File patch-2.3.3 is complete' &&
chmod 644 patch-2.3.3 ||
echo 'restore of patch-2.3.3 failed'
Cksum="`cksum < 'patch-2.3.3'`"
if ! test "2637971809 197362" = "$Cksum"
then
	echo 'patch-2.3.3: original Checksum 2637971809 197362, current one' "$Cksum" 
	rm -f _shar_wnt_.tmp
	rm -f _shar_seq_.tmp
	exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'
exit 0
#!/bin/sh
# this is part 3 of a 4 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.3.3 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.3.3'
else
echo 'x - continuing with patch-2.3.3'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.3.3' &&
-	{
-		unsigned long flags;
-		spin_lock_irqsave(&ohci_edtd_lock, flags);
-		ohci_add_td_to_ed(setup_td, control_ed);
-		spin_unlock_irqrestore(&ohci_edtd_lock, flags);
-	}
+	spin_lock_irqsave(&ohci_edtd_lock, flags);
+	control_ed->status |= OHCI_ED_SKIP;
+	ohci_add_td_to_ed(setup_td, control_ed);
+	if (data_td != status_td)
+		ohci_add_td_to_ed(data_td, control_ed);
+	ohci_add_td_to_ed(status_td, control_ed);
+	control_ed->status &= ~OHCI_ED_SKIP;
+	ohci_unhalt_ed(control_ed);
+	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
X 
-#if 0
+#ifdef OHCI_DEBUG
+	if (MegaDebug) {
X 	/* complete transaction debugging output (before) */
X 	printk(KERN_DEBUG " Control ED %lx:\n", virt_to_bus(control_ed));
X 	show_ohci_ed(control_ed);
@@ -623,48 +839,55 @@
X 	}
X 	printk(KERN_DEBUG " Status TD %lx:\n", virt_to_bus(status_td));
X 	show_ohci_td(status_td);
+	printk(KERN_DEBUG " Controller Status:\n");
+	show_ohci_status(dev->ohci);
+	}
X #endif
X 
+	/*
+	 * Start the control transaction..
+	 */
+	current->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue(&control_wakeup, &wait);
+
X 	/* Give the ED to the HC */
X 	ohci_add_control_ed(dev->ohci, control_ed);
X 
-	/* FIXME:
-	 * this should really check to see that the transaction completed.
-	 */
X 	schedule_timeout(HZ/10);
X 
X 	remove_wait_queue(&control_wakeup, &wait);
X 
-#if 0
+#ifdef OHCI_DEBUG
+	if (MegaDebug) {
X 	/* complete transaction debugging output (after) */
-	printk(KERN_DEBUG " (after) Control ED:\n");
+	printk(KERN_DEBUG " *after* Control ED %lx:\n", virt_to_bus(control_ed));
X 	show_ohci_ed(control_ed);
-	printk(KERN_DEBUG " (after) Setup TD:\n");
+	printk(KERN_DEBUG " *after* Setup TD %lx:\n", virt_to_bus(setup_td));
X 	show_ohci_td(setup_td);
X 	if (data_td != status_td) {
-		printk(KERN_DEBUG " (after) Data TD:\n");
+		printk(KERN_DEBUG " *after* Data TD %lx:\n", virt_to_bus(data_td));
X 		show_ohci_td(data_td);
X 	}
-	printk(KERN_DEBUG " (after) Status TD:\n");
+	printk(KERN_DEBUG " *after* Status TD %lx:\n", virt_to_bus(status_td));
X 	show_ohci_td(status_td);
+	printk(KERN_DEBUG " *after* Controller Status:\n");
+	show_ohci_status(dev->ohci);
+	}
X #endif
X 
-	/* clean up incase it failed */
-	/* XXX only do this if their ed pointer still points to control_ed
-	 * incase they've been reclaimed and used by something else
-	 * already. -greg */
-	ohci_remove_td_from_ed(setup_td, control_ed);
-	ohci_remove_td_from_ed(data_td, control_ed);
-	ohci_remove_td_from_ed(status_td, control_ed);
-
-	/* remove the control ED */
+	/* clean up */
+	ohci_free_td(setup_td);
+	if (data_td != status_td)
+		ohci_free_td(data_td);
+	ohci_free_td(status_td);
+	/* remove the control ED from the HC */
X 	ohci_remove_control_ed(dev->ohci, control_ed);
+	ohci_free_ed(control_ed);	 /* return it to the pool */
X 
X #if 0
X 	printk(KERN_DEBUG "leaving ohci_control_msg\n");
X #endif
-
-	return ohci_td_result(dev, status_td);
+	return completion_status;
X } /* ohci_control_msg() */
X 
X 
@@ -675,6 +898,7 @@
X {
X 	struct usb_device *usb_dev;
X 	struct ohci_device *dev;
+	int idx;
X 
X 	/*
X 	 * Allocate the generic USB device
@@ -696,6 +920,12 @@
X 
X 	memset(dev, 0, sizeof(*dev));
X 
+	/* Initialize all EDs in a new device with the skip flag so that
+	 * they are ignored by the controller until set otherwise. */
+	for (idx = 0; idx < NUM_EDS; ++idx) {
+		dev->ed[idx].status |= OHCI_ED_SKIP;
+	}
+
X 	/*
X 	 * Link them together
X 	 */
@@ -752,10 +982,10 @@
X  */
X static int reset_hc(struct ohci *ohci)
X {
-	int timeout = 1000;  /* prevent an infinite loop */
+	int timeout = 10000;  /* prevent an infinite loop */
X 
X #if 0
-	printk(KERN_DEBUG "usb-ohci: resetting HC %p\n", ohci);
+	printk(KERN_INFO "usb-ohci: resetting HC %p\n", ohci);
X #endif
X 
X 	writel(~0x0, &ohci->regs->intrdisable);    /* Disable HC interrupts */
@@ -770,7 +1000,7 @@
X 		udelay(1);
X 	}
X 
-	printk(KERN_DEBUG "usb-ohci: HC %p reset.\n", ohci);
+	printk(KERN_INFO "usb-ohci: HC %p reset.\n", ohci);
X 
X 	return 0;
X } /* reset_hc() */
@@ -783,6 +1013,7 @@
X {
X 	int ret = 0;
X 	int fminterval;
+	__u32 what_to_enable;
X 
X 	fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
X #if 0
@@ -812,9 +1043,13 @@
X 	 * useful for debugging and as a bus heartbeat. -greg
X 	 */
X 	/* Choose the interrupts we care about */
-	writel( OHCI_INTR_MIE | /* OHCI_INTR_RHSC | */
-		OHCI_INTR_WDH | OHCI_INTR_FNO,
-		&ohci->regs->intrenable);
+	what_to_enable = OHCI_INTR_MIE |
+#ifdef OHCI_RHSC_INT
+			OHCI_INTR_RHSC |
+#endif
+			/* | OHCI_INTR_FNO */
+			OHCI_INTR_WDH;
+	writel( what_to_enable, &ohci->regs->intrenable);
X 
X 	/* Enter the USB Operational state & start the frames a flowing.. */
X 	writel_set(OHCI_USB_OPER, &ohci->regs->control);
@@ -861,7 +1096,7 @@
X 	/*
X 	 * Wait for the reset to complete.
X 	 */
-	wait_ms(10);
+	wait_ms(20);
X 
X 	/* check port status to see that the reset completed */
X 	status = readl(&ohci->regs->roothub.portstatus[port]);
@@ -886,10 +1121,12 @@
X 	struct usb_device *usb_dev;
X 	struct ohci_device *dev;
X 	/* memory I/O address of the port status register */
-	void *portaddr = &ohci->regs->roothub.portstatus[port];
+	__u32 *portaddr = &ohci->regs->roothub.portstatus[port];
X 	int portstatus;	
X 
-	printk(KERN_DEBUG "ohci_connect_change(%p, %d)\n", ohci, port);
+#ifdef OHCI_DEBUG
+	printk(KERN_DEBUG "ohci_connect_change on port %d\n", port);
+#endif
X 
X 	/*
X 	 * Because of the status change we have to forget
@@ -903,6 +1140,14 @@
X 	/* disable the port if nothing is connected */
X 	if (!(portstatus & PORT_CCS)) {
X 		writel(PORT_CCS, portaddr);
+		/* We need to reset the CSC bit -after- disabling the
+		 * port because it causes the CSC bit to come on
+		 * again... */
+		wait_ms(20);
+		writel(PORT_CSC, portaddr);
+#ifdef OHCI_DEBUG
+		printk(KERN_DEBUG "ohci port %d disabled, nothing connected.\n", port);
+#endif
X 		return;
X 	}
X 
@@ -943,15 +1188,18 @@
X 	struct ohci_regs *regs = ohci->regs;
X 	int num = 0;
X 	int maxport = readl(&ohci->regs->roothub) & 0xff;
+	__u32 rh_change_flags = PORT_CSC | PORT_PESC;	/* root hub status changes */
X 
-#if 1
+#ifdef OHCI_DEBUG
X 	printk(KERN_DEBUG "entering ohci_check_configuration %p\n", ohci);
X #endif
X 
X 	do {
-		if (readl(®s->roothub.portstatus[num]) & PORT_CSC) {
-			/* reset the connect status change bit */
-			writel(PORT_CSC, ®s->roothub.portstatus[num]);
+		__u32 *portstatus_p = ®s->roothub.portstatus[num];
+		if (readl(portstatus_p) & rh_change_flags) {
+			/* acknowledge the root hub status changes */
+			writel_set(rh_change_flags, portstatus_p);
+			/* disable the port if nothing is on it */
X 			/* check the port for a nifty device */
X 			ohci_connect_change(ohci, num);
X 		}
@@ -977,8 +1225,8 @@
X 		int maxport = ohci->root_hub->usb->maxchild;
X 
X 		do {
-			if (readl(&ohci->regs->roothub.portstatus[num]) &
-					PORT_CSC) {
+			__u32 *portstatus_p = &ohci->regs->roothub.portstatus[num];
+			if (readl(portstatus_p) & PORT_CSC) {
X 				if (waitqueue_active(&ohci_configure))
X 					wake_up(&ohci_configure);
X 				return;
@@ -1037,6 +1285,9 @@
X 	while (td != NULL) {
X 		struct ohci_td *next_td = td->next_dl_td;
X 
+		if (td_dummy(*td))
+			printk("yikes! reaping a dummy TD\n");
+
X 		/* FIXME: munge td->info into a future standard status format */
X 		/* Check if TD should be re-queued */
X 		if ((td->completed != NULL) &&
@@ -1044,14 +1295,15 @@
X 		{
X 			/* Mark the TD as active again:
X 			 * Set the not accessed condition code
-			 * FIXME: should this reset OHCI_TD_ERRCNT?
+			 * Reset the Error count
+			 * [FIXME: report errors to the device's driver]
X 			 */
X 			td->info |= OHCI_TD_CC_NEW;
+			clear_td_errorcount(td);
X 
X 			/* point it back to the start of the data buffer */
X 			td->cur_buf = virt_to_bus(td->data);
X 
-			/* XXX disabled for debugging reasons right now.. */
X 			/* insert it back on its ED */
X 			ohci_add_td_to_ed(td, td->ed);
X 		} else {
@@ -1066,9 +1318,6 @@
X } /* ohci_reap_donelist() */
X 
X 
-#if 0
-static int in_int = 0;
-#endif
X /*
X  * Get annoyed at the controller for bothering us.
X  * This pretty much follows the OHCI v1.0a spec, section 5.3.
@@ -1080,19 +1329,10 @@
X 	struct ohci_hcca *hcca = ohci->root_hub->hcca;
X 	__u32 status, context;
X 
-#if 0
-	/* for debugging to keep IRQs from running away. */
-	if (in_int >= 2)
-		return;
-	++in_int;
-	return;
-#endif
-
X 	/* Save the status of the interrupts that are enabled */
X 	status = readl(®s->intrstatus);
X 	status &= readl(®s->intrenable);
X 
-
X 	/* make context = the interrupt status bits that we care about */
X 	if (hcca->donehead != 0) {
X 		context = OHCI_INTR_WDH;   /* hcca donehead needs processing */
@@ -1122,6 +1362,10 @@
X 		context &= ~OHCI_INTR_WDH;  /* mark this as checked */
X 	}
X 
+#ifdef OHCI_RHSC_INT
+	/* NOTE: this is very funky on some USB controllers (ie: it
+	 * doesn't work right).  Using the ohci_timer instead to poll
+	 * the root hub is a much better choice. */
X 	/* Process any root hub status changes */
X 	if (context & OHCI_INTR_RHSC) {
X 		/* Wake the thread to process root hub events */
@@ -1134,10 +1378,17 @@
X 		 * The control thread will re-enable it after it has
X 		 * checked the root hub status.
X 		 */
-	} else {
-		/* check the root hub status anyways. Some controllers
-		 * might not generate the interrupt properly. (?) */
-		ohci_root_hub_events(ohci);
+	}
+#endif
+
+	/* Start of Frame interrupts, used during safe ED removal */
+	if (context & (OHCI_INTR_SF)) {
+		writel(OHCI_INTR_SF, ®s->intrstatus);
+		if (waitqueue_active(&start_of_frame_wakeup))
+			wake_up(&start_of_frame_wakeup);
+		/* Do NOT mark the frame start interrupt as checked
+		 * as we don't want to receive any more of them until
+		 * asked. */
X 	}
X 
X 	/* Check those "other" pesky bits */
@@ -1166,8 +1417,8 @@
X 		context &= ~OHCI_INTR_OC;  /* mark this as checked */
X 	}
X 
-	/* Mask out any remaining unprocessed interrupts so we don't
-	 * get any more of them. */
+	/* Mask out any remaining unprocessed or unmasked interrupts
+	 * so that we don't get any more of them. */
X 	if (context & ~OHCI_INTR_MIE) {
X 		writel(context, ®s->intrdisable);
X 	}
@@ -1275,7 +1526,9 @@
X 
X 	/*
X 	 * Initialize the polling table to call interrupts at the
-	 * intended intervals.
+	 * intended intervals.  Note that these EDs are just
+	 * placeholders.  They have their SKIP bit set and are used as
+	 * list heads to insert real EDs onto.
X 	 */
X 	dev->hcca->int_table[0] = virt_to_bus(&dev->ed[ED_INT_1]);
X 	for (i = 1; i < NUM_INTS; i++) {
@@ -1297,18 +1550,14 @@
X 	}
X 
X 	/*
-	 * Tell the controller where the control and bulk lists are
+	 * Tell the controller where the control and bulk lists are.
X 	 * The lists start out empty.
X 	 */
X 	writel(0, &ohci->regs->ed_controlhead);
X 	writel(0, &ohci->regs->ed_bulkhead);
-	/*
-	writel(virt_to_bus(&dev->ed[ED_CONTROL]), &ohci->regs->ed_controlhead);
-	writel(virt_to_bus(&dev->ed[ED_BULK]), &ohci->regs->ed_bulkhead);
-	*/
X 
-#if 0
-	printk(KERN_DEBUG "alloc_ohci(): controller\n");
+#ifdef OHCI_DEBUG
+	printk(KERN_INFO "alloc_ohci(): controller\n");
X 	show_ohci_status(ohci);
X #endif
X 
@@ -1325,7 +1574,7 @@
X  */
X static void release_ohci(struct ohci *ohci)
X {
-	printk(KERN_DEBUG "entering release_ohci %p\n", ohci);
+	printk(KERN_INFO "Releasing OHCI controller 0x%p\n", ohci);
X 
X #ifdef OHCI_TIMER
X 	/* stop our timer */
@@ -1378,7 +1627,7 @@
X 	 * This thread doesn't need any user-level access,
X 	 * so get rid of all of our resources..
X 	 */
-	printk("ohci_control_thread code at %p\n", &ohci_control_thread);
+	printk(KERN_INFO "ohci-control thread code for 0x%p code at 0x%p\n", __ohci, &ohci_control_thread);
X 	exit_mm(current);
X 	exit_files(current);
X 	exit_fs(current);
@@ -1391,7 +1640,7 @@
X 	if (start_hc(ohci) < 0) {
X 		printk("usb-ohci: failed to start the controller\n");
X 		release_ohci(ohci);
-		printk(KERN_DEBUG "leaving ohci_control_thread %p\n", __ohci);
+		printk(KERN_INFO "leaving ohci_control_thread %p\n", __ohci);
X 		return 0;
X 	}
X 
@@ -1405,11 +1654,11 @@
X 		ohci_check_configuration(ohci);
X 
X 		/* re-enable root hub status change interrupts. */
-#if 0
+#ifdef OHCI_RHSC_INT
X 		writel(OHCI_INTR_RHSC, &ohci->regs->intrenable);
X #endif
X 
-		printk(KERN_DEBUG "ohci-control thread sleeping\n");
+		printk(KERN_INFO "ohci-control thread sleeping\n");
X 		interruptible_sleep_on(&ohci_configure);
X #ifdef CONFIG_APM
X 		if (apm_resume) {
@@ -1431,9 +1680,14 @@
X 			spin_unlock_irq(¤t->sigmask_lock);
X 
X 			if(signr == SIGUSR1) {
-				/* FIXME: have it do a full ed/td queue dump */
+				/* TODO: have it do a full ed/td queue dump? */
X 				printk(KERN_DEBUG "OHCI status dump:\n");
X 				show_ohci_status(ohci);
+			} else if (signr == SIGUSR2) {
+				/* toggle mega TD/ED debugging output */
+				MegaDebug = !MegaDebug;
+				printk(KERN_DEBUG "usb-ohci: Mega debugging %sabled.\n",
+						MegaDebug ? "en" : "dis");
X 			} else {
X 				/* unknown signal, exit the thread */
X 				break;
@@ -1444,7 +1698,7 @@
X 	reset_hc(ohci);
X 	release_ohci(ohci);
X 
-	printk(KERN_DEBUG "leaving ohci_control_thread %p\n", __ohci);
+	printk(KERN_INFO "ohci-control thread for 0x%p exiting\n", __ohci);
X 
X 	return 0;
X } /* ohci_control_thread() */
@@ -1538,8 +1792,8 @@
X 
X 		ohci->irq = irq;
X 
-#if 0
-		printk(KERN_DEBUG "usb-ohci: starting ohci-control thread\n");
+#ifdef OHCI_DEBUG
+		printk(KERN_INFO "usb-ohci: forking ohci-control thread for 0x%p\n", ohci);
X #endif
X 
X 		/* fork off the handler */
@@ -1555,7 +1809,7 @@
X 	}
X 	release_ohci(ohci);
X 
-#if 0
+#ifdef OHCI_DEBUG
X 	printk(KERN_DEBUG "leaving found_ohci %d %p\n", irq, mem_base);
X #endif
X 
@@ -1597,6 +1851,11 @@
X 	}
X         MOD_INC_USE_COUNT;
X 
+#ifdef OHCI_DEBUG
+	printk("usb-ohci: Warning! Gobs of debugging output has been enabled.\n");
+	printk("          Check your kern.debug logs for the bulk of it.\n");
+#endif
+
X 	if (found_ohci(dev->irq, (void *) mem_base) < 0) {
X 		MOD_DEC_USE_COUNT;
X 		return -1;
@@ -1672,6 +1931,7 @@
X 	}
X 	return retval;
X } /* ohci_init */
+
X 
X /* vim:sw=8
X  */
diff -u --recursive --new-file v2.3.2/linux/drivers/usb/ohci.h linux/drivers/usb/ohci.h
--- v2.3.2/linux/drivers/usb/ohci.h	Sat May 15 23:46:04 1999
+++ linux/drivers/usb/ohci.h	Sun May 16 22:23:31 1999
@@ -6,7 +6,7 @@
X  *
X  * (C) Copyright 1999 Gregory P. Smith <gr...@electricrain.com>
X  *
- * $Id: ohci.h,v 1.15 1999/05/09 23:25:49 greg Exp $
+ * $Id: ohci.h,v 1.24 1999/05/16 10:18:26 greg Exp $
X  */
X 
X #include <linux/list.h>
@@ -37,7 +37,9 @@
X 	struct ohci_td *next_dl_td;	/* used during donelist processing */
X 	void *data;			/* virt. address of the the buffer */
X 	usb_device_irq completed;	/* Completion handler routine */
-	int allocated;			/* boolean: is this TD allocated? */
+	int hcd_flags;			/* Flags for the HCD: */
+		/* bit0 = boolean: Is this TD allocated? */
+		/* bit1 = boolean: Is this a dummy (end of list) TD? */
X 
X 	/* User or Device class driver specific fields */
X 	void *dev_id;	/* user defined pointer passed to irq handler */
@@ -59,6 +61,7 @@
X #define td_force_toggle(b)	(((b) | 2) << 24)
X #define OHCI_TD_ERRCNT	(3 << 26)	/* error count */
X #define td_errorcount(td)	(((td).info >> 26) & 3)
+#define clear_td_errorcount(td)	((td)->info &= ~(__u32)OHCI_TD_ERRCNT)
X #define OHCI_TD_CC	(0xf << 28)	/* condition code */
X #define OHCI_TD_CC_GET(td_i) (((td_i) >> 28) & 0xf)
X #define OHCI_TD_CC_NEW	(OHCI_TD_CC)	/* set this on all unaccessed TDs! */
@@ -68,9 +71,16 @@
X #define td_active(td)	(!td_cc_noerror((td)) && (td_errorcount((td)) < 3))
X #define td_done(td)	(td_cc_noerror((td)) || (td_errorcount((td)) == 3))
X 
-#define td_allocated(td)	((td).allocated)
-#define allocate_td(td)		((td)->allocated = 1)
-#define ohci_free_td(td)	((td)->allocated = 0)
+/*
+ * Macros to use the td->hcd_flags field.
+ */
+#define td_allocated(td)	((td).hcd_flags & 1)
+#define allocate_td(td)		((td)->hcd_flags |= 1)
+#define ohci_free_td(td)	((td)->hcd_flags &= ~(__u32)1)
+
+#define td_dummy(td)		((td).hcd_flags & 2)
+#define make_dumb_td(td)	((td)->hcd_flags |= 2)
+#define clear_dumb_td(td)	((td)->hcd_flags &= ~(__u32)2)
X 
X 
X /*
@@ -114,14 +124,14 @@
X #define OHCI_ED_FA	(0x7f)
X 
X 
-/* NOTE: bits 27-31 of the status dword are reserved for the driver */
+/* NOTE: bits 27-31 of the status dword are reserved for the HCD */
X /*
X  * We'll use this status flag for to mark if an ED is in use by the
- * driver or not.  If the bit is set, it is used.
- *
- * FIXME: implement this!
+ * driver or not.  If the bit is set, it is being used.
X  */
-#define ED_USED	(1 << 31)
+#define ED_ALLOCATED	(1 << 31)
+#define ed_allocated(ed)	((ed).status & ED_ALLOCATED)
+#define allocate_ed(ed)		((ed)->status |= ED_ALLOCATED)
X 
X /*
X  * The HCCA (Host Controller Communications Area) is a 256 byte
@@ -187,16 +197,17 @@
X 
X /* .... */
X 
+/*
+ * These are the index of the placeholder EDs for the root hub to
+ * build the interrupt transfer ED tree out of.
+ */
X #define ED_INT_1	0
X #define ED_INT_2	1
X #define ED_INT_4	2
X #define ED_INT_8	3
X #define ED_INT_16	4
X #define ED_INT_32	5
-#define ED_CONTROL	6
-#define ED_BULK		7
X #define ED_ISO		ED_INT_1	/* same as 1ms interrupt queue */
-#define ED_FIRST_AVAIL  8		/* first non-reserved ED */
X 
X /*
X  * Given a period p in ms, convert it to the closest endpoint
@@ -215,7 +226,9 @@
X  * This is the maximum number of root hub ports.  I don't think we'll
X  * ever see more than two as that's the space available on an ATX
X  * motherboard's case, but it could happen.  The OHCI spec allows for
- * up to 15... (which is insane!)
+ * up to 15... (which is insane given that they each need to supply up
+ * to 500ma; that would be 7.5 amps!).  I have seen a PCI card with 4
+ * downstream ports on it.
X  * 
X  * Although I suppose several "ports" could be connected directly to
X  * internal laptop devices such as a keyboard, mouse, camera and
@@ -259,6 +272,15 @@
X 	} roothub;
X } __attribute((aligned(32)));
X 
+/*
+ * These are used by internal ED managing functions as a
+ * parameter to state the type of ED to deal with (when it matters).
+ */
+#define HCD_ED_ISOC     (0)
+#define HCD_ED_INT      (1)
+#define HCD_ED_CONTROL  (2)
+#define HCD_ED_BULK     (3)
+
X /* 
X  * Read a MMIO register and re-write it after ANDing with (m)
X  */
@@ -352,9 +374,9 @@
X #define OHCI_TIMER		/* enable the OHCI timer */
X #define OHCI_TIMER_FREQ	(234)	/* ms between each root hub status check */
X 
-#undef OHCI_RHSC_INT		/* don't use root hub status interrupts */
+#undef OHCI_RHSC_INT		/* Don't use root hub status interrupts! */
X 
-/* Debugging code */
+/* Debugging code [ohci-debug.c] */
X void show_ohci_ed(struct ohci_ed *ed);
X void show_ohci_td(struct ohci_td *td);
X void show_ohci_status(struct ohci *ohci);
diff -u --recursive --new-file v2.3.2/linux/fs/ChangeLog linux/fs/ChangeLog
--- v2.3.2/linux/fs/ChangeLog	Fri Dec 18 07:09:35 1998
+++ linux/fs/ChangeLog	Sat May 15 23:43:05 1999
@@ -144,24 +144,12 @@
X 	* rmdir of immutable/append-only directory shouldn't be allowed. Fixed.
X 
X Remains unfixed:
-	* UMSDOS_rename is broken. Call it with the dest. existing and being an
-		empty directory and you've got EBUSY. At least it doesn't do
-		any harm, so that will wait several days till rename cleanup.
-		Sigh... It will wait a bit more. Problems with fat-derived
-		filesystems are much worse than I thought. Idea of changing
-		inode under dentry is broken by design - guess where the
-		semaphore sits, for one.
-	* umsdos: weird. rename() shouldn't return -EEXIST. BTW, manpage
-		for rename(2) is obviously bogus - it mentions EEXIST and
-		on the next line (correctly) says that EINVAL should be
-		returned. Under the same conditions.
X 	* rename's handling of races is, erm, not optimal. Looks like I know
X 		what to do, but this thing needs some more cleanup - we can
X 		take care of almost all races in VFS and be much more graceful
X 		wrt locking. Moreover, it would give strong lookup atomicity.
X 		But it's a lot of changes to lookup and dcache code, so it will
X 		go after the fs drivers' cleanup.
-	* hfs allows mknod. Only for regular files ;-/ IMHO it's bogus.
X 	* affs allows HARD links to directories. VFS is, to put it politely,
X 		not too ready to cope with _that_. And I'm not sure it should
X 		be - looks like they are pretty much similar to symlinks.
@@ -169,8 +157,3 @@
X 		braindead filesystems). I've submitted a patch to Linus, but
X 		looks like it wasn't applied.
X 	* msdos: shouldn't we treat SYS as IMMUTABLE? Makes sense, IMHO.
-	* minix, qnx and sysv do NOT allow to mkdir sticky directories.
-	* {minix,sysv}/namei.c (do_{minix,syv}_{rename,unlink}):
-		Stuff related to retries still needs cleanup/fixing.
-		Looks like I've found an extremely low-probability race
-		there...
diff -u --recursive --new-file v2.3.2/linux/fs/Config.in linux/fs/Config.in
--- v2.3.2/linux/fs/Config.in	Sat May 15 23:46:04 1999
+++ linux/fs/Config.in	Sun May 16 10:27:40 1999
@@ -36,7 +36,7 @@
X if [ "$CONFIG_NTFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
X   bool '   NTFS read-write support (DANGEROUS)' CONFIG_NTFS_RW
X fi
-tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
+tristate 'OS/2 HPFS filesystem support (read/write) (NEW)' CONFIG_HPFS_FS
X bool '/proc filesystem support' CONFIG_PROC_FS
X if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
X   # It compiles as a module for testing only.  It should not be used
diff -u --recursive --new-file v2.3.2/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.3.2/linux/fs/affs/namei.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/affs/namei.c	Sat May 15 23:43:05 1999
@@ -315,7 +315,7 @@
X 	error       = affs_add_entry(dir,NULL,inode,dentry,ST_USERDIR);
X 	if (error)
X 		goto out_iput;
-	inode->i_mode = S_IFDIR | S_ISVTX | (mode & 0777 & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | S_ISVTX | mode;
X 	inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode);
X 	d_instantiate(dentry,inode);
X 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.2/linux/fs/devices.c linux/fs/devices.c
--- v2.3.2/linux/fs/devices.c	Fri May 14 18:55:24 1999
+++ linux/fs/devices.c	Sat May 15 23:43:04 1999
@@ -193,7 +193,7 @@
X  * it. Thus it is called only upon a 'mount' or 'open'. This
X  * is the best way of combining speed and utility, I think.
X  * People changing diskettes in the middle of an operation deserve
- * to loose :-)
+ * to lose :-)
X  */
X int check_disk_change(kdev_t dev)
X {
diff -u --recursive --new-file v2.3.2/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.2/linux/fs/ext2/namei.c	Fri May 14 18:55:24 1999
+++ linux/fs/ext2/namei.c	Sat May 15 23:43:05 1999
@@ -490,7 +490,7 @@
X 	inode->i_nlink = 2;
X 	mark_buffer_dirty(dir_block, 1);
X 	brelse (dir_block);
-	inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | mode;
X 	if (dir->i_mode & S_ISGID)
X 		inode->i_mode |= S_ISGID;
X 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.2/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c
--- v2.3.2/linux/fs/ext2/truncate.c	Sat May 15 23:46:04 1999
+++ linux/fs/ext2/truncate.c	Sun May 16 13:55:46 1999
@@ -384,7 +384,7 @@
X 		
X void ext2_truncate (struct inode * inode)
X {
-	int err, offset, retry;
+	int err, offset;
X 
X 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
X 	    S_ISLNK(inode->i_mode)))
@@ -393,7 +393,7 @@
X 		return;
X 	ext2_discard_prealloc(inode);
X 	while (1) {
-		retry = trunc_direct(inode);
+		int retry = trunc_direct(inode);
X 		retry |= trunc_indirect (inode, 
X 				EXT2_IND_BLOCK,
X 				(u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK],
diff -u --recursive --new-file v2.3.2/linux/fs/hfs/bnode.c linux/fs/hfs/bnode.c
--- v2.3.2/linux/fs/hfs/bnode.c	Fri May 14 18:55:24 1999
+++ linux/fs/hfs/bnode.c	Sat May 15 15:02:50 1999
@@ -228,7 +228,7 @@
X 			break;
X 
X 		case HFS_LOCK_NONE:
-			while (bn->lock || witqueue_active(&bn->wqueue)) {
+			while (bn->lock || waitqueue_active(&bn->wqueue)) {
X 				hfs_sleep_on(&bn->rqueue);
X 			}
X 			++bn->count;
diff -u --recursive --new-file v2.3.2/linux/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- v2.3.2/linux/fs/hfs/catalog.c	Fri May 14 18:55:24 1999
+++ linux/fs/hfs/catalog.c	Sat May 15 15:02:50 1999
@@ -647,7 +647,7 @@
X  */
X static inline void start_write(struct hfs_cat_entry *dir)
X {
-	if (dir->u.dir.readers || wait_queue_active(&dir->u.dir.read_wait)) {
+	if (dir->u.dir.readers || waitqueue_active(&dir->u.dir.read_wait)) {
X 		hfs_sleep_on(&dir->u.dir.write_wait);
X 	}
X 	++dir->u.dir.writers;
@@ -658,7 +658,7 @@
X  */
X static inline void start_read(struct hfs_cat_entry *dir)
X {
-	if (dir->u.dir.writers || wait_queue_active(&dir->u.dir.write_wait)) {
+	if (dir->u.dir.writers || waitqueue_active(&dir->u.dir.write_wait)) {
X 		hfs_sleep_on(&dir->u.dir.read_wait);
X 	}
X 	++dir->u.dir.readers;
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/alloc.c linux/fs/hpfs/alloc.c
--- v2.3.2/linux/fs/hpfs/alloc.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/alloc.c	Sun May 16 10:27:40 1999
@@ -307,6 +307,7 @@
X 	if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
X 		for (j = 0; j < 512; j++) {
X 			unsigned k;
+			if (!bmp[j]) continue;
X 			for (k = bmp[j]; k; k >>= 1) if (k & 1) if (!--n) {
X 				hpfs_brelse4(&qbh);
X 				return 0;
@@ -327,9 +328,9 @@
X 	if (bmp) {
X 		for (j = 0; j < 512; j++) {
X 			unsigned k;
+			if (!bmp[j]) continue;
X 			for (k = 0xf; k; k <<= 4)
X 				if ((bmp[j] & k) == k) {
-					/*printk("%08x,%08x\n",j,i);*/
X 					if (!--n) {
X 						hpfs_brelse4(&qbh);
X 						return 0;
@@ -372,8 +373,13 @@
X 			 int lock)
X {
X 	struct dnode *d;
-	if (!(*dno = alloc_in_dirband(s, near, lock)))
-		if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL;
+	if (hpfs_count_one_bitmap(s, s->s_hpfs_dmap) > FREE_DNODES_ADD) {
+		if (!(*dno = alloc_in_dirband(s, near, lock)))
+			if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL;
+	} else {
+		if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock)))
+			if (!(*dno = alloc_in_dirband(s, near, lock))) return NULL;
+	}
X 	if (!(d = hpfs_get_4sectors(s, *dno, qbh))) {
X 		hpfs_free_dnode(s, *dno);
X 		return NULL;
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/dentry.c linux/fs/hpfs/dentry.c
--- v2.3.2/linux/fs/hpfs/dentry.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/dentry.c	Sun May 16 10:27:40 1999
@@ -16,14 +16,14 @@
X {
X 	unsigned long	 hash;
X 	int		 i;
-	int l = qstr->len;
+	unsigned l = qstr->len;
X 
X 	if (l == 1) if (qstr->name[0]=='.') goto x;
X 	if (l == 2) if (qstr->name[0]=='.' || qstr->name[1]=='.') goto x;
-	if (hpfs_chk_name((char *)qstr->name,l))
-		/*return -ENAMETOOLONG;*/
-		return -ENOENT;
X 	hpfs_adjust_length((char *)qstr->name, &l);
+	/*if (hpfs_chk_name((char *)qstr->name,&l))*/
+		/*return -ENAMETOOLONG;*/
+		/*return -ENOENT;*/
X 	x:
X 
X 	hash = init_name_hash();
@@ -36,15 +36,15 @@
X 
X int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
X {
-	int al=a->len;
-	int bl=b->len;
+	unsigned al=a->len;
+	unsigned bl=b->len;
X 	hpfs_adjust_length((char *)a->name, &al);
-	hpfs_adjust_length((char *)b->name, &bl);
+	/*hpfs_adjust_length((char *)b->name, &bl);*/
X 	/* 'a' is the qstr of an already existing dentry, so the name
X 	 * must be valid. 'b' must be validated first.
X 	 */
X 
-	if (hpfs_chk_name((char *)b->name, bl)) return 1;
+	if (hpfs_chk_name((char *)b->name, &bl)) return 1;
X 	if (hpfs_compare_names(dentry->d_sb, (char *)a->name, al, (char *)b->name, bl, 0)) return 1;
X 	return 0;
X }
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/dir.c linux/fs/hpfs/dir.c
--- v2.3.2/linux/fs/hpfs/dir.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/dir.c	Sun May 16 10:27:40 1999
@@ -30,8 +30,6 @@
X 	char *tempname;
X 	int c1, c2 = 0;
X 
-	if (!inode) return -EBADF;
-	if (!S_ISDIR(inode->i_mode)) return -EBADF;
X 	if (inode->i_sb->s_hpfs_chk) {
X 		if (hpfs_chk_sectors(inode->i_sb, inode->i_ino, 1, "dir_fnode"))
X 			return -EFSERROR;
@@ -150,57 +148,30 @@
X struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct quad_buffer_head qbh;
X 	struct hpfs_dirent *de;
-	struct inode *inode;
X 	ino_t ino;
-
+	int err;
X 	struct inode *result = NULL;
-	if (dir == 0) return -ENOENT;
-	hpfs_adjust_length((char *)name, &len);
+
+	if ((err = hpfs_chk_name((char *)name, &len))) {
+		if (err == -ENAMETOOLONG) return ERR_PTR(-ENAMETOOLONG);
+		goto end_add;
+	}
+
X 	hpfs_lock_inode(dir);
-	if (!S_ISDIR(dir->i_mode)) goto bail;
X 	/*
-	 * Read in the directory entry. "." is there under the name ^A^A .
-	 * Always read the dir even for . and .. in case we need the dates.
-	 *
-	 * M.P.: No - we can't read '^A^A' for current directory. In some cases
-	 * the information under '^A^A' is incomplete (missing ea_size, bad
-	 * fnode number) - chkdsk ignores such errors and it doesn't seem to
-	 * matter under OS/2.
-	 */
-	if (name[0] == '.' && len == 1) {
-		result = dir;
-		dir->i_count++;
-		goto end;
-	} else if (name[0] == '.' && name[1] == '.' && len == 2) {
-		struct buffer_head *bh;
-		struct fnode *fnode;
-		if (dir->i_ino == dir->i_sb->s_hpfs_root) {
-			result = dir;
-			dir->i_count++;
-			goto end;
-		}
-		if (dir->i_hpfs_parent_dir == dir->i_sb->s_hpfs_root) {
-			result = dir->i_sb->s_root->d_inode;
-			result->i_count++;
-			goto end;
-		}
-		if (!(fnode = hpfs_map_fnode(dir->i_sb, dir->i_hpfs_parent_dir, &bh))) goto bail;
-		de = map_fnode_dirent(dir->i_sb, dir->i_hpfs_parent_dir, fnode, &qbh);
-		brelse(bh);
-	} else
-		de = map_dirent(dir, dir->i_hpfs_dno, (char *) name, len, NULL, &qbh, NULL);
+	 * '.' and '..' will never be passed here.
+	 */
+
+	de = map_dirent(dir, dir->i_hpfs_dno, (char *) name, len, NULL, &qbh);
X 
X 	/*
X 	 * This is not really a bailout, just means file not found.
X 	 */
X 
-	if (!de) {
-		result = NULL;
-		goto end;
-	}
+	if (!de) goto end;
X 
X 	/*
X 	 * Get inode number, what we're after.
@@ -213,18 +184,18 @@
X 	 */
X 
X 	hpfs_lock_iget(dir->i_sb, de->directory || (de->ea_size && dir->i_sb->s_hpfs_eas) ? 1 : 2);
-	if (!(inode = iget(dir->i_sb, ino))) {
+	if (!(result = iget(dir->i_sb, ino))) {
X 		hpfs_unlock_iget(dir->i_sb);
-		hpfs_error(inode->i_sb, "hpfs_lookup: can't get inode");
+		hpfs_error(result->i_sb, "hpfs_lookup: can't get inode");
X 		goto bail1;
X 	}
-	if (!de->directory) inode->i_hpfs_parent_dir = dir->i_ino;
+	if (!de->directory) result->i_hpfs_parent_dir = dir->i_ino;
X 	hpfs_unlock_iget(dir->i_sb);
X 
-	hpfs_decide_conv(inode, (char *)name, len);
+	hpfs_decide_conv(result, (char *)name, len);
X 
X 	if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
-		hpfs_error(inode->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
+		hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
X 		goto bail1;
X 	}
X 
@@ -233,24 +204,24 @@
X 	 * inode.
X 	 */
X 
-	if (!inode->i_ctime) {
-		if (!(inode->i_ctime = local_to_gmt(dir->i_sb, de->creation_date)))
-			inode->i_ctime = 1;
-		inode->i_mtime = local_to_gmt(dir->i_sb, de->write_date);
-		inode->i_atime = local_to_gmt(dir->i_sb, de->read_date);
-		inode->i_hpfs_ea_size = de->ea_size;
-		if (!inode->i_hpfs_ea_mode && de->read_only)
-			inode->i_mode &= ~0222;
+	if (!result->i_ctime) {
+		if (!(result->i_ctime = local_to_gmt(dir->i_sb, de->creation_date)))
+			result->i_ctime = 1;
+		result->i_mtime = local_to_gmt(dir->i_sb, de->write_date);
+		result->i_atime = local_to_gmt(dir->i_sb, de->read_date);
+		result->i_hpfs_ea_size = de->ea_size;
+		if (!result->i_hpfs_ea_mode && de->read_only)
+			result->i_mode &= ~0222;
X 		if (!de->directory) {
-			if (inode->i_size == -1) {
-				inode->i_size = de->file_size;
+			if (result->i_size == -1) {
+				result->i_size = de->file_size;
X 			/*
X 			 * i_blocks should count the fnode and any anodes.
X 			 * We count 1 for the fnode and don't bother about
X 			 * anodes -- the disk heads are on the directory band
X 			 * and we want them to stay there.
X 			 */
-				inode->i_blocks = 1 + ((inode->i_size + 511) >> 9);
+				result->i_blocks = 1 + ((result->i_size + 511) >> 9);
X 			}
X 		}
X 	}
@@ -261,9 +232,9 @@
X 	 * Made it.
X 	 */
X 
-	result = inode;
X 	end:
X 	hpfs_unlock_inode(dir);
+	end_add:
X 	hpfs_set_dentry_operations(dentry);
X 	d_add(dentry, result);
X 	return NULL;
@@ -275,7 +246,7 @@
X 	
X 	hpfs_brelse4(&qbh);
X 	
-	bail:
+	/*bail:*/
X 
X 	hpfs_unlock_inode(dir);
X 	return ERR_PTR(-ENOENT);
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/dnode.c linux/fs/hpfs/dnode.c
--- v2.3.2/linux/fs/hpfs/dnode.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/dnode.c	Sun May 16 10:27:40 1999
@@ -368,7 +368,6 @@
X 	struct quad_buffer_head qbh;
X 	dnode_secno dno;
X 	int c;
-	int depth = cdepth;
X 	int c1, c2 = 0;
X 	dno = i->i_hpfs_dno;
X 	down:
@@ -385,7 +384,6 @@
X 			if (de->down) {
X 				dno = de_down_pointer(de);
X 				hpfs_brelse4(&qbh);
-				depth++;
X 				goto down;
X 			}
X 			break;
@@ -393,7 +391,7 @@
X 	}
X 	hpfs_brelse4(&qbh);
X 	if (!cdepth) hpfs_lock_creation(i->i_sb);
-	if (hpfs_check_free_dnodes(i->i_sb, depth + 2)) {
+	if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) {
X 		c = 1;
X 		goto ret;
X 	}	
@@ -574,11 +572,6 @@
X 		goto end;
X 	}
X 
-	/*{
-		static int cnt_t_ = 0;
-		if (cnt_t_++ & 1) goto endm;
-	}*/
-
X 	if (!de->last) {
X 		struct hpfs_dirent *de_next = de_next_de(de);
X 		struct hpfs_dirent *de_cp;
@@ -607,7 +600,6 @@
X 		kfree(de_cp);
X 		goto try_it_again;
X 	} else {
-		/*printk("HPFS: warning: not balancing tree\n");*/
X 		struct hpfs_dirent *de_prev = dnode_pre_last_de(dnode);
X 		struct hpfs_dirent *de_cp;
X 		struct dnode *d1;
@@ -692,20 +684,21 @@
X {
X 	struct dnode *dnode = qbh->data;
X 	dnode_secno down = 0;
+	int lock = 0;
X 	loff_t t;
X 	if (de->first || de->last) {
X 		hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno);
X 		hpfs_brelse4(qbh);
X 		return 1;
X 	}
-	if (de->down) {
-		if ((down = de_down_pointer(de)) && depth) {
-			hpfs_lock_creation(i->i_sb);
-			if (hpfs_check_free_dnodes(i->i_sb, depth + 2)) {
-				hpfs_brelse4(qbh);
-				hpfs_unlock_creation(i->i_sb);
-				return 2;
-			}
+	if (de->down) down = de_down_pointer(de);
+	if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) {
+		lock = 1;
+		hpfs_lock_creation(i->i_sb);
+		if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) {
+			hpfs_brelse4(qbh);
+			hpfs_unlock_creation(i->i_sb);
+			return 2;
X 		}
X 	}
X 	i->i_version = ++event;
@@ -716,10 +709,12 @@
X 	if (down) {
X 		dnode_secno a = move_to_top(i, down, dno);
X 		for_all_poss(i, hpfs_pos_subst, 5, t);
-		if (depth) hpfs_unlock_creation(i->i_sb);
X 		if (a) delete_empty_dnode(i, a);
+		if (lock) hpfs_unlock_creation(i->i_sb);
X 		return !a;
-	} else delete_empty_dnode(i, dno);
+	}
+	delete_empty_dnode(i, dno);
+	if (lock) hpfs_unlock_creation(i->i_sb);
X 	return 0;
X }
X 
@@ -888,15 +883,13 @@
X /* Find a dirent in tree */
X 
X struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno, char *name, unsigned len,
-			       dnode_secno *dd, struct quad_buffer_head *qbh, int *depth)
+			       dnode_secno *dd, struct quad_buffer_head *qbh)
X {
X 	struct dnode *dnode;
X 	struct hpfs_dirent *de;
X 	struct hpfs_dirent *de_end;
X 	int c1, c2 = 0;
X 
-	if (depth) *depth = 0;
-
X 	if (!S_ISDIR(inode->i_mode)) hpfs_error(inode->i_sb, "map_dirent: not a directory\n");
X 	again:
X 	if (inode->i_sb->s_hpfs_chk)
@@ -914,7 +907,6 @@
X 			if (de->down) {
X 				dno = de_down_pointer(de);
X 				hpfs_brelse4(qbh);
-				if (depth) (*depth)++;
X 				goto again;
X 			}
X 		break;
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/file.c linux/fs/hpfs/file.c
--- v2.3.2/linux/fs/hpfs/file.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/file.c	Sun May 16 10:27:40 1999
@@ -54,7 +54,6 @@
X 	i->i_hpfs_n_secs = 0;
X 	hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
X 	i->i_blocks = 1 + ((i->i_size + 511) >> 9);
-	/*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
X 	hpfs_write_inode(i);
X }
X 
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h
--- v2.3.2/linux/fs/hpfs/hpfs_fn.h	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/hpfs_fn.h	Sun May 16 10:27:40 1999
@@ -42,6 +42,9 @@
X #define ANODE_RD_AHEAD	16
X #define DNODE_RD_AHEAD	4
X 
+#define FREE_DNODES_ADD	58
+#define FREE_DNODES_DEL	29
+
X #define CHKCOND(x,y) if (!(x)) printk y
X 
X #ifdef DBG
@@ -237,7 +240,7 @@
X void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
X dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
X struct hpfs_dirent *map_pos_dirent(struct inode *, loff_t *, struct quad_buffer_head *);
-struct hpfs_dirent *map_dirent(struct inode *, dnode_secno, char *, unsigned, dnode_secno *, struct quad_buffer_head *, int *depth);
+struct hpfs_dirent *map_dirent(struct inode *, dnode_secno, char *, unsigned, dnode_secno *, struct quad_buffer_head *);
X void hpfs_remove_dtree(struct super_block *, dnode_secno);
X struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct fnode *, struct quad_buffer_head *);
X 
@@ -285,7 +288,7 @@
X /* name.c */
X 
X unsigned char hpfs_upcase(unsigned char *, unsigned char);
-int hpfs_chk_name(unsigned char *, unsigned);
+int hpfs_chk_name(unsigned char *, unsigned *);
X char *hpfs_translate_name(struct super_block *, unsigned char *, unsigned, int, int);
X int hpfs_compare_names(struct super_block *, unsigned char *, unsigned, unsigned char *, unsigned, int);
X int hpfs_is_name_long(unsigned char *, unsigned);
@@ -310,5 +313,6 @@
X int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
X int hpfs_remount_fs(struct super_block *, int *, char *);
X void hpfs_put_super(struct super_block *);
+unsigned hpfs_count_one_bitmap(struct super_block *, secno);
X int hpfs_statfs(struct super_block *, struct statfs *, int);
X struct super_block *hpfs_read_super(struct super_block *, void *, int);
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/inode.c linux/fs/hpfs/inode.c
--- v2.3.2/linux/fs/hpfs/inode.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/inode.c	Sun May 16 10:27:40 1999
@@ -128,6 +128,7 @@
X 	unsigned char *ea;
X 	int ea_size;
X 	i->i_op = 0;
+	/*i->i_hpfs_sem = MUTEX;*/
X 	init_MUTEX(&i->i_hpfs_sem);
X 	i->i_uid = sb->s_hpfs_uid;
X 	i->i_gid = sb->s_hpfs_gid;
@@ -199,27 +200,27 @@
X 			return;
X 		}
X 		if ((ea = hpfs_get_ea(i->i_sb, fnode, "MODE", &ea_size))) {
+			int rdev = 0;
+			umode_t mode = sb->s_hpfs_mode;
X 			if (ea_size == 2) {
-				i->i_mode = ea[0] + (ea[1] << 8);
+				mode = ea[0] + (ea[1] << 8);
X 				i->i_hpfs_ea_mode = 1;
X 			}
X 			kfree(ea);
-			if (S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode)) {
+			i->i_mode = mode;
+			if (S_ISBLK(mode) || S_ISCHR(mode)) {
X 				if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) {
X 					if (ea_size == 4)
-						i->i_rdev = to_kdev_t(ea[0] + (ea[1] << 8) + (ea[2] << 16) + (ea[3] << 24));
+						rdev = ea[0] + (ea[1] << 8) + (ea[2] << 16) + (ea[3] << 24);
X 					kfree(ea);
X 				}
X 			}
-			if (S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode) || S_ISFIFO(i->i_mode) || S_ISSOCK(i->i_mode)) {
+			if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
X 				brelse(bh);
X 				i->i_nlink = 1;
X 				i->i_size = 0;
X 				i->i_blocks = 1;
-				i->i_op = NULL;
-				if (S_ISBLK(i->i_mode)) i->i_op = (struct inode_operations *) &blkdev_inode_operations;
-				if (S_ISCHR(i->i_mode)) i->i_op = (struct inode_operations *) &chrdev_inode_operations;
-				if (S_ISFIFO(i->i_mode)) init_fifo(i);
+				init_special_inode(i, mode, rdev);
X 				return;
X 			}
X 		}
@@ -341,7 +342,7 @@
X 		hpfs_brelse4(&qbh);
X 	}
X 	if (S_ISDIR(i->i_mode)) {
-		if ((de = map_dirent(i, i->i_hpfs_dno, "\001\001", 2, NULL, &qbh, NULL))) {
+		if ((de = map_dirent(i, i->i_hpfs_dno, "\001\001", 2, NULL, &qbh))) {
X 			de->write_date = gmt_to_local(i->i_sb, i->i_mtime);
X 			de->read_date = gmt_to_local(i->i_sb, i->i_atime);
X 			de->creation_date = gmt_to_local(i->i_sb, i->i_ctime);
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/name.c linux/fs/hpfs/name.c
--- v2.3.2/linux/fs/hpfs/name.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/name.c	Sun May 16 10:27:40 1999
@@ -70,13 +70,15 @@
X 	return dir[a];
X }
X 
-int hpfs_chk_name(unsigned char *name, unsigned len)
+int hpfs_chk_name(unsigned char *name, unsigned *len)
X {
X 	int i;
-	if (!len || len > 254) return 1;
-	for (i = 0; i < len; i++) if (not_allowed_char(name[i])) return 1;
-	if (len == 1) if (name[0] == '.') return 1;
-	if (len == 2) if (name[0] == '.' && name[1] == '.') return 1;
+	if (*len > 254) return -ENAMETOOLONG;
+	hpfs_adjust_length(name, len);
+	if (!*len) return -EINVAL;
+	for (i = 0; i < *len; i++) if (not_allowed_char(name[i])) return -EINVAL;
+	if (*len == 1) if (name[0] == '.') return -EINVAL;
+	if (*len == 2) if (name[0] == '.' && name[1] == '.') return -EINVAL;
X 	return 0;
X }
X 
@@ -101,7 +103,7 @@
X }
X 
X int hpfs_compare_names(struct super_block *s, unsigned char *n1, unsigned l1,
-		  unsigned char *n2, unsigned l2, int last)
+		       unsigned char *n2, unsigned l2, int last)
X {
X 	unsigned l = l1 < l2 ? l1 : l2;
X 	unsigned i;
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/namei.c linux/fs/hpfs/namei.c
--- v2.3.2/linux/fs/hpfs/namei.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/namei.c	Sun May 16 10:27:40 1999
@@ -11,7 +11,7 @@
X int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct quad_buffer_head qbh0;
X 	struct buffer_head *bh;
X 	struct hpfs_dirent *de;
@@ -22,14 +22,8 @@
X 	dnode_secno dno;
X 	int r;
X 	struct hpfs_dirent dee;
-	if (!dir) return -ENOENT;
-	if (!S_ISDIR(dir->i_mode)) {
-		return -ENOTDIR;
-	}
-	hpfs_adjust_length((char *)name, &len);
-	if (hpfs_chk_name((char *)name, len)) {
-		return -ENAMETOOLONG;
-	}	
+	int err;
+	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
X 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
X 	if (!(dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1))) goto bail1;
X 	memset(&dee, 0, sizeof dee);
@@ -105,25 +99,15 @@
X int hpfs_create(struct inode *dir, struct dentry *dentry, int mode)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
-	struct inode *result;
+	unsigned len = dentry->d_name.len;
+	struct inode *result = NULL;
X 	struct buffer_head *bh;
X 	struct fnode *fnode;
X 	fnode_secno fno;
X 	int r;
X 	struct hpfs_dirent dee;
-	result = NULL;
-	if (!dir) return -ENOENT;
-	if (!S_ISDIR(dir->i_mode)) {
-		return -ENOTDIR;
-	}
-	if (!S_ISREG(mode)) {
-		return -EINVAL;
-	}
-	hpfs_adjust_length((char *)name, &len);
-	if (hpfs_chk_name((char *)name, len)) {
-		return -ENAMETOOLONG;
-	}	
+	int err;
+	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
X 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
X 	memset(&dee, 0, sizeof dee);
X 	if (!(mode & 0222)) dee.read_only = 1;
@@ -178,28 +162,16 @@
X int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct buffer_head *bh;
X 	struct fnode *fnode;
X 	fnode_secno fno;
X 	int r;
X 	struct hpfs_dirent dee;
X 	struct inode *result = NULL;
-	if (!dir) return -ENOENT;
-	if (dir->i_sb->s_hpfs_eas < 2) {
-		/*iput(dir);*/
-		return -EPERM;
-	}
-	if (!S_ISDIR(dir->i_mode)) {
-		return -ENOTDIR;
-	}
-	if (!S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) && !S_ISSOCK(mode)) {
-		return -EINVAL;
-	}
-	hpfs_adjust_length((char *)name, &len);
-	if (hpfs_chk_name((char *)name, len)) {
-		return -ENAMETOOLONG;
-	}	
+	int err;
+	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+	if (dir->i_sb->s_hpfs_eas < 2) return -EPERM;
X 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
X 	memset(&dee, 0, sizeof dee);
X 	if (!(mode & 0222)) dee.read_only = 1;
@@ -227,17 +199,12 @@
X 		result->i_hpfs_ea_size = 0;
X 		/*if (result->i_blocks == -1) result->i_blocks = 1;
X 		if (result->i_size == -1) result->i_size = 0;*/
-		result->i_mode = mode;
X 		result->i_uid = current->fsuid;
X 		result->i_gid = current->fsgid;
-		if (!S_ISFIFO(mode)) result->i_rdev = to_kdev_t(rdev);
X 		result->i_nlink = 1;
X 		result->i_size = 0;
X 		result->i_blocks = 1;
-		result->i_op = NULL;
-		if (S_ISBLK(result->i_mode)) result->i_op = (struct inode_operations *) &blkdev_inode_operations;
-		if (S_ISCHR(result->i_mode)) result->i_op = (struct inode_operations *) &chrdev_inode_operations;
-		if (S_ISFIFO(result->i_mode)) init_fifo(result);
+		init_special_inode(result, mode, rdev);
X 		hpfs_write_inode_nolock(result);
X 		d_instantiate(dentry, result);
X 	}
@@ -258,24 +225,16 @@
X int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct buffer_head *bh;
X 	struct fnode *fnode;
X 	fnode_secno fno;
X 	int r;
X 	struct hpfs_dirent dee;
X 	struct inode *result;
-	if (!dir) return -ENOENT;
-	if (dir->i_sb->s_hpfs_eas < 2) {
-		return -EPERM;
-	}
-	if (!S_ISDIR(dir->i_mode)) {
-		return -ENOTDIR;
-	}
-	hpfs_adjust_length((char *)name, &len);
-	if (hpfs_chk_name((char *)name, len)) {
-		return -ENAMETOOLONG;
-	}
+	int err;
+	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+	if (dir->i_sb->s_hpfs_eas < 2) return -EPERM;
X 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
X 	memset(&dee, 0, sizeof dee);
X 	dee.archive = 1;
@@ -331,16 +290,18 @@
X int hpfs_unlink(struct inode *dir, struct dentry *dentry)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct quad_buffer_head qbh;
X 	struct hpfs_dirent *de;
X 	struct inode *inode = dentry->d_inode;
X 	dnode_secno dno;
X 	fnode_secno fno;
-	int depth, r;
+	int r;
+	int rep = 0;
X 	hpfs_adjust_length((char *)name, &len);
+	again:
X 	hpfs_lock_2inodes(dir, inode);
-	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh, &depth))) {
+	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh))) {
X 		hpfs_unlock_2inodes(dir, inode);
X 		return -ENOENT;
X 	}
@@ -355,29 +316,49 @@
X 		return -EISDIR;
X 	}
X 	fno = de->fnode;
-	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, depth)) == 1) hpfs_error(dir->i_sb, "there was error when removing dirent");
+	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1) hpfs_error(dir->i_sb, "there was error when removing dirent");
X 	if (r != 2) {
X 		inode->i_nlink--;
X 		hpfs_unlock_2inodes(dir, inode);
X 		d_delete(dentry);
-	} else hpfs_unlock_2inodes(dir, inode);
+	} else {	/* no space for deleting, try to truncate file */
+		struct iattr newattrs;
+		hpfs_unlock_2inodes(dir, inode);
+		if (rep || dentry->d_count > 1 || permission(inode, MAY_WRITE) || get_write_access(inode)) goto ret;
+		/*printk("HPFS: truncating file before delete.\n");*/
+		down(&inode->i_sem);	/* do_truncate should be called here, but it's */
+		newattrs.ia_size = 0;	/* not exported */
+		newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+		if (notify_change(dentry, &newattrs)) {
+			up(&inode->i_sem);
+			put_write_access(inode);
+			goto ret;
+		}
+		vmtruncate(inode, 0);
+		if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode);
+		up(&inode->i_sem);
+		put_write_access(inode);
+		rep = 1;
+		goto again;
+	}
+	ret:
X 	return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
X }
X 
X int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
X {
X 	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
+	unsigned len = dentry->d_name.len;
X 	struct quad_buffer_head qbh;
X 	struct hpfs_dirent *de;
X 	struct inode *inode = dentry->d_inode;
X 	dnode_secno dno;
X 	fnode_secno fno;
X 	int n_items = 0;
-	int depth, r;
+	int r;
X 	hpfs_adjust_length((char *)name, &len);
X 	hpfs_lock_2inodes(dir, inode);
-	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh, &depth))) {
+	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh))) {
X 		hpfs_unlock_2inodes(dir, inode);
X 		return -ENOENT;
X 	}	
@@ -391,8 +372,6 @@
X 		hpfs_unlock_2inodes(dir, inode);
X 		return -ENOTDIR;
X 	}
-	/*shrink_dcache_parent(dentry);
-	if (dentry->d_count > 1) {*/
X 	if (!list_empty(&dentry->d_hash)) {
X 		hpfs_brelse4(&qbh);
X 		hpfs_unlock_2inodes(dir, inode);
@@ -405,7 +384,7 @@
X 		return -ENOTEMPTY;
X 	}
X 	fno = de->fnode;
-	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, depth)) == 1)
+	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1)
X 		hpfs_error(dir->i_sb, "there was error when removing dirent");
X 	if (r != 2) {
X 		dir->i_nlink--;
@@ -445,7 +424,7 @@
X {
X 	struct inode *inode = dinode->d_inode;
X 	char *link;
-	int len;
+	unsigned len;
X 	struct buffer_head *bh;
X 	struct fnode *fnode;
X 	if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
@@ -471,40 +450,29 @@
X 	int old_len = old_dentry->d_name.len;
X 	char *new_name = (char *)new_dentry->d_name.name;
X 	int new_len = new_dentry->d_name.len;
-	struct inode *i;
+	struct inode *i = old_dentry->d_inode;
X 	struct inode *new_inode = new_dentry->d_inode;
X 	struct quad_buffer_head qbh, qbh1;
X 	struct hpfs_dirent *dep, *nde;
X 	struct hpfs_dirent de;
X 	dnode_secno dno;
-	int depth, r;
-	int err = 0;
+	int r;
X 	struct buffer_head *bh;
X 	struct fnode *fnode;
+	int err;
+	if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
+	err = 0;
X 	hpfs_adjust_length((char *)old_name, &old_len);
-	hpfs_adjust_length((char *)new_name, &new_len);
-	if (hpfs_chk_name((char *)new_name, new_len) || hpfs_chk_name((char *)old_name, old_len)) {
-		err = -ENAMETOOLONG;
-		goto end2;
-	}
-	if (!(i = old_dentry->d_inode)) {
-		hpfs_error(old_dir->i_sb, "hpfs_rename: grrr, could not get inode");
-		err = -ENOENT;
-		goto end2;
-	}
-	if (i->i_sb != old_dir->i_sb || i->i_sb != new_dir->i_sb) {
-		err = -EINVAL; /* Do not allow to move mount points */
-		goto end1_;
-	}
X 
X 	hpfs_lock_3inodes(old_dir, new_dir, i);
X 	
-	if (is_subdir(new_dentry, old_dentry) || (new_inode && S_ISDIR(new_inode->i_mode))) {
+	/* Erm? Moving over the empty non-busy directory is perfectly legal */
+	if (new_inode && S_ISDIR(new_inode->i_mode)) {
X 		err = -EINVAL;
X 		goto end1;
X 	}
X 
-	if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh, &depth))) {
+	if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh))) {
X 		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
X 		err = -ENOENT;
X 		goto end1;
@@ -514,10 +482,10 @@
X 
X 	if (new_inode) {
X 		hpfs_brelse4(&qbh);
-		if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1, NULL))) {
+		if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
X 			int r;
-			if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, depth)) != 2) {
-				if (!(nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1, NULL))) {
+			if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
+				if (!(nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
X 					hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent #2");
X 					goto end1;
X 				}
@@ -539,7 +507,7 @@
X 	if (new_dir == old_dir) hpfs_brelse4(&qbh);
X 
X 	hpfs_lock_creation(i->i_sb);
-	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, depth + 2))) {
+	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {
X 		hpfs_unlock_creation(i->i_sb);
X 		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
X 		err = r == 1 ? -ENOSPC : -EFSERROR;
@@ -548,7 +516,7 @@
X 	}
X 	
X 	if (new_dir == old_dir)
-		if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh, &depth))) {
+		if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh))) {
X 			hpfs_unlock_creation(i->i_sb);
X 			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
X 			err = -ENOENT;
@@ -577,12 +545,9 @@
X 		mark_buffer_dirty(bh, 1);
X 		brelse(bh);
X 	}
-	d_move(old_dentry, new_dentry);
X 	i->i_hpfs_conv = i->i_sb->s_hpfs_conv;
X 	hpfs_decide_conv(i, (char *)new_name, new_len);
X 	end1:
X 	hpfs_unlock_3inodes(old_dir, new_dir, i);
-	end1_:
-	end2:
X 	return err;
X }
diff -u --recursive --new-file v2.3.2/linux/fs/hpfs/super.c linux/fs/hpfs/super.c
--- v2.3.2/linux/fs/hpfs/super.c	Sat May 15 23:46:04 1999
+++ linux/fs/hpfs/super.c	Sun May 16 10:27:40 1999
@@ -105,7 +105,7 @@
X 	MOD_DEC_USE_COUNT;
X }
X 
-static unsigned count_one_bitmap(struct super_block *s, secno secno)
+unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
X {
X 	struct quad_buffer_head qbh;
X 	unsigned *bits;
@@ -114,6 +114,7 @@
X 	count = 0;
X 	for (i = 0; i < 2048 / sizeof(unsigned); i++) {
X 		unsigned b; 
+		if (!bits[i]) continue;
X 		for (b = bits[i]; b; b>>=1) count += b & 1;
X 	}
X 	hpfs_brelse4(&qbh);
@@ -126,7 +127,7 @@
X 	n_bands = (s->s_hpfs_fs_size + 0x3fff) >> 14;
X 	count = 0;
X 	for (n = 0; n < n_bands; n++)
-		count += count_one_bitmap(s, s->s_hpfs_bmp_dir[n]);
+		count += hpfs_count_one_bitmap(s, s->s_hpfs_bmp_dir[n]);
X 	return count;
X }
X 
@@ -135,7 +136,7 @@
X 	struct statfs tmp;
X 	/*if (s->s_hpfs_n_free == -1) {*/
X 		s->s_hpfs_n_free = count_bitmaps(s);
-		s->s_hpfs_n_free_dnodes = count_one_bitmap(s, s->s_hpfs_dmap);
+		s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap);
X 	/*}*/
X 	tmp.f_type = s->s_magic;
X 	tmp.f_bsize = 512;
@@ -379,7 +380,8 @@
X 	s->s_hpfs_cp_table = NULL;
X 
X 	s->s_hpfs_creation_de_lock = s->s_hpfs_rd_inode = 0;
-	s->s_hpfs_creation_de = s->s_hpfs_iget_q = NULL;
+	init_waitqueue_head(&s->s_hpfs_creation_de);
+	init_waitqueue_head(&s->s_hpfs_iget_q);
X 
X 	uid = current->uid;
X 	gid = current->gid;
@@ -540,7 +542,7 @@
X 
X 	root_dno = hpfs_fnode_dno(s, s->s_hpfs_root);
X 	if (root_dno)
-		de = map_dirent(s->s_root->d_inode, root_dno, "\001\001", 2, NULL, &qbh, NULL);
+		de = map_dirent(s->s_root->d_inode, root_dno, "\001\001", 2, NULL, &qbh);
X 	if (!root_dno || !de) hpfs_error(s, "unable to find root dir");
X 	else {
X 		s->s_root->d_inode->i_atime = local_to_gmt(s, de->read_date);
diff -u --recursive --new-file v2.3.2/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.2/linux/fs/minix/namei.c	Fri May 14 18:55:25 1999
+++ linux/fs/minix/namei.c	Sat May 15 23:43:05 1999
@@ -297,7 +297,7 @@
X 	inode->i_nlink = 2;
X 	mark_buffer_dirty(dir_block, 1);
X 	brelse(dir_block);
-	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | mode;
X 	if (dir->i_mode & S_ISGID)
X 		inode->i_mode |= S_ISGID;
X 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.2/linux/fs/namei.c linux/fs/namei.c
--- v2.3.2/linux/fs/namei.c	Fri May 14 18:55:25 1999
+++ linux/fs/namei.c	Sat May 15 23:43:05 1999
@@ -882,10 +882,6 @@
X 	return error;
X }
X 
-/*
- * Look out: this function may change a normal dentry
- * into a directory dentry (different size)..
- */
X static inline int do_mkdir(const char * pathname, int mode)
X {
X 	int error;
@@ -919,7 +915,7 @@
X 		goto exit_lock;
X 
X 	DQUOT_INIT(dir->d_inode);
-	mode &= 0777 & ~current->fs->umask;
+	mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
X 	error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode);
X 
X exit_lock:
diff -u --recursive --new-file v2.3.2/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.3.2/linux/fs/nfsd/vfs.c	Mon Apr 12 10:03:45 1999
+++ linux/fs/nfsd/vfs.c	Sat May 15 23:43:05 1999
@@ -691,6 +691,8 @@
X 		break;
X 	case S_IFDIR:
X 		opfunc = (nfsd_dirop_t) dirp->i_op->mkdir;
+		/* Odd, indeed, but filesystems did it anyway */
+		iap->ia_mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
X 		break;
X 	case S_IFCHR:
X 	case S_IFBLK:
diff -u --recursive --new-file v2.3.2/linux/fs/super.c linux/fs/super.c
--- v2.3.2/linux/fs/super.c	Fri May 14 18:55:26 1999
+++ linux/fs/super.c	Sat May 15 23:43:04 1999
@@ -846,7 +846,8 @@
X  * Anyone using this new feature must know what he/she is doing.
X  */
X 
-int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data)
+int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
+	     const char * type, int flags, void * data)
X {
X 	struct dentry * dir_d;
X 	struct super_block * sb;
diff -u --recursive --new-file v2.3.2/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.3.2/linux/fs/sysv/namei.c	Fri May 14 18:55:26 1999
+++ linux/fs/sysv/namei.c	Sat May 15 23:43:05 1999
@@ -291,7 +291,7 @@
X 	inode->i_nlink = 2;
X 	mark_buffer_dirty(dir_block, 1);
X 	brelse(dir_block);
-	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | mode;
X 	if (dir->i_mode & S_ISGID)
X 		inode->i_mode |= S_ISGID;
X 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.2/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.3.2/linux/fs/ufs/namei.c	Fri May 14 18:55:27 1999
+++ linux/fs/ufs/namei.c	Sat May 15 23:43:05 1999
@@ -539,7 +539,7 @@
X 	inode->i_nlink = 2;
X 	mark_buffer_dirty(dir_block, 1);
X 	brelse (dir_block);
-	inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | mode;
X 	if (dir->i_mode & S_ISGID)
SHAR_EOF
true || echo 'restore of patch-2.3.3 failed'
fi
echo 'End of  part 3'
echo 'File patch-2.3.3 is continued in part 4'
echo 4 > _shar_seq_.tmp