diff -ur linux-109/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- linux-109/drivers/scsi/ultrastor.c	Mon Jan 24 18:55:21 1994
+++ linux/drivers/scsi/ultrastor.c	Sun Feb 15 12:46:24 1998
@@ -282,23 +282,29 @@
 static inline int find_and_clear_bit_16(unsigned short *field)
 {
   int rv;
+  unsigned long flags;
+
+  save_flags(flags);
   cli();
   if (*field == 0) panic("No free mscp");
   asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b"
       : "=&r" (rv), "=m" (*field) : "1" (*field));
-  sti();
+  restore_flags(flags);
   return rv;
 }
 
-/* This asm is fragile: it doesn't work without the casts and it may
+/* This has been re-implemented with the help of Richard Earnshaw,
+   <rwe@pegasus.esprit.ec.org> and works with gcc-2.5.8 and gcc-2.6.0.
+   The instability noted by jfc below appears to be a bug in
+   gcc-2.5.x when compiling w/o optimization.  --Caleb
+
+   This asm is fragile: it doesn't work without the casts and it may
    not work without optimization.  Maybe I should add a swap builtin
    to gcc.  --jfc  */
 static inline unsigned char xchgb(unsigned char reg,
 				  volatile unsigned char *mem)
 {
-  asm("xchgb %0,%1" :
-      "=r" (reg), "=m" (*(unsigned char *)mem) :
-      "0" (reg), "1" (*(unsigned char *)mem));
+  __asm__ ("xchgb %0,%1" : "=q" (reg), "=m" (*mem) : "0" (reg));
   return reg;
 }