]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.47pre8 2.3.47pre8
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:58 +0000 (15:31 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:58 +0000 (15:31 -0500)
92 files changed:
Documentation/Configure.help
Documentation/filesystems/devfs/ChangeLog
Documentation/filesystems/devfs/README
Documentation/kbuild/config-language.txt
Documentation/magic-number.txt
Makefile
arch/i386/boot/setup.S
arch/i386/config.in
arch/i386/kernel/apm.c
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/mtrr.c
arch/i386/kernel/process.c
arch/sparc64/config.in
drivers/block/ll_rw_blk.c
drivers/block/loop.c
drivers/block/raid1.c
drivers/char/Makefile
drivers/char/console.c
drivers/char/h8.c
drivers/char/joystick/joystick.c
drivers/char/stallion.c
drivers/char/sysrq.c
drivers/char/vc_screen.c
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_syms.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/ohci1394.h
drivers/ieee1394/pcilynx.h
drivers/ieee1394/raw1394.c
drivers/net/Config.in
drivers/net/Makefile
drivers/net/eepro100.c
drivers/net/tulip.c
drivers/pcmcia/cs.c
drivers/scsi/st.c
drivers/scsi/st.h
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/esssolo1.c
drivers/sound/sonicvibes.c
drivers/usb/Makefile
drivers/usb/acm.c
drivers/usb/plusb.c
drivers/usb/printer.c
drivers/usb/uhci-debug.h
drivers/usb/usb-core.c
drivers/usb/usb-storage-debug.h [new file with mode: 0644]
drivers/usb/usb-storage.c [new file with mode: 0644]
drivers/usb/usb-storage.h [new file with mode: 0644]
drivers/usb/usb_storage.c [deleted file]
drivers/usb/usb_storage.h [deleted file]
drivers/usb/usb_storage_debug.c [deleted file]
fs/Config.in
fs/binfmt_script.c
fs/ext2/inode.c
fs/inode.c
fs/lockd/clntproc.c
fs/lockd/xdr.c
fs/minix/inode.c
fs/ncpfs/sock.c
fs/nfs/inode.c
fs/nfsd/nfsfh.c
fs/proc/inode.c
fs/super.c
include/linux/apm_bios.h
include/linux/dcache.h
include/linux/fs.h
include/linux/ide.h
include/linux/lists.h
include/linux/pci.h
include/linux/pm.h
include/net/pkt_sched.h
include/net/profile.h
kernel/ksyms.c
kernel/pm.c
kernel/sched.c
mm/mremap.c
mm/page_alloc.c
net/core/dev.c
net/core/profile.c
net/ipv4/ipconfig.c
net/ipv4/tcp_output.c
net/sched/sch_api.c
scripts/Configure
scripts/Menuconfig
scripts/header.tk
scripts/tkcond.c
scripts/tkgen.c
scripts/tkparse.c
scripts/tkparse.h

index 4931d2680fc61bea3ceefbbb32ea090dd7201251..ed07c63bbd0d6847e532b9b50e34d8a7f704b8c0 100644 (file)
@@ -1262,26 +1262,27 @@ CONFIG_PARIDE_ON26
 
 Logical Volume Manager (LVM) support
 CONFIG_BLK_DEV_LVM
-  This driver lets you combine several hard disks, hard disk partitions,
-  multiple devices or even loop devices (for evaluation purposes) into
-  a volume group. Imagine a volume group as a kind of virtual disk.
-  Logical volumes, which can be thought of as virtual partitions,
-  can be created in the volume group.  You can resize volume groups and
-  logical volumes after creation time, corresponding to new capacity needs.
-  Logical volumes are accessed as block devices named
-  /dev/VolumeGroupName/LogicalVolumeName.
+  This driver lets you combine several hard disks, hard disk
+  partitions, multiple devices or even loop devices (for evaluation
+  purposes) into a volume group.  Imagine a volume group as a kind of
+  virtual disk. Logical volumes, which can be thought of as virtual
+  partitions, can be created in the volume group.  You can resize
+  volume groups and logical volumes after creation time, corresponding
+  to new capacity needs.  Logical volumes are accessed as block
+  devices named /dev/VolumeGroupName/LogicalVolumeName.
 
   For details see /usr/src/linux/Documentaion/LVM-HOWTO.
 
   To get the newest software see <http://linux.msede.com/lvm>.
 
-Logical Volume Manager proc filesystem information
+Logical Volume Manager /proc file system information
 CONFIG_LVM_PROC_FS
-  If you say Y here, you are able to access overall Logical Volume Manager,
-  Volume Group, Logical and Physical Volume information in /proc/lvm.
+  If you say Y here, you are able to access overall Logical Volume
+  Manager, Volume Group, Logical and Physical Volume information in
+  /proc/lvm.
 
-  To use this option, you have to check, that the "proc filesystem support"
-  (CONFIG_PROC_FS) is enabled too.
+  To use this option, you have to check, that the "/proc file system
+  support" (CONFIG_PROC_FS) is enabled too.
 
 Multiple devices driver support
 CONFIG_BLK_DEV_MD
@@ -1565,12 +1566,12 @@ CONFIG_SYN_COOKIES
   them off.
 
   If you say Y here, note that SYN cookies aren't enabled by default;
-  you can enable them by saying Y to "/proc file-system support" and
+  you can enable them by saying Y to "/proc file system support" and
   "Sysctl support" below and executing the command
 
     echo 1 >/proc/sys/net/ipv4/tcp_syncookies 
 
-  at boot time after the proc file-system has been mounted.
+  at boot time after the /proc file system has been mounted.
   
   If unsure, say Y.
 
@@ -2092,7 +2093,7 @@ CONFIG_BINFMT_MISC
   Documentation/java.txt for information about how to include Java
   support.
 
-  You must say Y to "proc file system support" (CONFIG_PROC_FS) to
+  You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
   use this part of the kernel.
 
   You may say M here for module support and later load the module when
@@ -4475,7 +4476,7 @@ CONFIG_AIC7XXX_PROC_STATS
   small amount of overhead to each and every SCSI command the aic7xxx
   driver handles, so if you aren't really interested in this
   information, it is best to leave it disabled. This will only work if
-  you also say Y to "/proc file systems support", below. 
+  you also say Y to "/proc file system support", below. 
 
   If unsure, say N.
 
@@ -5732,7 +5733,7 @@ CONFIG_AIRONET4500
        slave=1         Adhoc slave(btw, it is still forming own net 
                        sometimes)
        channel=1..?    meaningful in adhoc mode
-  all other parameters can be set via proc interface
+  all other parameters can be set via /proc interface
   These parameters belong to .._card module, but alas, they are here
   if you have problems with screwing up card, both_bap_lock=1 is conservative
   value (performance hit 15%)
@@ -6210,9 +6211,9 @@ CONFIG_NET_SCHED
   That package also contains some documentation; for more, check out
   http://snafu.freedom.org/linux2.2/iproute-notes.html .
 
-  If you say Y here and to "/proc file systems" below, you will be able
-  to read status information about packet schedulers from the file
-  /proc/net/psched.
+  If you say Y here and to "/proc file system support" below, you will
+  be able to read status information about packet schedulers from the
+  file /proc/net/psched.
   
   The available schedulers are listed in the following questions; you
   can say Y to as many as you like. If unsure, say N now.
@@ -6415,7 +6416,7 @@ CONFIG_NET_CLS_RSVP6
 
 Network code profiler
 CONFIG_NET_PROFILE
-  If you say Y here and to "/proc file systems support" below, some
+  If you say Y here and to "/proc file system support" below, some
   obscure and undocumented information about the network code's
   performance will be written to /proc/net/profile. If you don't know
   what it is about, you don't need it: say N.
@@ -6770,17 +6771,29 @@ CONFIG_NI65
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-RealTek 8129/8139 (not 8019/8029!) support
-CONFIG_RTL8139
+RealTek 8129 (not 8019/8029!) support (EXPERIMENTAL)
+CONFIG_RTL8129
   This is a driver for the Fast Ethernet PCI network cards based on
-  the RTL8129 and RTL8139 chips. If you have one of those, say Y and
+  the RTL8129 chip. If you have one of those, say Y and
   read the Ethernet-HOWTO, available from
   http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
   say M here and read Documentation/modules.txt. This is recommended.
-  The module will be called rtl8139.o.
+  The module will be called rtl8129.o.
+
+RealTek RTL-8139 PCI Fast Ethernet Adapter support
+CONFIG_8139TOO
+  This is a driver for the Fast Ethernet PCI network cards based on
+  the RTL8139 chip. If you have one of those, say Y and
+  read the Ethernet-HOWTO, available from
+  http://www.linuxdoc.org/docs.html#howto .
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. This is recommended.
+  The module will be called 8139too.o.
 
 SiS 900 PCI Fast Ethernet Adapter support
 CONFIG_SIS900
@@ -7330,7 +7343,7 @@ CONFIG_SKMC
   Documentation/networking/net-modules.txt.
 
 EISA, VLB, PCI and on board controllers
-CONFIG_NET_EISA
+CONFIG_NET_PCI
   This is another class of network cards which attach directly to the
   bus. If you have one of those, say Y and read the Ethernet-HOWTO,
   available from http://www.linuxdoc.org/docs.html#howto .
@@ -7451,7 +7464,7 @@ CONFIG_DGRS
   Documentation/networking/net-modules.txt.
 
 EtherExpress PRO/100 support
-CONFIG_EEXPRESS_PRO100
+CONFIG_EEPRO100
   If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
   card, say Y and read the Ethernet-HOWTO, available from
   http://www.linuxdoc.org/docs.html#howto .
@@ -8528,9 +8541,9 @@ CONFIG_EXT2_FS
   compiled as a module, and so this could be dangerous. Most everyone
   wants to say Y here.
 
-SCO UnixWare BFS Support
+BFS file system support (EXPERIMENTAL)
 CONFIG_BFS_FS
-  Boot Filesystem (BFS) is a file system used under SCO UnixWare to
+  Boot File System (BFS) is a file system used under SCO UnixWare to
   allow bootloader access the kernel image and other important files
   during the boot process. It is usually mounted under /stand and
   corresponds to the slice marked as "STAND" in the UnixWare
@@ -8548,7 +8561,7 @@ CONFIG_BFS_FS
 ISO 9660 CDROM file system support
 CONFIG_ISO9660_FS
   This is the standard file system used on CDROMs. It was previously
-  known as "High Sierra Filesystem" and is called "hsfs" on other Unix
+  known as "High Sierra File System" and is called "hsfs" on other Unix
   systems. The so-called Rock-Ridge extensions which allow for long
   Unix filenames and symbolic links are also supported by this driver.
   If you have a CDROM drive and want to do more with it than just
@@ -8571,7 +8584,7 @@ CONFIG_JOLIET
   http://www.unicode.org for more information). Say Y here if you want
   to be able to read Joliet CDROMs under Linux.
 
-UDF Filesystem support (read only)
+UDF file system support (read only)
 CONFIG_UDF_FS
   This is the new file system used by some CDROMS and DVD drivers. Say
   Y if you intend to mount DVD discs or CDRW's written in packet mode,
@@ -8677,7 +8690,7 @@ CONFIG_VFAT_FS
   say M here and read Documentation/modules.txt. The module will be
   called vfat.o.
 
-UMSDOS: Unix-like file system on top of standard MSDOS file system
+UMSDOS: Unix-like file system on top of standard MSDOS fs
 CONFIG_UMSDOS_FS
   Say Y here if you want to run Linux from within an existing DOS
   partition of your hard drive. The advantage of this is that you can
@@ -8719,32 +8732,34 @@ CONFIG_PROC_FS
   often a source of trouble if two devices are mistakenly configured
   to use the same IRQ). 
 
-  The /proc filesystem is explained in the file
+  The /proc file system is explained in the file
   Documentation/filesystems/proc.txt and on the proc(5) manpage ("man
   5 proc").
 
   This option will enlarge your kernel by about 67 KB. Several
   programs depend on this, so everyone should say Y here.
 
-/dev filesystem support (EXPERIMENTAL)
+/dev file system support (EXPERIMENTAL)
 CONFIG_DEVFS_FS
-  This is another virtual filesystem (like /proc) which provides the
-  filesystem interface to device drivers, normally found in /dev.
+  This is another virtual file system (like /proc) which provides the
+  file system interface to device drivers, normally found in /dev.
   Devfs does not depend on major and minor number allocations. Device
   drivers register entries in /dev which appear automagically. Without
   devfs you need to populate /dev with hundreds, even thousands of
   inodes.
   This is work in progress. If you want to use this you *must* read
   Documentation/filesystems/devfs/README
+  In particular, make sure you install devfsd. If you don't, expect to
+  spend time patching broken code and updating configuration files.
 
-Enable devfs debugging output
+Debug devfs
 CONFIG_DEVFS_DEBUG
   This option appears if you have CONFIG_DEVFS_FS enabled. Setting
   this to 'Y' enables devfs debugging output. See the file
   Documentation/filesystems/devfs/boot-options for more details.
   The default is 'N'.
 
-NFS filesystem support
+NFS file system support
 CONFIG_NFS_FS
   If you are connected to some other (usually local) Unix computer
   (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
@@ -8834,7 +8849,7 @@ CONFIG_HPFS_FS
   The module is called hpfs.o. If you want to compile it as a module,
   say M here and read Documentation/modules.txt. If unsure, say N.
 
-Windows NT NTFS support (read only)
+NTFS file system support (read only)
 CONFIG_NTFS_FS
   NTFS is the file system of Microsoft Windows NT. Say Y if you want
   to get read access to files on NTFS partitions of your hard drive.
@@ -8989,7 +9004,7 @@ CONFIG_AUTOFS_FS
   If you want to use the newer version of autofs with more features,
   say N here and select automounter v4.
 
-Kernel automounter v4 support
+Kernel automounter version 4 support (also supports v3)
 CONFIG_AUTOFS4_FS
   The automounter is a tool to automatically mount remote file systems
   on demand. This implementation is partially kernel-based to reduce
@@ -9170,8 +9185,9 @@ CONFIG_UNIXWARE_DISKLABEL
   partition (VTOC - Virtual Table of Contents). Its format is
   incompatible with all other OSes. Saying Y here allows you to read
   VTOC and further mount UnixWare partitions read-only from within
-  Linux if you have also said Y to "UFS file system support" or "System
-  V and Coherent file system support", above.
+  Linux if you have also said Y to "UFS file system support", "System
+  V and Coherent file system support" or "BFS file system support",
+  above.
 
   This is mainly used to carry data from a UnixWare box to your
   Linux box via a removable medium like magneto-optical, ZIP or
@@ -10291,7 +10307,7 @@ CONFIG_FT_NR_BUFFERS
 Procfs entry for ftape
 CONFIG_FT_PROC_FS
   Optional. Saying Y will result in creation of a directory
-  `/proc/ftape' under the proc file system. The files can be viewed
+  `/proc/ftape' under the /proc file system. The files can be viewed
   with your favorite pager (i.e. use "more /proc/ftape/history" or
   "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The
   file will contain some status information about the inserted
@@ -10301,9 +10317,10 @@ CONFIG_FT_PROC_FS
   by approximately 2 KB.
 
   WARNING: When compiling ftape as a module (i.e. saying M to
-  "Floppy tape drive") it is dangerous to use ftape's proc file system
-  interface. Accessing `/proc/ftape' while the module is unloaded will
-  result in a kernel Oops. This cannot be fixed from inside ftape.
+  "Floppy tape drive") it is dangerous to use ftape's /proc file
+  system interface. Accessing `/proc/ftape' while the module is
+  unloaded will result in a kernel Oops. This cannot be fixed from
+  inside ftape.
 
 Controlling the amount of debugging output of ftape
 CONFIG_FT_NORMAL_DEBUG
@@ -10632,6 +10649,11 @@ CONFIG_APM
    11) exchange RAM chips 
    12) exchange the motherboard.
 
+  To compile this driver as a module ( = code which can be inserted in
+  and removed from the running kernel whenever you want), say M here
+  and read Documentation/modules.txt. The module will be called
+  apm.o.
+
 Ignore USER SUSPEND
 CONFIG_APM_IGNORE_USER_SUSPEND
   This option will ignore USER SUSPEND requests. On machines with a
@@ -10713,14 +10735,6 @@ CONFIG_APM_ALLOW_INTS
   many of the newer IBM Thinkpads.  If you experience hangs when you
   suspend, try setting this to Y.  Otherwise, say N.
 
-Entry point offset fix (some Acer laptops)
-CONFIG_APM_BAD_ENTRY_OFFSET
-  Some implementations of the APM BIOS provide the driver with a bad
-  entry point offset.  If you set this option to Y, then the upper
-  sixteen bits of the offset will be set to zero.  This is usually
-  unnecessary but harmless.  This is required for the Acer Travelmate
-  510DX, Travelmate 510T and Extensa 503T.  For others, say N.
-
 Use real mode APM BIOS call to power off
 CONFIG_APM_REAL_MODE_POWER_OFF
   Use real mode APM BIOS calls to switch off the computer. This is
index 0096e3bcf66501166248de69fb69bba669fe9673..7d8e588904951b235eaba0be08482a8f1207f7d0 100644 (file)
@@ -913,7 +913,7 @@ Changes for patch v104
 Changes for patch v105
 
 - Unregister SCSI host from <scsi_host_no_list> in <scsi_unregister>
-  Thanks to Zoltan BOSZORMENYI <zboszor@mol.hu>
+  Thanks to Zoltán Böszörményi <zboszor@mail.externet.hu>
 
 - Don't save /dev/log in rc.devfs
 
@@ -1450,3 +1450,16 @@ Work sponsored by SGI
 
 - Moved device registration from <lp_init> to <lp_register>
   Thanks to Tim Waugh <twaugh@redhat.com>
+===============================================================================
+Changes for patch v160
+
+Work sponsored by SGI
+
+- Fixed drivers/char/joystick/joystick.c
+  Thanks to Vojtech Pavlik <vojtech@suse.cz>
+
+- Documentation updates
+
+- Fixed arch/i386/kernel/mtrr.c if procfs and devfs not enabled
+
+- Fixed drivers/char/stallion.c
index a4fc3f9088b223cc04722aef3f5ffc7fe16136bb..b3ab9ffa6f8d0d150bf0951ec820ce04b9a10db8 100644 (file)
@@ -472,6 +472,29 @@ it to maintain compatibility entries. It is almost certain that you
 will require this. Note that the kernel creates a compatibility entry
 for the root device, so you don't need initrd.
 
+Note that you no longer need to mount devpts if you use Unix98 PTYs,
+as devfs can manage /dev/pts itself. This saves you some RAM, as you
+don't need to compile and install devpts. Note that some versions of
+glibc have a bug with Unix98 pty handling on devfs systems. Contact
+the glibc maintainers for a fix.
+
+Note also that apart from editing /etc/fstab, other things will need
+to be changed if you *don't* install devfsd. Some software (like the X
+server) hard-wire device names in their source. It really is much
+easier to install devfsd so that compatibility entries are created.
+You can then slowly migrate your system to using the new device names
+(for example, by starting with /etc/fstab), and then limiting the
+compatibility entries that devfsd creates.
+MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
+
+Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of
+reports back. Many of these are because people are trying to run
+without devfsd, and hence some things break. Please just run devfsd if
+things break. I want to concentrate on real bugs rather than
+misconfiguration problems at the moment. If people are willing to fix
+bugs/false assumptions in other code (i.e. glibc, X server) and submit
+that to the respective maintainers, that would be great.
+
 Fail-safe Approach with real /dev inodes                           <subsection>
 ----------------------------------------
 This method involves more work, and is no longer recommended now that
@@ -614,25 +637,25 @@ Device drivers currently ported                                       <section>
 - TTY devices (console, serial ports, terminals and pseudo-terminals)
   Thanks to C. Scott Ananian <cananian@alumni.princeton.edu>
 
-- SCSI tapes (/dev/st*)
+- SCSI tapes (/dev/scsi and /dev/tapes)
 
-- SCSI CD-ROMs (/dev/sr*)
+- SCSI CD-ROMs (/dev/scsi and /dev/cdroms)
 
-- SCSI generic devices (/dev/sg*)
+- SCSI generic devices (/dev/scsi)
 
 - RAMDISCS (/dev/ram?)
 
 - Meta Devices (/dev/md*)
 
-- Floppy discs (/dev/fd?*)
+- Floppy discs (/dev/floppy)
 
-- Parallel port printers (/dev/lp*)
+- Parallel port printers (/dev/printers)
 
-- Sound devices
+- Sound devices (/dev/sound)
   Thanks to Eric Dumas <dumas@linux.eu.org> and
   C. Scott Ananian <cananian@alumni.princeton.edu>
 
-- Joysticks (/dev/js*)
+- Joysticks (/dev/joysticks)
 
 - Sparc keyboard (/dev/kbd)
 
@@ -642,12 +665,12 @@ Device drivers currently ported                                       <section>
 
 - Coda network file system (/dev/cfs*)
 
-- Virtual console capture devices (/dev/vcs*)
+- Virtual console capture devices (/dev/vcc)
   Thanks to Dennis Hou <smilax@mindmeld.yi.org>
 
-- Frame buffer devices (/dev/fb*)
+- Frame buffer devices (/dev/fb)
 
-- Video capture devices (/dev/video? /dev/vbi?)
+- Video capture devices (/dev/v4l)
 
 
 Naming Scheme                                                         <section>
@@ -751,6 +774,7 @@ The tty devices now appear as:
   /dev/tts/{0,1,...}         /dev/ttyS{0,1,...}         Serial ports
   /dev/cua/{0,1,...}         /dev/cua{0,1,...}          Call out devices
   /dev/vc/{0,1,...}          /dev/tty{1...63}           Virtual consoles
+  /dev/vcc/{0,1,...}         /dev/vcs{1...63}           Virtual consoles
   /dev/pty/m{0,1,...}        /dev/ptyp??                PTY masters
   /dev/pty/s{0,1,...}        /dev/ttyp??                PTY slaves
 
@@ -849,5 +873,12 @@ simultaneous xterms and remote logins).  Note that the device number
 is limited to the range 36864-61439 (majors 144-239), in order to
 avoid any possible conflicts with existing official allocations.
 
+Please note that using dynamically allocated block device numbers may
+break the NFS daemons (both user and kernel mode), which expect dev_t
+for a given device to be constant over reboots. A simple reboot, with
+no change in your hardware layout, would result in the same device
+numbers being allocated, and hence will not cause a problem for NFS
+daemons.
+
 A final note on this scheme: since it doesn't increase the size of
 device numbers, there are no compatibility issues with userspace.
index 50b788730a823d2b5ae98083217e0981570fdfa7..357dc5122a63d3c68d3e352bc6c2c8adcb316092 100644 (file)
@@ -120,6 +120,7 @@ Here are all the statements:
     Dependent statements:
 
         dep_bool        /prompt/ /symbol/ /dep/ ...
+        dep_mbool       /prompt/ /symbol/ /dep/ ...
         dep_hex         /prompt/ /symbol/ /word/ /dep/ ...
         dep_int         /prompt/ /symbol/ /word/ /dep/ ...
         dep_string      /prompt/ /symbol/ /word/ /dep/ ...
@@ -386,8 +387,8 @@ mconfig:    implemented
 
 Example:
 
-    # Not from the corpus
-    define_int CONFIG_UID_TORVALDS 2026
+    # drivers/char/ftape/Config.in
+    define_int CONFIG_FT_ALPHA_CLOCK 0
 
 
 
@@ -424,10 +425,15 @@ mconfig:    implemented
 
 Example:
 
-    # not from the corpus
-    if [ "$CONFIG_ZFTAPE" != "n" ]; then
-      comment 'The compressor will be built as a module only!'
-      define_tristate CONFIG_ZFT_COMPRESSOR m
+    # drivers/video/Config.in
+    if [ "$CONFIG_FB_AMIGA" = "y" ]; then
+       define_tristate CONFIG_FBCON_AFB y
+       define_tristate CONFIG_FBCON_ILBM y
+    else
+       if [ "$CONFIG_FB_AMIGA" = "m" ]; then
+          define_tristate CONFIG_FBCON_AFB m
+          define_tristate CONFIG_FBCON_ILBM m
+       fi
     fi
 
 
@@ -438,6 +444,36 @@ This verb evaluates all of the dependencies in the dependency list.
 Any dependency which has a value of "y" does not restrict the input
 range.  Any dependency which has an empty value is ignored.
 Any dependency which has a value of "n", or which has some other value,
+(like "m") restricts the input range to "n".  Quoting dependencies is not
+allowed. Using dependencies with an empty value possible is not
+recommended.  See also dep_mbool below.
+
+If the input range is restricted to the single choice "n", dep_bool
+silently assigns "n" to /symbol/.  If the input range has more than
+one choice, dep_bool displays /prompt/ to the user, accepts a value
+from the user, and assigns that value to /symbol/.
+
+Configure:  implemented
+Menuconfig: implemented
+XConfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # drivers/net/Config.in
+    dep_bool 'Aironet 4500/4800 PCI support 'CONFIG_AIRONET4500_PCI $CONFIG_PCI
+
+Known bugs:
+- Xconfig does not write "# foo is not set" to .config (as well as
+  "#unset foo" to autoconf.h) if command is disabled by its dependencies.
+
+
+=== dep_mbool /prompt/ /symbol/ /dep/ ...
+
+This verb evaluates all of the dependencies in the dependency list.
+Any dependency which has a value of "y" or "m" does not restrict the
+input range.  Any dependency which has an empty value is ignored.
+Any dependency which has a value of "n", or which has some other value,
 restricts the input range to "n".  Quoting dependencies is not allowed.
 Using dependencies with an empty value possible is not recommended.
 
@@ -446,13 +482,18 @@ silently assigns "n" to /symbol/.  If the input range has more than
 one choice, dep_bool displays /prompt/ to the user, accepts a value
 from the user, and assigns that value to /symbol/.
 
+Notice that the only difference between dep_bool and dep_mbool
+is in the way of treating the "m" value as a dependency.
+
 Configure:  implemented
 Menuconfig: implemented
 XConfig:    implemented
-mconfig:    implemented
+mconfig:    not implemented
 
-    # not from the corpus
-    dep_bool 'RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_PCI
+Example:
+
+    # Not from the corpus
+    dep_mbool 'Packet socket: mmapped IO' CONFIG_PACKET_MMAP $CONFIG_PACKET
 
 Known bugs:
 - Xconfig does not write "# foo is not set" to .config (as well as
@@ -492,6 +533,11 @@ Menuconfig: implemented
 Xconfig:    implemented
 mconfig:    implemented
 
+Example:
+
+    # drivers/char/Config.in
+    dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+
 Known bugs:
 - Xconfig does not write "# foo is not set" to .config (as well as
   "#unset foo" to autoconf.h) if command is disabled by its dependencies.
@@ -508,6 +554,13 @@ Menuconfig: implemented
 Xconfig:    implemented (with bugs)
 mconfig:    implemented
 
+Example:
+
+    # arch/mips/config.in
+    unset CONFIG_PCI
+    unset CONFIG_MIPS_JAZZ
+    unset CONFIG_VIDEO_G364
+
 
 
 === choice /prompt/ /word/ /word/
@@ -538,6 +591,14 @@ Menuconfig: implemented
 Xconfig:    implemented
 mconfig:    implemented
 
+Example:
+
+    # arch/i386/config.in
+    choice '  PCI access mode' \
+        "BIOS           CONFIG_PCI_GOBIOS       \
+         Direct         CONFIG_PCI_GODIRECT     \
+         Any            CONFIG_PCI_GOANY"       Any
+
 
 
 === nchoice /prompt/ /symbol/ /prompt/ /symbol/ ...
@@ -603,9 +664,6 @@ Xconfig has some known bugs, and probably some unknown bugs too:
 
 - literals with an empty "" value are not properly handled.
 
-- tkparse gives the wrong precedence to -o, -a, and !.  Don't use both
-  -o and -a in an expression.  Don't use ! at all.
-
 
 
 === mainmenu_option next_comment
index 4449732ab81afa33fec393090638d17d1feaf737..5b81ca3f863ce0076c3b8c042d3daa18c3239da9 100644 (file)
@@ -48,7 +48,7 @@ Magic Name            Number      Structure            File
 PG_MAGIC             'P'         pg_{read,write}_hdr include/linux/pg.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
-APM_BIOS_MAGIC        0x4101      apm_bios_struct   include/linux/apm_bios.h
+APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
 FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
 PTY_MAGIC            0x5001      (none at the moment)
index 88fd0d824745932df752c5c2c00cce23d2232388..659b9779d43eeadfc12a4d04bf3269aafdb69986 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -271,8 +271,8 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
        $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
                --start-group \
                $(CORE_FILES) \
-               $(NETWORKS) \
                $(DRIVERS) \
+               $(NETWORKS) \
                $(LIBS) \
                --end-group \
                -o vmlinux
index 1a08bc3abd06a67bdd6b5920095b61cc915fa369..7c50d54a88cc6bdcd333752519894a849ba63eb1 100644 (file)
@@ -436,7 +436,7 @@ no_mca:
        movw    $0xAA, (0x1ff)                  # device present
 no_psmouse:
 
-#ifdef CONFIG_APM
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
 # Then check for an APM BIOS...
                                                # %ds points to the bootsector
        movw    $0, 0x40                        # version = 0 means no APM BIOS
@@ -455,7 +455,11 @@ no_psmouse:
        xorw    %bx, %bx
        int     $0x15                           # ignore return code
        movw    $0x05303, %ax                   # 32 bit connect
-       xorw    %bx, %bx
+       xorl    %ebx, %ebx
+       xorw    %cx, %cx                        # paranoia :-)
+       xorw    %dx, %dx                        #   ...
+       xorl    %esi, %esi                      #   ...
+       xorw    %di, %di                        #   ...
        int     $0x15
        jc      no_32_apm_bios                  # Ack, error. 
 
@@ -463,12 +467,13 @@ no_psmouse:
        movl    %ebx, (68)                      # BIOS entry point offset
        movw    %cx,  (72)                      # BIOS 16 bit code segment
        movw    %dx,  (74)                      # BIOS data segment
-       movl    %esi, (78)                      # BIOS code segment length
+       movl    %esi, (78)                      # BIOS code segment lengths
        movw    %di,  (82)                      # BIOS data segment length
 # Redo the installation check as the 32 bit connect
 # modifies the flags returned on some BIOSs
        movw    $0x05300, %ax                   # APM BIOS installation check
        xorw    %bx, %bx
+       xorw    %cx, %cx                        # paranoia
        int     $0x15
        jc      apm_disconnect                  # error -> shouldn't happen
 
index 980fbcbf1140e89ae39986ab4fb08e24b8971c71..e074ea81d0f2a6c5771a98239e8d0e974ea2e7d2 100644 (file)
@@ -148,7 +148,7 @@ if [ "$CONFIG_ACPI" != "n" ]; then
    fi
 fi
 
-bool 'Advanced Power Management BIOS support' CONFIG_APM
+tristate 'Advanced Power Management BIOS support' CONFIG_APM
 if [ "$CONFIG_APM" != "n" ]; then
    bool '  Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
    bool '  Enable PM at boot time' CONFIG_APM_DO_ENABLE
@@ -158,7 +158,6 @@ if [ "$CONFIG_APM" != "n" ]; then
    bool '  Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
    bool '  RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
    bool '  Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
-   bool '  Entry point offset fix (some Acer laptops)' CONFIG_APM_BAD_ENTRY_OFFSET
    bool '  Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
 fi
 
index 4b90347c48c2ef5aae9a34ba29d46031ec9e3ecd..4ec5e7993e3594df7b9041960a6f62ae9a173698 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  * APM BIOS driver for Linux
- * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.com)
  *
  * Initial development of this driver was funded by NEC Australia P/L
  *     and NEC Corporation
@@ -35,6 +35,8 @@
  * Jan 1999, Version 1.9
  * Oct 1999, Version 1.10
  * Nov 1999, Version 1.11
+ * Jan 2000, Version 1.12
+ * Feb 2000, Version 1.13
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -54,7 +56,7 @@
  *         The new replacment for it is, but Linux doesn't yet support this.
  *         Alan Cox Linux 2.1.55
  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
- *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by 
+ *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
  *         Dean Gaudet <dgaudet@arctic.org>.
  *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
  *    1.5: Fix segment register reloading (in case of bad segments saved
  *         (reported by Panos Katsaloulis <teras@writeme.com>).
  *         Real mode power off patch (Walter Hofmann
  *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
+ *   1.12: Remove CONFIG_SMP as the compiler will optimize
+ *         the code away anyway (smp_num_cpus == 1 in UP)
+ *         noted by Artur Skawina <skawina@geocities.com>.
+ *         Make power off under SMP work again.
+ *         Fix thinko with initial engaging of BIOS.
+ *         Make sure power off only happens on CPU 0
+ *         (Paul "Rusty" Russell <rusty@linuxcare.com>).
+ *         Do error notification to user mode if BIOS calls fail.
+ *         Move entrypoint offset fix to ...boot/setup.S
+ *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
+ *         Remove smp-power-off. SMP users must now specify
+ *         "apm=power-off" on the kernel command line. Suggested
+ *         by Jim Avera <jima@hal.com>, modified by Alan Cox
+ *         <alan@lxorguk.ukuu.org.uk>.
+ *         Register the /proc/apm entry even on SMP so that
+ *         scripts that check for it before doing power off
+ *         work (Jim Avera <jima@hal.com>).
+ *   1.13: Changes for new pm_ interfaces (Andy Henroid
+ *         <andy_henroid@yahoo.com>).
+ *         Modularize the code.
  *
  * APM 1.1 Reference:
  *
 #include <linux/apm_bios.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/pm.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
-#include <linux/pm.h>
-
 extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
 
@@ -172,10 +193,10 @@ extern int (*console_blank_hook)(int);
  * See Documentation/Config.help for the configuration options.
  *
  * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
  *     apm=on/off                      enable/disable APM
  *         [no-]debug                  log some debugging messages
- *         [no-]power-off              power off on shutdown
- *         [no-]smp-power-off          allow power off even for SMP
+ *         [no-]power[-_]off           power off on shutdown
  */
 
 /* KNOWN PROBLEM MACHINES:
@@ -219,8 +240,8 @@ extern int (*console_blank_hook)(int);
 
 /*
  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David 
- * Chen <chen@ctpa04.mit.edu>
+ * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
+ * David Chen <chen@ctpa04.mit.edu>
  */
 #undef INIT_TIMER_AFTER_SUSPEND
 
@@ -237,7 +258,7 @@ extern int (*console_blank_hook)(int);
 
 /*
  * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
- * ignore suspend events for this amount of time
+ * ignore suspend events for this amount of time after a resume
  */
 #define BOUNCE_INTERVAL                (3 * HZ)
 
@@ -247,6 +268,34 @@ extern int (*console_blank_hook)(int);
 #define savesegment(seg, where) \
                __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
 
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS         20
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+       int             magic;
+       struct apm_user *       next;
+       int             suser: 1;
+       int             suspend_wait: 1;
+       int             suspend_result;
+       int             suspends_pending;
+       int             standbys_pending;
+       int             suspends_read;
+       int             standbys_read;
+       int             event_head;
+       int             event_tail;
+       apm_event_t     events[APM_MAX_EVENTS];
+};
+
+/*
+ * The magic number in apm_user
+ */
+#define APM_BIOS_MAGIC         0x4101
+
 /*
  * Local variables
  */
@@ -254,8 +303,6 @@ static struct {
        unsigned long   offset;
        unsigned short  segment;
 }                              apm_bios_entry;
-static int                     apm_enabled = 0;
-static int                     smp_hack = 0;
 #ifdef CONFIG_APM_CPU_IDLE
 static int                     clock_slowed = 0;
 #endif
@@ -274,12 +321,19 @@ static int                        got_clock_diff = 0;
 #endif
 static int                     debug = 0;
 static int                     apm_disabled = 0;
-static int                     power_off_enabled = 1;
+#ifdef CONFIG_SMP
+static int                     power_off = 0;
+#else
+static int                     power_off = 1;
+#endif
+static int                     exit_kapmd = 0;
+static int                     kapmd_running = 0;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static struct apm_bios_struct *        user_list = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+static struct apm_user *       user_list = NULL;
 
-static char                    driver_version[] = "1.11";      /* no spaces */
+static char                    driver_version[] = "1.12";      /* no spaces */
 
 static char *  apm_event_name[] = {
        "system standby",
@@ -380,6 +434,10 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
        __save_flags(flags);
        APM_DO_CLI;
        APM_DO_SAVE_SEGS;
+       /*
+        * N.B. We do NOT need a cld after the BIOS call
+        * because we always save and restore the flags.
+        */
        __asm__ __volatile__(APM_DO_ZERO_SEGS
                "pushl %%edi\n\t"
                "pushl %%ebp\n\t"
@@ -413,10 +471,14 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
        {
                int     cx, dx, si;
 
+               /*
+                * N.B. We do NOT need a cld after the BIOS call
+                * because we always save and restore the flags.
+                */
                __asm__ __volatile__(APM_DO_ZERO_SEGS
                        "pushl %%edi\n\t"
                        "pushl %%ebp\n\t"
-                       "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry)"\n\t"
+                       "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
                        "setc %%bl\n\t"
                        "popl %%ebp\n\t"
                        "popl %%edi\n\t"
@@ -499,6 +561,7 @@ static void apm_do_busy(void)
        }
 }
 
+#if 0
 extern int hlt_counter;
 
 /*
@@ -543,48 +606,63 @@ static void apm_cpu_idle(void)
        }
 }
 #endif
+#endif
+
+#ifdef CONFIG_SMP
+static int apm_magic(void * unused)
+{
+       while (1)
+               schedule();
+}
+#endif
 
 static void apm_power_off(void)
 {
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+       unsigned char   po_bios_call[] = {
+               0xb8, 0x00, 0x10,       /* movw  $0x1000,ax  */
+               0x8e, 0xd0,             /* movw  ax,ss       */
+               0xbc, 0x00, 0xf0,       /* movw  $0xf000,sp  */
+               0xb8, 0x07, 0x53,       /* movw  $0x5307,ax  */
+               0xbb, 0x01, 0x00,       /* movw  $0x0001,bx  */
+               0xb9, 0x03, 0x00,       /* movw  $0x0003,cx  */
+               0xcd, 0x15              /* int   $0x15       */
+       };
+#endif
+
        /*
-        * smp_hack == 2 means that we would have enabled APM support
-        * except there is more than one processor and so most of
-        * the APM stuff is unsafe.  We will still try power down
-        * because is is useful to some people and they know what
-        * they are doing because they booted with the smp-power-off
-        * kernel option.
+        * This may be called on an SMP machine.
         */
-       if (apm_enabled || (smp_hack == 2)) {
+#ifdef CONFIG_SMP
+       /* Some bioses don't like being called from CPU != 0 */
+       while (cpu_number_map[smp_processor_id()] != 0) {
+               kernel_thread(apm_magic, NULL,
+                       CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+               schedule();
+       }
+#endif
 #ifdef CONFIG_APM_REAL_MODE_POWER_OFF
-               unsigned char   po_bios_call[] = {
-                       0xb8, 0x00, 0x10,       /* movw  $0x1000,ax  */
-                       0x8e, 0xd0,             /* movw  ax,ss       */
-                       0xbc, 0x00, 0xf0,       /* movw  $0xf000,sp  */
-                       0xb8, 0x07, 0x53,       /* movw  $0x5307,ax  */
-                       0xbb, 0x01, 0x00,       /* movw  $0x0001,bx  */
-                       0xb9, 0x03, 0x00,       /* movw  $0x0003,cx  */
-                       0xcd, 0x15              /* int   $0x15       */
-               };
-
-               machine_real_restart(po_bios_call, sizeof(po_bios_call));
+       machine_real_restart(po_bios_call, sizeof(po_bios_call));
 #else
-               (void) apm_set_power_state(APM_STATE_OFF);
+       (void) apm_set_power_state(APM_STATE_OFF);
 #endif
-       }
 }
 
-#ifdef CONFIG_APM_DO_ENABLE
-static int __init apm_enable_power_management(void)
+static int apm_enable_power_management(int enable)
 {
        u32     eax;
 
+       if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+               return APM_NOT_ENGAGED;
        if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
-                       1, &eax))
+                       enable, &eax))
                return (eax >> 8) & 0xff;
-       apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+       if (enable)
+               apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+       else
+               apm_bios_info.flags |= APM_BIOS_DISABLED;
        return APM_SUCCESS;
 }
-#endif
 
 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
 {
@@ -632,12 +710,21 @@ static int apm_get_battery_status(u_short which, u_short *status,
 }
 #endif
 
-static int __init apm_engage_power_management(u_short device)
+static int apm_engage_power_management(u_short device, int enable)
 {
        u32     eax;
 
-       if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, 1, &eax))
+       if ((enable == 0) && (device == APM_DEVICE_ALL)
+           && (apm_bios_info.flags & APM_BIOS_DISABLED))
+               return APM_DISABLED;
+       if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
                return (eax >> 8) & 0xff;
+       if (device == APM_DEVICE_ALL) {
+               if (enable)
+                       apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+               else
+                       apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+       }
        return APM_SUCCESS;
 }
 
@@ -655,7 +742,6 @@ static void apm_error(char *str, int err)
 }
 
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-/* Called from console driver -- must make sure apm_enabled. */
 static int apm_console_blank(int blank)
 {
        int     error;
@@ -664,9 +750,13 @@ static int apm_console_blank(int blank)
        state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
        /* Blank the first display device */
        error = set_power_state(0x100, state);
-       if (error != APM_SUCCESS)
+       if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
                /* try to blank them all instead */
                error = set_power_state(0x1ff, state);
+               if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
+                       /* try to blank device one instead */
+                       error = set_power_state(0x101, state);
+       }
        if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
                return 1;
        apm_error("set display", error);
@@ -674,20 +764,20 @@ static int apm_console_blank(int blank)
 }
 #endif
 
-static int queue_empty(struct apm_bios_struct * as)
+static int queue_empty(struct apm_user *as)
 {
        return as->event_head == as->event_tail;
 }
 
-static apm_event_t get_queued_event(struct apm_bios_struct * as)
+static apm_event_t get_queued_event(struct apm_user *as)
 {
        as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
        return as->events[as->event_tail];
 }
 
-static void queue_event(apm_event_t event, struct apm_bios_struct *sender)
+static void queue_event(apm_event_t event, struct apm_user *sender)
 {
-       struct apm_bios_struct *        as;
+       struct apm_user *       as;
 
        if (user_list == NULL)
                return;
@@ -751,18 +841,11 @@ static void get_time_diff(void)
 #endif
 }
 
-static void suspend(void)
+static void reinit_timer(void)
 {
-       int             err;
 #ifdef INIT_TIMER_AFTER_SUSPEND
        unsigned long   flags;
-#endif
 
-       get_time_diff();
-       err = apm_set_power_state(APM_STATE_SUSPEND);
-       if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
-               apm_error("suspend", err);
-#ifdef INIT_TIMER_AFTER_SUSPEND
        save_flags(flags);
        cli();
        /* set the clock to 100 Hz */
@@ -774,7 +857,27 @@ static void suspend(void)
        udelay(10);
        restore_flags(flags);
 #endif
+}
+
+static int suspend(void)
+{
+       int             err;
+       int             ret;
+       struct apm_user *as;
+
+       get_time_diff();
+       err = apm_set_power_state(APM_STATE_SUSPEND);
+       reinit_timer();
        set_time();
+       ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
+       if (!ret)
+               apm_error("suspend", err);
+       for (as = user_list; as != NULL; as = as->next) {
+               as->suspend_wait = 0;
+               as->suspend_result = (ret ? 0 : -EIO);
+       }
+       wake_up_interruptible(&apm_suspend_waitqueue);
+       return ret;
 }
 
 static void standby(void)
@@ -806,15 +909,14 @@ static apm_event_t get_event(void)
        return 0;
 }
 
-static int send_event(apm_event_t event, apm_event_t undo,
-                      struct apm_bios_struct *sender)
+static int send_event(apm_event_t event, struct apm_user *sender)
 {
        switch (event) {
        case APM_SYS_SUSPEND:
        case APM_CRITICAL_SUSPEND:
        case APM_USER_SUSPEND:
                /* map all suspends to ACPI D3 */
-               if (pm_send_request(PM_SUSPEND, (void*) 3)) {
+               if (pm_send_request(PM_SUSPEND, (void *)3)) {
                        if (apm_bios_info.version > 0x100)
                                apm_set_power_state(APM_STATE_REJECT);
                        return 0;
@@ -823,11 +925,7 @@ static int send_event(apm_event_t event, apm_event_t undo,
        case APM_NORMAL_RESUME:
        case APM_CRITICAL_RESUME:
                /* map all resumes to ACPI D0 */
-               if (pm_send_request(PM_RESUME, 0)) {
-                       if (apm_bios_info.version > 0x100)
-                               apm_set_power_state(APM_STATE_REJECT);
-                       return 0;
-               }
+               (void) pm_send_request(PM_RESUME, (void *)0);
                break;
        }
 
@@ -864,7 +962,7 @@ static void check_events(void)
                        if (waiting_for_resume)
                                break;
 #endif
-                       if (send_event(event, APM_STANDBY_RESUME, NULL)) {
+                       if (send_event(event, NULL)) {
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                                waiting_for_resume = 1;
 #endif
@@ -888,12 +986,12 @@ static void check_events(void)
                        if (waiting_for_resume)
                                break;
 #endif
-                       if (send_event(event, APM_NORMAL_RESUME, NULL)) {
+                       if (send_event(event, NULL)) {
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                                waiting_for_resume = 1;
 #endif
                                if (suspends_pending <= 0)
-                                       suspend();
+                                       (void) suspend();
                        }
                        break;
 
@@ -908,13 +1006,13 @@ static void check_events(void)
                        ignore_bounce = 1;
 #endif
                        set_time();
-                       send_event(event, 0, NULL);
+                       send_event(event, NULL);
                        break;
 
                case APM_CAPABILITY_CHANGE:
                case APM_LOW_BATTERY:
                case APM_POWER_STATUS_CHANGE:
-                       send_event(event, 0, NULL);
+                       send_event(event, NULL);
                        break;
 
                case APM_UPDATE_TIME:
@@ -922,7 +1020,7 @@ static void check_events(void)
                        break;
 
                case APM_CRITICAL_SUSPEND:
-                       suspend();
+                       (void) suspend();
                        break;
                }
        }
@@ -930,18 +1028,18 @@ static void check_events(void)
 
 static void apm_event_handler(void)
 {
-       static int      pending_count = 0;
+       static int      pending_count = 4;
        int             err;
 
        if ((standbys_pending > 0) || (suspends_pending > 0)) {
-               if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
+               if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
                        pending_count = 4;
                        err = apm_set_power_state(APM_STATE_BUSY);
                        if (err)
                                apm_error("busy", err);
                }
        } else
-               pending_count = 0;
+               pending_count = 4;
        check_events();
 }
 
@@ -957,13 +1055,17 @@ static void apm_event_handler(void)
 static void apm_mainloop(void)
 {
        DECLARE_WAITQUEUE(wait, current);
-       apm_enabled = 1;
+
+       if (smp_num_cpus > 1)
+               return;
 
        add_wait_queue(&apm_waitqueue, &wait);
        current->state = TASK_INTERRUPTIBLE;
        for (;;) {
                /* Nothing to do, just sleep for the timeout */
                schedule_timeout(APM_CHECK_TIMEOUT);
+               if (exit_kapmd)
+                       break;
 
                /*
                 * Ok, check all events, check for idle (and mark us sleeping
@@ -976,11 +1078,11 @@ static void apm_mainloop(void)
                        continue;
                if (apm_do_idle()) {
                        unsigned long start = jiffies;
-                       do {
+                       while (system_idle()) {
                                apm_do_idle();
                                if (jiffies - start > APM_CHECK_TIMEOUT)
                                        break;
-                       } while (system_idle());
+                       }
                        apm_do_busy();
                        apm_event_handler();
                }
@@ -988,7 +1090,7 @@ static void apm_mainloop(void)
        }
 }
 
-static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
+static int check_apm_user(struct apm_user *as, const char *func)
 {
        if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
                printk(KERN_ERR "apm: %s passed bad filp", func);
@@ -999,13 +1101,13 @@ static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
 
 static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
 {
-       struct apm_bios_struct *        as;
+       struct apm_user *       as;
        int                     i;
        apm_event_t             event;
        DECLARE_WAITQUEUE(wait, current);
 
        as = fp->private_data;
-       if (check_apm_bios_struct(as, "read"))
+       if (check_apm_user(as, "read"))
                return -EIO;
        if (count < sizeof(apm_event_t))
                return -EINVAL;
@@ -1053,10 +1155,10 @@ repeat:
 
 static unsigned int do_poll(struct file *fp, poll_table * wait)
 {
-       struct apm_bios_struct * as;
+       struct apm_user * as;
 
        as = fp->private_data;
-       if (check_apm_bios_struct(as, "select"))
+       if (check_apm_user(as, "poll"))
                return 0;
        poll_wait(fp, &apm_waitqueue, wait);
        if (!queue_empty(as))
@@ -1067,11 +1169,11 @@ static unsigned int do_poll(struct file *fp, poll_table * wait)
 static int do_ioctl(struct inode * inode, struct file *filp,
                    u_int cmd, u_long arg)
 {
-       struct apm_bios_struct *        as;
-       int                             send_ok = 1;
+       struct apm_user *       as;
+       DECLARE_WAITQUEUE(wait, current);
 
        as = filp->private_data;
-       if (check_apm_bios_struct(as, "ioctl"))
+       if (check_apm_user(as, "ioctl"))
                return -EIO;
        if (!as->suser)
                return -EPERM;
@@ -1081,11 +1183,9 @@ static int do_ioctl(struct inode * inode, struct file *filp,
                        as->standbys_read--;
                        as->standbys_pending--;
                        standbys_pending--;
-               }
-               else
-                       send_ok = send_event(APM_USER_STANDBY,
-                                            APM_STANDBY_RESUME, as);
-               if (send_ok && (standbys_pending <= 0))
+               } else if (!send_event(APM_USER_STANDBY, as))
+                       return -EAGAIN;
+               if (standbys_pending <= 0)
                        standby();
                break;
        case APM_IOC_SUSPEND:
@@ -1093,12 +1193,25 @@ static int do_ioctl(struct inode * inode, struct file *filp,
                        as->suspends_read--;
                        as->suspends_pending--;
                        suspends_pending--;
+               } else if (!send_event(APM_USER_SUSPEND, as))
+                       return -EAGAIN;
+               if (suspends_pending <= 0) {
+                       if (!suspend())
+                               return -EIO;
+               } else {
+                       as->suspend_wait = 1;
+                       add_wait_queue(&apm_suspend_waitqueue, &wait);
+                       while (1) {
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               if ((as->suspend_wait == 0)
+                                   || signal_pending(current))
+                                       break;
+                               schedule();
+                       }
+                       current->state = TASK_RUNNING;
+                       remove_wait_queue(&apm_suspend_waitqueue, &wait);
+                       return as->suspend_result;
                }
-               else
-                       send_ok = send_event(APM_USER_SUSPEND,
-                                            APM_NORMAL_RESUME, as);
-               if (send_ok && (suspends_pending <= 0))
-                       suspend();
                break;
        default:
                return -EINVAL;
@@ -1108,10 +1221,10 @@ static int do_ioctl(struct inode * inode, struct file *filp,
 
 static int do_release(struct inode * inode, struct file * filp)
 {
-       struct apm_bios_struct *        as;
+       struct apm_user *       as;
 
        as = filp->private_data;
-       if (check_apm_bios_struct(as, "release"))
+       if (check_apm_user(as, "release"))
                return 0;
        filp->private_data = NULL;
        if (as->standbys_pending > 0) {
@@ -1122,12 +1235,12 @@ static int do_release(struct inode * inode, struct file * filp)
        if (as->suspends_pending > 0) {
                suspends_pending -= as->suspends_pending;
                if (suspends_pending <= 0)
-                       suspend();
+                       (void) suspend();
        }
        if (user_list == as)
                user_list = as->next;
        else {
-               struct apm_bios_struct *        as1;
+               struct apm_user *       as1;
 
                for (as1 = user_list;
                     (as1 != NULL) && (as1->next != as);
@@ -1139,17 +1252,21 @@ static int do_release(struct inode * inode, struct file * filp)
                        as1->next = as->next;
        }
        kfree_s(as, sizeof(*as));
+       MOD_DEC_USE_COUNT;
        return 0;
 }
 
 static int do_open(struct inode * inode, struct file * filp)
 {
-       struct apm_bios_struct *        as;
+       struct apm_user *       as;
 
-       as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
+       MOD_INC_USE_COUNT;
+
+       as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
        if (as == NULL) {
                printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
                       sizeof(*as));
+               MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
        as->magic = APM_BIOS_MAGIC;
@@ -1184,11 +1301,10 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
        int             time_units     = -1;
        char            *units         = "?";
 
-       if (!apm_enabled)
-               return 0;
        p = buf;
 
-       if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
+       if ((smp_num_cpus == 1) &&
+           !(error = apm_get_power_status(&bx, &cx, &dx))) {
                ac_line_status = (bx >> 8) & 0xff;
                battery_status = bx & 0xff;
                if ((cx & 0xff) != 0xff)
@@ -1264,6 +1380,11 @@ static int apm(void *unused)
        char *          power_stat;
        char *          bat_stat;
 
+       kapmd_running = 1;
+
+       exit_files(current);    /* daemonize doesn't do exit_files */
+       daemonize();
+
        strcpy(current->comm, "kapmd");
        sigfillset(&current->blocked);
 
@@ -1278,7 +1399,7 @@ static int apm(void *unused)
                        apm_bios_info.version = 0x100;
                }
        }
-       if (debug) {
+       if (debug && (smp_num_cpus == 1)) {
                printk(KERN_INFO "apm: Connection version %d.%d\n",
                        (apm_bios_info.version >> 8) & 0xff,
                        apm_bios_info.version & 0xff);
@@ -1328,32 +1449,51 @@ static int apm(void *unused)
                 * is booted with PM disabled but not in the docking station.
                 * Unfortunate ...
                 */
-               error = apm_enable_power_management();
+               error = apm_enable_power_management(1);
                if (error) {
                        apm_error("enable power management", error);
                        return -1;
                }
        }
 #endif
-       if (((apm_bios_info.flags & APM_BIOS_DISENGAGED) == 0)
+       if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
            && (apm_bios_info.version > 0x0100)) {
-               if (apm_engage_power_management(0x0001) == APM_SUCCESS)
-                       apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+               error = apm_engage_power_management(APM_DEVICE_ALL, 1);
+               if (error) {
+                       apm_error("engage power management", error);
+                       return -1;
+               }
        }
 
        /* Install our power off handler.. */
-       if (power_off_enabled)
+       if (power_off)
                pm_power_off = apm_power_off;
 #ifdef CONFIG_MAGIC_SYSRQ
        sysrq_power_off = apm_power_off;
 #endif
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-       console_blank_hook = apm_console_blank;
+       if (smp_num_cpus == 1)
+               console_blank_hook = apm_console_blank;
 #endif
 
        pm_active = 1;
 
        apm_mainloop();
+
+       pm_active = 0;
+
+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
+       if (smp_num_cpus == 1)
+               console_blank_hook = NULL;
+#endif
+#ifdef CONFIG_MAGIC_SYSRQ
+       sysrq_power_off = NULL;
+#endif
+       if (power_off)
+               pm_power_off = NULL;
+
+       kapmd_running = 0;
+
        return 0;
 }
 
@@ -1371,10 +1511,9 @@ static int __init apm_setup(char *str)
                        str += 3;
                if (strncmp(str, "debug", 5) == 0)
                        debug = !invert;
-               if (strncmp(str, "power-off", 9) == 0)
-                       power_off_enabled = !invert;
-               if (strncmp(str, "smp-power-off", 13) == 0)
-                       smp_hack = !invert;
+               if ((strncmp(str, "power-off", 9) == 0) ||
+                   (strncmp(str, "power_off", 9) == 0))
+                       power_off = !invert;
                str = strchr(str, ',');
                if (str != NULL)
                        str += strspn(str, ", \t");
@@ -1455,7 +1594,10 @@ static int __init apm_init(void)
                printk(KERN_NOTICE "apm: disabled on user request.\n");
                APM_INIT_ERROR_RETURN;
        }
-
+       if ((smp_num_cpus > 1) && !power_off) {
+               printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+               APM_INIT_ERROR_RETURN;
+       }
        if (PM_IS_ACTIVE()) {
                printk(KERN_NOTICE "apm: overridden by ACPI.\n");
                APM_INIT_ERROR_RETURN;
@@ -1472,9 +1614,6 @@ static int __init apm_init(void)
        _set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
 
        apm_bios_entry.offset = apm_bios_info.offset;
-#ifdef CONFIG_APM_BAD_ENTRY_OFFSET
-       apm_bios_entry.offset &= 0xffff;
-#endif
        apm_bios_entry.segment = APM_CS;
        set_base(gdt[APM_CS >> 3],
                 __va((unsigned long)apm_bios_info.cseg << 4));
@@ -1483,18 +1622,16 @@ static int __init apm_init(void)
        set_base(gdt[APM_DS >> 3],
                 __va((unsigned long)apm_bios_info.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
-       if (apm_bios_info.version == 0x100)
+       if (apm_bios_info.version == 0x100) {
 #endif
-       {
                /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
                _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
                /* For some unknown machine. */
                _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
                /* For the DEC Hinote Ultra CT475 (and others?) */
                _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
-       }
 #ifndef APM_RELAX_SEGMENTS
-       else {
+       else {
                _set_limit((char *)&gdt[APM_CS >> 3],
                        (apm_bios_info.cseg_len - 1) & 0xffff);
                _set_limit((char *)&gdt[APM_CS_16 >> 3],
@@ -1504,21 +1641,36 @@ static int __init apm_init(void)
        }
 #endif
 
-#ifdef CONFIG_SMP
+       create_proc_info_entry("apm", 0, NULL, apm_get_info);
+
+       kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+
        if (smp_num_cpus > 1) {
-               printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
-               if (smp_hack)
-                       smp_hack = 2;
+               printk(KERN_NOTICE
+                  "apm: disabled - APM is not SMP safe (power off active).\n");
                APM_INIT_ERROR_RETURN;
        }
-#endif
-
-       create_proc_info_entry("apm", 0, 0, apm_get_info);
 
        misc_register(&apm_device);
 
-       kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
        return 0;
 }
 
-__initcall(apm_init);
+static void __exit apm_exit(void)
+{
+       misc_deregister(&apm_device);
+       remove_proc_entry("apm", NULL);
+       exit_kapmd = 1;
+       while (kapmd_running)
+               schedule();
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Enable debug mode");
+
+EXPORT_NO_SYMBOLS;
index f58e7485f110baf234beb6d55da0fa61853755c2..cad6ceb1734da4b80550ed73d8247c430e299584 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/smp_lock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
+#include <linux/apm_bios.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -20,6 +21,7 @@
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/mmx.h>
+#include <asm/desc.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
@@ -34,6 +36,8 @@ extern struct drive_info_struct drive_info;
 EXPORT_SYMBOL(drive_info);
 #endif
 
+extern unsigned long get_cmos_time(void);
+
 /* platform dependent support */
 EXPORT_SYMBOL(boot_cpu_data);
 EXPORT_SYMBOL(EISA_bus);
@@ -51,6 +55,9 @@ EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(pm_idle);
 EXPORT_SYMBOL(pm_power_off);
+EXPORT_SYMBOL(get_cmos_time);
+EXPORT_SYMBOL(apm_bios_info);
+EXPORT_SYMBOL(gdt);
 
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
index dc9a69ea6e7736b6d8c2449aae66c3957da777ca..a0a4ab85141ddd249b90e255b82004c81f9a88de 100644 (file)
@@ -1,6 +1,6 @@
 /*  Generic MTRR (Memory Type Range Register) driver.
 
-    Copyright (C) 1997-1999  Richard Gooch
+    Copyright (C) 1997-2000  Richard Gooch
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
                success.
     19991008   Manfred Spraul <manfreds@colorfullife.com>
               replaced spin_lock_reschedule() with a normal semaphore.
+  v1.36
+    20000221   Richard Gooch <rgooch@atnf.csiro.au>
+               Compile fix if procfs and devfs not enabled.
+              Formatting changes.
 */
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/hardirq.h>
 #include <linux/irq.h>
 
-#define MTRR_VERSION            "1.35 (19990512)"
+#define MTRR_VERSION            "1.36 (20000221)"
 
 #define TRUE  1
 #define FALSE 0
@@ -484,8 +488,9 @@ static void intel_get_mtrr (unsigned int reg, unsigned long *base,
     unsigned long dummy, mask_lo, base_lo;
 
     rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy);
-    if ((mask_lo & 0x800) == 0) {
-       /* Invalid (i.e. free) range. */
+    if ( (mask_lo & 0x800) == 0 )
+    {
+       /*  Invalid (i.e. free) range  */
        *base = 0;
        *size = 0;
        *type = 0;
@@ -541,22 +546,26 @@ static void cyrix_get_arr (unsigned int reg, unsigned long *base,
       *size = 0;
 
     /* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */
-    if (reg < 7) {
-      switch (rcr) {
-       case  1: *type = MTRR_TYPE_UNCACHABLE; break;
-       case  8: *type = MTRR_TYPE_WRBACK;     break;
-       case  9: *type = MTRR_TYPE_WRCOMB;     break;
-       case 24:
-       default: *type = MTRR_TYPE_WRTHROUGH;  break;
-      }
-    } else {
-      switch (rcr) {
-       case  0: *type = MTRR_TYPE_UNCACHABLE; break;
-       case  8: *type = MTRR_TYPE_WRCOMB;     break;
-       case  9: *type = MTRR_TYPE_WRBACK;     break;
-       case 25:
-       default: *type = MTRR_TYPE_WRTHROUGH;  break;
-      }
+    if (reg < 7)
+    {
+       switch (rcr)
+       {
+         case  1: *type = MTRR_TYPE_UNCACHABLE; break;
+         case  8: *type = MTRR_TYPE_WRBACK;     break;
+         case  9: *type = MTRR_TYPE_WRCOMB;     break;
+         case 24:
+         default: *type = MTRR_TYPE_WRTHROUGH;  break;
+       }
+    } else
+    {
+       switch (rcr)
+       {
+         case  0: *type = MTRR_TYPE_UNCACHABLE; break;
+         case  8: *type = MTRR_TYPE_WRCOMB;     break;
+         case  9: *type = MTRR_TYPE_WRBACK;     break;
+         case 25:
+         default: *type = MTRR_TYPE_WRTHROUGH;  break;
+       }
     }
 }   /*  End Function cyrix_get_arr  */
 
@@ -657,20 +666,24 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
     size &= 0x7fff; /* make sure arr_size <= 14 */
     for(arr_size = 0; size; arr_size++, size >>= 1);
 
-    if (reg<7) {
-      switch (type) {
-       case MTRR_TYPE_UNCACHABLE:      arr_type =  1; break;
-       case MTRR_TYPE_WRCOMB:          arr_type =  9; break;
-       case MTRR_TYPE_WRTHROUGH:       arr_type = 24; break;
-       default:                        arr_type =  8; break;
-      }
-    } else {
-      switch (type) {
-       case MTRR_TYPE_UNCACHABLE:      arr_type =  0; break;
-       case MTRR_TYPE_WRCOMB:          arr_type =  8; break;
-       case MTRR_TYPE_WRTHROUGH:       arr_type = 25; break;
-       default:                        arr_type =  9; break;
-      }
+    if (reg<7)
+    {
+       switch (type) {
+         case MTRR_TYPE_UNCACHABLE:    arr_type =  1; break;
+         case MTRR_TYPE_WRCOMB:                arr_type =  9; break;
+         case MTRR_TYPE_WRTHROUGH:     arr_type = 24; break;
+         default:                      arr_type =  8; break;
+       }
+    }
+    else
+    {
+       switch (type)
+       {
+         case MTRR_TYPE_UNCACHABLE:    arr_type =  0; break;
+         case MTRR_TYPE_WRCOMB:                arr_type =  8; break;
+         case MTRR_TYPE_WRTHROUGH:     arr_type = 25; break;
+         default:                      arr_type =  9; break;
+       }
     }
 
     if (do_safe) set_mtrr_prepare (&ctxt);
@@ -783,16 +796,18 @@ static int __init set_mtrr_var_range_testing (unsigned int index,
     int changed = FALSE;
 
     rdmsr(MTRRphysBase_MSR(index), lo, hi);
-    if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
-       || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) {
-       wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
+    if ( (vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
+        || (vr->base_hi & 0xfUL) != (hi & 0xfUL) )
+    {
+       wrmsr (MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
        changed = TRUE;
     }
 
-    rdmsr(MTRRphysMask_MSR(index), lo, hi);
+    rdmsr (MTRRphysMask_MSR(index), lo, hi);
 
-    if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
-       || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) {
+    if ( (vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
+        || (vr->mask_hi & 0xfUL) != (hi & 0xfUL) )
+    {
        wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
        changed = TRUE;
     }
@@ -820,22 +835,27 @@ static int __init set_fixed_ranges_testing(mtrr_type *frs)
     unsigned long lo, hi;
 
     rdmsr(MTRRfix64K_00000_MSR, lo, hi);
-    if (p[0] != lo || p[1] != hi) {
-       wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
+    if (p[0] != lo || p[1] != hi)
+    {
+       wrmsr (MTRRfix64K_00000_MSR, p[0], p[1]);
        changed = TRUE;
     }
 
-    for (i = 0; i < 2; i++) {
-       rdmsr(MTRRfix16K_80000_MSR + i, lo, hi);
-       if (p[2 + i*2] != lo || p[3 + i*2] != hi) {
-           wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i*2], p[3 + i*2]);
+    for (i = 0; i < 2; i++)
+    {
+       rdmsr (MTRRfix16K_80000_MSR + i, lo, hi);
+       if (p[2 + i*2] != lo || p[3 + i*2] != hi)
+       {
+           wrmsr (MTRRfix16K_80000_MSR + i, p[2 + i*2], p[3 + i*2]);
            changed = TRUE;
        }
     }
 
-    for (i = 0; i < 8; i++) {
-       rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi);
-       if (p[6 + i*2] != lo || p[7 + i*2] != hi) {
+    for (i = 0; i < 8; i++)
+    {
+       rdmsr (MTRRfix4K_C0000_MSR + i, lo, hi);
+       if (p[6 + i*2] != lo || p[7 + i*2] != hi)
+       {
            wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]);
            changed = TRUE;
        }
@@ -903,8 +923,8 @@ static unsigned long __init set_mtrr_state (struct mtrr_state *state,
        change_mask |= MTRR_CHANGE_MASK_FIXED;
     /*  Set_mtrr_restore restores the old value of MTRRdefType,
        so to set it we fiddle with the saved value  */
-    if ((ctxt->deftype_lo & 0xff) != state->def_type
-       || ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled)
+    if ( (ctxt->deftype_lo & 0xff) != state->def_type
+        || ( (ctxt->deftype_lo & 0xc00) >> 10 ) != state->enabled)
     {
        ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
        change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
@@ -1057,11 +1077,14 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
     unsigned long lbase, lsize;
 
     /* If we are to set up a region >32M then look at ARR7 immediately */
-    if (size > 0x2000000UL) {
+    if (size > 0x2000000UL)
+    {
        cyrix_get_arr (7, &lbase, &lsize, &ltype);
        if (lsize < 1) return 7;
-    /* else try ARR0-ARR6 first */
-    } else {
+       /*  Else try ARR0-ARR6 first  */
+    }
+    else
+    {
        for (i = 0; i < 7; i++)
        {
            cyrix_get_arr (i, &lbase, &lsize, &ltype);
@@ -1099,29 +1122,32 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
-       if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
-         /* Apply the K6 block alignment and size rules
+       if (boot_cpu_data.x86 < 6)
+       {   /* pre-Athlon CPUs */
+           /* Apply the K6 block alignment and size rules
             In order
                o Uncached or gathering only
                o 128K or bigger block
                o Power of 2 block
                o base suitably aligned to the power
            */
-         if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
-             (size & ~(size-1))-size || (base & (size-1)))
-             return -EINVAL;
+           if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+                (size & ~(size-1))-size || ( base & (size-1) ) )
+               return -EINVAL;
          break;
-       } /* else fall through */
+       }
+       /*  Else fall through  */
       case X86_VENDOR_INTEL:
-       /*  Double check for Intel, we may run on Athlon. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
-         /*  For Intel PPro stepping <= 7, must be 4 MiB aligned  */
-         if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
-              (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
-         {
-             printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
-             return -EINVAL;
-         }
+       /*  Double check for Intel, we may run on Athlon  */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+       {
+           /*  For Intel PPro stepping <= 7, must be 4 MiB aligned  */
+           if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
+                (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) -1 ) ) )
+           {
+               printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+               return -EINVAL;
+           }
        }
        /*  Fall through  */
       case X86_VENDOR_CYRIX:
@@ -1236,7 +1262,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
 
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
     max = get_num_var_ranges ();
-    down(&main_lock);
+    down (&main_lock);
     if (reg < 0)
     {
        /*  Search for existing MTRR  */
@@ -1258,15 +1284,15 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
     }
     if (reg >= max)
     {
-       up(&main_lock);
+       up (&main_lock);
        printk ("mtrr: register: %d too big\n", reg);
        return -EINVAL;
     }
     if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX)
     {
-       if ((reg == 3) && arr3_protected)
+       if ( (reg == 3) && arr3_protected )
        {
-           up(&main_lock);
+           up (&main_lock);
            printk ("mtrr: ARR3 cannot be changed\n");
            return -EINVAL;
        }
@@ -1274,19 +1300,19 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
     (*get_mtrr) (reg, &lbase, &lsize, &ltype);
     if (lsize < 1)
     {
-       up(&main_lock);
+       up (&main_lock);
        printk ("mtrr: MTRR %d not used\n", reg);
        return -EINVAL;
     }
     if (usage_table[reg] < 1)
     {
-       up(&main_lock);
+       up (&main_lock);
        printk ("mtrr: reg: %d has count=0\n", reg);
        return -EINVAL;
     }
     if (--usage_table[reg] < 1) set_mtrr (reg, 0, 0, 0);
     compute_ascii ();
-    up(&main_lock);
+    up (&main_lock);
     return reg;
 }   /*  End Function mtrr_del  */
 
@@ -1473,16 +1499,17 @@ static int mtrr_close (struct inode *ino, struct file *file)
 
 static struct file_operations mtrr_fops =
 {
-        read:          mtrr_read,
-        write:         mtrr_write,
-        ioctl:         mtrr_ioctl,
-        release:       mtrr_close,
+    read:      mtrr_read,
+    write:     mtrr_write,
+    ioctl:     mtrr_ioctl,
+    release:   mtrr_close,
 };
 
 #  ifdef CONFIG_PROC_FS
 
-static struct inode_operations proc_mtrr_inode_operations = {
-       &mtrr_fops,             /* default property file-ops */
+static struct inode_operations proc_mtrr_inode_operations =
+{
+    &mtrr_fops,             /* default property file-ops */
 };
 
 static struct proc_dir_entry *proc_root_mtrr;
@@ -1538,15 +1565,17 @@ EXPORT_SYMBOL(mtrr_del);
 
 #ifdef __SMP__
 
-typedef struct {
-  unsigned long base;
-  unsigned long size;
-  mtrr_type type;
+typedef struct
+{
+    unsigned long base;
+    unsigned long size;
+    mtrr_type type;
 } arr_state_t;
 
-arr_state_t arr_state[8] __initdata = {
-  {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},
-  {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}
+arr_state_t arr_state[8] __initdata =
+{
+    {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},
+    {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}
 };
 
 unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
@@ -1604,31 +1633,35 @@ static void __init cyrix_arr_init(void)
     ccr[5] = getCx86 (CX86_CCR5);
     ccr[6] = getCx86 (CX86_CCR6);
 
-    if (ccr[3] & 1) {
-      ccrc[3] = 1;
-      arr3_protected = 1;
-    } else {
-      /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
-       * access to SMM memory through ARR3 (bit 7).
-       */
-      if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
-      if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
-      if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
-      arr3_protected = 0;
-      if (ccr[6] & 0x02) {
-        ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3. */
-        setCx86 (CX86_CCR6, ccr[6]);
-      }
-      /* Disable ARR3. This is safe now that we disabled SMM. */
-      /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
+    if (ccr[3] & 1)
+    {
+       ccrc[3] = 1;
+       arr3_protected = 1;
+    }
+    else
+    {
+       /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
+        * access to SMM memory through ARR3 (bit 7).
+        */
+       if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
+       if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
+       if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
+       arr3_protected = 0;
+       if (ccr[6] & 0x02) {
+           ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3 */
+           setCx86 (CX86_CCR6, ccr[6]);
+       }
+       /* Disable ARR3. This is safe now that we disabled SMM. */
+       /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
     }
     /* If we changed CCR1 in memory, change it in the processor, too. */
     if (ccrc[1]) setCx86 (CX86_CCR1, ccr[1]);
 
     /* Enable ARR usage by the processor */
-    if (!(ccr[5] & 0x20)) {
-      ccr[5] |= 0x20; ccrc[5] = 1;
-      setCx86 (CX86_CCR5, ccr[5]);
+    if (!(ccr[5] & 0x20))
+    {
+       ccr[5] |= 0x20; ccrc[5] = 1;
+       setCx86 (CX86_CCR5, ccr[5]);
     }
 
 #ifdef __SMP__
@@ -1680,11 +1713,14 @@ static void __init mtrr_setup(void)
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
-       if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
-         get_mtrr = amd_get_mtrr;
-         set_mtrr_up = amd_set_mtrr_up;
-         break;
-       } /* else fall through */
+       if (boot_cpu_data.x86 < 6)
+       {
+           /* pre-Athlon CPUs */
+           get_mtrr = amd_get_mtrr;
+           set_mtrr_up = amd_set_mtrr_up;
+           break;
+       }
+       /*   Else fall through  */
       case X86_VENDOR_INTEL:
        get_mtrr = intel_get_mtrr;
        set_mtrr_up = intel_set_mtrr_up;
@@ -1713,7 +1749,7 @@ void __init mtrr_init_boot_cpu(void)
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
-       if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
+       if (boot_cpu_data.x86 < 6) break;  /*  Pre-Athlon CPUs  */
       case X86_VENDOR_INTEL:
        get_mtrr_state (&smp_mtrr_state);
        break;
@@ -1751,7 +1787,7 @@ void __init mtrr_init_secondary_cpu(void)
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
-       /* Just for robustness: pre-Athlon CPUs cannot do SMP. */
+       /*  Just for robustness: pre-Athlon CPUs cannot do SMP  */
        if (boot_cpu_data.x86 < 6) break;
       case X86_VENDOR_INTEL:
        intel_mtrr_init_secondary_cpu ();
@@ -1775,17 +1811,17 @@ void __init mtrr_init_secondary_cpu(void)
 int __init mtrr_init(void)
 {
     if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
-#  ifdef __SMP__
+#ifdef __SMP__
     switch (boot_cpu_data.x86_vendor)
     {
       case X86_VENDOR_AMD:
-       if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
+       if (boot_cpu_data.x86 < 6) break;  /*  Pre-Athlon CPUs  */
       case X86_VENDOR_INTEL:
        finalize_mtrr_state (&smp_mtrr_state);
        mtrr_state_warn (smp_changes_mask);
        break;
     }
-#  else /* __SMP__ */
+#else  /*  __SMP__  */
     mtrr_setup ();
     switch (boot_cpu_data.x86_vendor)
     {
@@ -1796,15 +1832,17 @@ int __init mtrr_init(void)
         centaur_mcr_init ();
         break;
     }
-#  endif  /*  !__SMP__  */
+#endif  /*  !__SMP__  */
 
-#  ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
     proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
     proc_root_mtrr->ops = &proc_mtrr_inode_operations;
-#endif    
+#endif
+#ifdev CONFIG_DEVFS_FS
     devfs_handle = devfs_register (NULL, "cpu/mtrr", 0, DEVFS_FL_DEFAULT, 0, 0,
                                   S_IFREG | S_IRUGO | S_IWUSR, 0, 0,
                                   &mtrr_fops, NULL);
+#endif
     init_table ();
     return 0;
 }   /*  End Function mtrr_init  */
index c38e383e7d8b73333af14446d1a01d0862d0827c..0f61ca5431a669cc35b601ab2d896c901fadbcdc 100644 (file)
@@ -48,16 +48,6 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int hlt_counter=0;
 
-void disable_hlt(void)
-{
-       hlt_counter++;
-}
-
-void enable_hlt(void)
-{
-       hlt_counter--;
-}
-
 /*
  * Powermanagement idle function, if any..
  */
@@ -68,6 +58,16 @@ void (*pm_idle)(void) = NULL;
  */
 void (*pm_power_off)(void) = NULL;
 
+void disable_hlt(void)
+{
+       hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+       hlt_counter--;
+}
+
 /*
  * We use this if we don't have any better
  * idle routine..
@@ -293,7 +293,7 @@ void machine_real_restart(unsigned char *code, int length)
 
 void machine_restart(char * __unused)
 {
-#if __SMP__
+#if CONFIG_SMP
        /*
         * Stop all CPUs and turn off local APICs and the IO-APIC, so
         * other OSs see a clean IRQ state.
index 6aebbfcc848f97d6a18adf9b101c0f045d940c33..bee2a55740b719bf176fc9b29fd2fc093c018378 100644 (file)
@@ -226,9 +226,9 @@ if [ "$CONFIG_NET" = "y" ]; then
       if [ "$CONFIG_PCI" = "y" ]; then
         tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
         tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
-        tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+        tristate 'RealTek RTL-8139 support' CONFIG_8139TOO
         tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
-        tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+        tristate 'EtherExpressPro/100 support' CONFIG_EEPRO100
         tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
       fi
       endmenu
index f5dadb42a18712b8e39d336e2e2a8025fff0cf93..5bb994ed8c58432ee933354fff7180fbd9ce2637 100644 (file)
@@ -1236,4 +1236,5 @@ EXPORT_SYMBOL(blk_init_queue);
 EXPORT_SYMBOL(blk_cleanup_queue);
 EXPORT_SYMBOL(blk_queue_headactive);
 EXPORT_SYMBOL(blk_queue_pluggable);
+EXPORT_SYMBOL(blk_queue_make_request);
 EXPORT_SYMBOL(generic_make_request);
index ab47b380e9523f059e630f738e9665f184c99ce8..3209aa46b95fc6abdf8794c6158214d3ccf899bf 100644 (file)
@@ -377,13 +377,13 @@ done:
        spin_lock_irq(&io_request_lock);
        current_request->sector += current_request->current_nr_sectors;
        current_request->nr_sectors -= current_request->current_nr_sectors;
-       list_add(&current_request->queue, &current_request->q->queue_head);
+       list_add(&current_request->queue, &q->queue_head);
        end_request(1);
        goto repeat;
 error_out_lock:
        spin_lock_irq(&io_request_lock);
 error_out:
-       list_add(&current_request->queue, &current_request->q->queue_head);
+       list_add(&current_request->queue, &q->queue_head);
        end_request(0);
        goto repeat;
 }
index 6671f83e8db6c58ff63831ee82e531b3a24bf4cc..057be0d64226d13a3818f875967d2632a8ce8878 100644 (file)
@@ -211,7 +211,11 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh)
        while (!( /* FIXME: now we are rather fault tolerant than nice */
        r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL)
        ) )
+       {
                printk ("raid1_make_request(#1): out of memory\n");
+               current->policy |= SCHED_YIELD;
+               schedule();
+       }
        memset (r1_bh, 0, sizeof (struct raid1_bh));
 
 /*
@@ -298,7 +302,11 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh)
                while (!( /* FIXME: now we are rather fault tolerant than nice */
                mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL)
                ) )
+               {
                        printk ("raid1_make_request(#2): out of memory\n");
+                       current->policy |= SCHED_YIELD;
+                       schedule();
+               }
                memset (mirror_bh[i], 0, sizeof (struct buffer_head));
 
        /*
@@ -710,7 +718,11 @@ static int raid1_run (int minor, struct md_dev *mddev)
        while (!( /* FIXME: now we are rather fault tolerant than nice */
        mddev->private = kmalloc (sizeof (struct raid1_data), GFP_KERNEL)
        ) )
+       {
                printk ("raid1_run(): out of memory\n");
+               current->policy |= SCHED_YIELD;
+               schedule();
+       }
        raid_conf = mddev->private;
        memset(raid_conf, 0, sizeof(*raid_conf));
 
index bde31a4ba49132f7ea54bb99c184d06605b8b8e8..22f46b337c9597306abc09ccfc9220038ad288e4 100644 (file)
@@ -36,7 +36,7 @@ obj-y  += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs     :=     busmouse.o console.o i2c-old.o keyboard.o \
+export-objs     :=     busmouse.o console.o i2c-old.o keyboard.o sysrq.o \
                        misc.o pty.o random.o selection.o serial.o videodev.o \
                        tty_io.o
 
@@ -144,13 +144,14 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
 obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
 obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o
 obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
-obj-$(CONFIG_ADBMOUSE) += adbmouse.o
+obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o
 obj-$(CONFIG_PC110_PAD) += pc110pad.o
 obj-$(CONFIG_WDT) += wdt.o
 obj-$(CONFIG_RTC) += rtc.o
 ifeq ($(CONFIG_PPC),)
   obj-$(CONFIG_NVRAM) += nvram.o
 endif
+obj-$(CONFIG_I810_RNG) += i810_rng.o
 
 obj-$(CONFIG_VIDEO_DEV) += videodev.o
 
index e8a87dd8d3a0b2369ca8c1062fef434eb659105b..a1c9f3cf39ff62c2761b37713083e79cb43fef1f 100644 (file)
@@ -2931,6 +2931,7 @@ EXPORT_SYMBOL(video_font_height);
 EXPORT_SYMBOL(video_scan_lines);
 EXPORT_SYMBOL(vc_resize);
 EXPORT_SYMBOL(fg_console);
+EXPORT_SYMBOL(console_blank_hook);
 
 #ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
index 99b157833210e04ab3c5891f01bdae210293259f..0583923d943663aa3e8fb529846b141b5e5df006 100644 (file)
@@ -260,7 +260,7 @@ static void h8_intr(int irq, void *dev_id, struct pt_regs *regs)
                return;
            } else if (data_reg == H8_SYNC_BYTE) {
                h8_state = H8_IDLE;
-               if (!QUEUE_EMPTY(&h8_actq, link))
+               if (!QUEUE_IS_EMPTY(&h8_actq, link))
                    h8_send_next_cmd_byte();
            } else {
                Dprintk ("h8_intr: resync unknown data 0x%x \n", data_reg);
@@ -279,7 +279,7 @@ static void h8_intr(int irq, void *dev_id, struct pt_regs *regs)
                    QUEUE_REMOVE(&h8_actq, qp, link);
                    h8_cmd_done (qp);
                    /* More commands to send over? */
-                   if (!QUEUE_EMPTY(&h8_cmdq, link))
+                   if (!QUEUE_IS_EMPTY(&h8_cmdq, link))
                        h8_start_new_cmd();
                }
                return;
@@ -458,7 +458,7 @@ h8_q_cmd(u_char *cmd, int cmd_size, int resp_size)
 
         /* get cmd buf */
        save_flags(flags); cli();
-        while (QUEUE_EMPTY(&h8_freeq, link)) {
+        while (QUEUE_IS_EMPTY(&h8_freeq, link)) {
                 Dprintk("H8: need to allocate more cmd buffers\n");
                 restore_flags(flags);
                 h8_alloc_queues();
@@ -500,13 +500,13 @@ h8_start_new_cmd(void)
                 return;
         }
 
-        if (!QUEUE_EMPTY(&h8_actq, link)) {
+        if (!QUEUE_IS_EMPTY(&h8_actq, link)) {
                 Dprintk("h8_start_new_cmd: inconsistency: IDLE with non-empty active queue!\n");
                 restore_flags(flags);
                 return;
         }
 
-        if (QUEUE_EMPTY(&h8_cmdq, link)) {
+        if (QUEUE_IS_EMPTY(&h8_cmdq, link)) {
                 Dprintk("h8_start_new_cmd: no command to dequeue\n");
                 restore_flags(flags);
                 return;
index 854c6131c4b8b38f800f14fec49db1db31c52156..cfd0f2e82f86fba59bbd3b5425403c4516808a66 100644 (file)
@@ -738,12 +738,6 @@ int js_register_device(struct js_port *port, int number, int axes, int buttons,
 
        curd->name = all += axes * sizeof(struct js_corr);
        strcpy(curd->name, name);
-       sprintf (devfs_name, "analogue%d", number);
-       curd->devfs_handle = devfs_register (devfs_handle, devfs_name, 0,
-                                            DEVFS_FL_DEFAULT,
-                                            JOYSTICK_MAJOR, number,
-                                            S_IFCHR | S_IRUGO | S_IWUSR, 0, 0,
-                                            &js_fops, NULL);
 
        port->devs[number] = curd;
        port->axes[number] = curd->new.axes;
@@ -757,6 +751,13 @@ int js_register_device(struct js_port *port, int number, int axes, int buttons,
 
        spin_unlock_irqrestore(&js_lock, flags);        
 
+       sprintf(devfs_name, "js%d", i);
+       curd->devfs_handle = devfs_register(devfs_handle, devfs_name, 0,
+                                           DEVFS_FL_DEFAULT,
+                                           JOYSTICK_MAJOR, i,
+                                           S_IFCHR | S_IRUGO | S_IWUSR, 0, 0,
+                                           &js_fops, NULL);
+
        return i;
 }
 
@@ -772,7 +773,7 @@ void js_unregister_device(struct js_dev *dev)
 
        spin_unlock_irqrestore(&js_lock, flags);        
 
-       devfs_unregister (dev->devfs_handle);
+       devfs_unregister(dev->devfs_handle);
        kfree(dev);
 }
 
@@ -805,7 +806,7 @@ int __init js_init(void)
                printk(KERN_ERR "js: unable to get major %d for joystick\n", JOYSTICK_MAJOR);
                return -EBUSY;
        }
-       devfs_handle = devfs_mk_dir (NULL, "joysticks", 9, NULL);
+       devfs_handle = devfs_mk_dir(NULL, "joysticks", 9, NULL);
 
        printk(KERN_INFO "js: Joystick driver v%d.%d.%d (c) 1999 Vojtech Pavlik <vojtech@suse.cz>\n",
                JS_VERSION >> 16 & 0xff, JS_VERSION >> 8 & 0xff, JS_VERSION & 0xff);
@@ -885,9 +886,9 @@ int __init js_init(void)
 void cleanup_module(void)
 {
        del_timer(&js_timer);
-       devfs_unregister (devfs_handle);
+       devfs_unregister(devfs_handle);
        if (devfs_unregister_chrdev(JOYSTICK_MAJOR, "js"))
-       printk(KERN_ERR "js: can't unregister device\n");
+               printk(KERN_ERR "js: can't unregister device\n");
 }
 #endif
 
index 340ecb7dda21c0edef148ba08541996ebd1919f9..18fa8c6452df5fa968c44236ad2df1a27ed2d51a 100644 (file)
@@ -751,6 +751,8 @@ static struct file_operations       stl_fsiomem = {
 
 /*****************************************************************************/
 
+static devfs_handle_t devfs_handle = NULL;
+
 #ifdef MODULE
 
 /*
@@ -775,8 +777,6 @@ int init_module()
 
 /*****************************************************************************/
 
-static devfs_handle_t devfs_handle = NULL;
-
 void cleanup_module()
 {
        stlbrd_t        *brdp;
index 6fece94702eaf799b9ef8b79f3bc6986b2679c5a..7fcbfbb527f4fe3d8342823d4fe1b5733a6186f4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kbd_kern.h>
 #include <linux/quotaops.h>
 #include <linux/smp_lock.h>
+#include <linux/module.h>
 
 #include <asm/ptrace.h>
 
@@ -32,6 +33,8 @@ extern struct vfsmount *vfsmntlist;
 /* Machine specific power off function */
 void (*sysrq_power_off)(void) = NULL;
 
+EXPORT_SYMBOL(sysrq_power_off);
+
 /* Send a signal to all user processes */
 
 static void send_sig_all(int sig, int even_init)
index 8c1c9a71923e9c6fb6236625c4c808926678cecf..1da60703e1f33834319d52db163cbde01be958d9 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/console.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 
 #undef attr
 #undef org
@@ -176,71 +177,58 @@ vcs_read(struct file *file, char *buf, size_t count, loff_t *ppos)
                                con_buf0[1] = (char) video_num_columns;
                                getconsxy(currcons, con_buf0 + 2);
 
-                               tmp_count = HEADER_SIZE - p;
+                               con_buf_start += p;
+                               this_round += p;
+                               if (this_round > CON_BUF_SIZE) {
+                                       this_round = CON_BUF_SIZE;
+                                       orig_count = this_round - p;
+                               }
+
+                               tmp_count = HEADER_SIZE;
                                if (tmp_count > this_round)
                                        tmp_count = this_round;
 
                                /* Advance state pointers and move on. */
                                this_round -= tmp_count;
-                               con_buf_start += p;
-                               orig_count -= p;
-                               p += tmp_count;
-                               con_buf0 = con_buf + p;
+                               p = HEADER_SIZE;
+                               con_buf0 = con_buf + HEADER_SIZE;
+                               /* If this_round >= 0, then p is even... */
+                       } else if (p & 1) {
+                               /* Skip first byte for output if start address is odd
+                                * Update region sizes up/down depending on free
+                                * space in buffer.
+                                */
+                               con_buf_start++;
+                               if (this_round < CON_BUF_SIZE)
+                                       this_round++;
+                               else
+                                       orig_count--;
                        }
-                       p -= HEADER_SIZE;
-                       col = (p/2) % maxcol;
                        if (this_round > 0) {
-                               char tmp_byte;
-
-                               org = screen_pos(currcons, p/2, viewed);
-                               if ((p & 1) && this_round > 0) {
-#ifdef __BIG_ENDIAN
-                                       tmp_byte = vcs_scr_readw(currcons, org++) & 0xff;
-#else
-                                       tmp_byte = vcs_scr_readw(currcons, org++) >> 8;
-#endif
-
-                                       *con_buf0++ = tmp_byte;
+                               unsigned short *tmp_buf = (unsigned short *)con_buf0;
 
-                                       this_round--;   
-                                       p++;
-                                       if (++col == maxcol) {
-                                               org = screen_pos(currcons, p/2, viewed);
-                                               col = 0;
-                                       }
-                               }
+                               p -= HEADER_SIZE;
                                p /= 2;
+                               col = p % maxcol;
+
+                               org = screen_pos(currcons, p, viewed);
                                p += maxcol - col;
-                       }
 
-                       if (this_round > 1) {
-                               size_t tmp_count = this_round;
-                               unsigned short *tmp_buf = (unsigned short *)con_buf0;
+                               /* Buffer has even length, so we can always copy
+                                * character + attribute. We do not copy last byte
+                                * to userspace if this_round is odd.
+                                */
+                               this_round = (this_round + 1) >> 1;
 
-                               while (tmp_count > 1) {
+                               while (this_round) {
                                        *tmp_buf++ = vcs_scr_readw(currcons, org++);
-                                       tmp_count -= 2;
+                                       this_round --;
                                        if (++col == maxcol) {
                                                org = screen_pos(currcons, p, viewed);
                                                col = 0;
                                                p += maxcol;
                                        }
                                }
-
-                               /* Advance pointers, and move on. */
-                               this_round = tmp_count;
-                               con_buf0 = (char*)tmp_buf;
-                       }
-                       if (this_round > 0) {
-                               char tmp_byte;
-
-#ifdef __BIG_ENDIAN
-                               tmp_byte = vcs_scr_readw(currcons, org) >> 8;
-#else
-                               tmp_byte = vcs_scr_readw(currcons, org) & 0xff;
-#endif
-
-                               *con_buf0++ = tmp_byte;
                        }
                }
 
@@ -416,7 +404,7 @@ vcs_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
                        while (this_round > 1) {
                                unsigned short w;
 
-                               w = *((const unsigned short *)con_buf0);
+                               w = get_unaligned(((const unsigned short *)con_buf0));
                                vcs_scr_writew(currcons, w, org++);
                                con_buf0 += 2;
                                this_round -= 2;
index 1ac6a9595c2b5e7ca15382c07ae75406fe45012e..9a9951204769ef193b01b3d5b4e3ff7c09ecfc1c 100644 (file)
 static struct hpsb_host_template *templates = NULL;
 spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
 
-
-/*
- * The following function is exported for module usage.  It will
- * be called from high-level drivers such as the raw driver.
- */
-int hpsb_get_host_list(struct hpsb_host *list[], int list_size)
-{
-    struct hpsb_host *host, **ptr;
-    struct hpsb_host_template *tmpl;
-    int count=0;
-
-    ptr = list;
-
-    for (tmpl = templates ; tmpl != NULL; tmpl = tmpl->next) {
-        for (host = tmpl->hosts; (host != NULL) && (count < list_size); 
-             host = host->next) {
-            *ptr = host;
-            ptr++;
-            count++;
-        }
-    }
-
-    return count;
-}
-
 /*
  * This function calls the add_host/remove_host hooks for every host currently
  * registered.  Init == TRUE means add_host.
@@ -131,7 +106,7 @@ struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl,
         h->timeout_tq.data = h;
 
         h->topology_map = h->csr.topology_map + 3;
-        h->speed_map = h->csr.speed_map + 2;
+        h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
         h->template = tmpl;
         if (hd_size) {
index d516e7f8c8839cebf40afce4d68178cca66ed2a8..3465f27d73ab27708c7212d013a0e0e57e096a48 100644 (file)
@@ -27,7 +27,8 @@ struct hpsb_host {
         wait_queue_head_t tlabel_wait;
 
         int reset_retries;
-        quadlet_t *topology_map, *speed_map;
+        quadlet_t *topology_map;
+        u8 *speed_map;
         struct csr_control csr;
 
         unsigned char iso_listen_count[64];
@@ -173,14 +174,6 @@ void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl);
 struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl, 
                                 size_t hostdata_size);
 
-/*
- * Write pointers to all available hpsb_hosts into list.
- * Return number of host adapters (i.e. elements in list).
- *
- * DEPRECATED - register with highlevel instead.
- */
-int hpsb_get_host_list(struct hpsb_host *list[], int max_list_size);
-
 /*
  * Increase / decrease host usage counter.  Increase function will return true
  * only if successful (host still existed).  Decrease function expects host to
index eccbe893301ee80aeae0af7c8728c82d80906277..771189f0b37e3111592879007226f2d3a4cf0840 100644 (file)
@@ -4,7 +4,7 @@
  * Core support: hpsb_packet management, packet handling and forwarding to
  *               csr or lowlevel code
  *
- * Copyright (C) 1999 Andreas E. Bombe
+ * Copyright (C) 1999, 2000 Andreas E. Bombe
  */
 
 #include <linux/kernel.h>
@@ -191,6 +191,74 @@ static int check_selfids(struct hpsb_host *host, unsigned int num_of_selfids)
         return nodeid + 1;
 }
 
+static void build_speed_map(struct hpsb_host *host, int nodecount)
+{
+        char speedcap[nodecount];
+        char cldcnt[nodecount];
+        u8 *map = host->speed_map;
+        quadlet_t *sidp;
+        int i, j, n;
+
+        for (i = 0; i < (nodecount * 64); i += 64) {
+                for (j = 0; j < nodecount; j++) {
+                        map[i+j] = SPEED_400;
+                }
+        }
+
+        for (i = 0; i < nodecount; i++) {
+                cldcnt[i] = 0;
+        }
+
+        /* find direct children count and speed */
+        for (sidp = &host->topology_map[host->selfid_count-1],
+                     n = nodecount - 1;
+             sidp >= host->topology_map; sidp--) {
+                if (*sidp & 0x00800000 /* extended */) {
+                        for (i = 2; i < 18; i += 2) {
+                                if ((*sidp & (0x3 << i)) == (0x3 << i)) {
+                                        cldcnt[n]++;
+                                }
+                        }
+                } else {
+                        for (i = 2; i < 8; i += 2) {
+                                if ((*sidp & (0x3 << i)) == (0x3 << i)) {
+                                        cldcnt[n]++;
+                                }
+                        }
+                        speedcap[n] = (*sidp >> 14) & 0x3;
+                        n--;
+                }
+        }
+
+        /* set self mapping */
+        for (i = nodecount - 1; i; i--) {
+                map[64*i + i] = speedcap[i];
+        }
+
+        /* fix up direct children count to total children count;
+         * also fix up speedcaps for sibling and parent communication */
+        for (i = 1; i < nodecount; i++) {
+                for (j = cldcnt[i], n = i - 1; j > 0; j--) {
+                        cldcnt[i] += cldcnt[n];
+                        speedcap[n] = MIN(speedcap[n], speedcap[i]);
+                        n -= cldcnt[n] + 1;
+                }
+        }
+
+        for (n = 0; n < nodecount; n++) {
+                for (i = n - cldcnt[n]; i <= n; i++) {
+                        for (j = 0; j < (n - cldcnt[n]); j++) {
+                                map[j*64 + i] = map[i*64 + j] =
+                                        MIN(map[i*64 + j], speedcap[n]);
+                        }
+                        for (j = n + 1; j < nodecount; j++) {
+                                map[j*64 + i] = map[i*64 + j] =
+                                        MIN(map[i*64 + j], speedcap[n]);
+                        }
+                }
+        }
+}
+
 void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
 {
         if (host->in_bus_reset) {
@@ -204,8 +272,6 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
 
 void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
 {
-        
-
         host->node_id = 0xffc0 | phyid;
         host->in_bus_reset = 0;
         host->is_root = isroot;
@@ -219,9 +285,11 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
                         return;
                 } else {
                         HPSB_NOTICE("stopping out-of-control reset loop");
-                        HPSB_NOTICE("warning - topology map will therefore not "
-                                    "be valid");
+                        HPSB_NOTICE("warning - topology map and speed map will "
+                                    "therefore not be valid");
                 }
+        } else {
+                build_speed_map(host, host->node_count);
         }
 
         /* irm_id is kept up to date by check_selfids() */
@@ -275,8 +343,22 @@ int hpsb_send_packet(struct hpsb_packet *packet)
         }
 
         packet->state = queued;
+        packet->speed_code = host->speed_map[(host->node_id & NODE_MASK) * 64
+                                            + (packet->node_id & NODE_MASK)];
 
-        dump_packet("send packet:", packet->header, packet->header_size);
+        switch (packet->speed_code) {
+        case 2:
+                dump_packet("send packet 400:", packet->header,
+                            packet->header_size);
+                break;
+        case 1:
+                dump_packet("send packet 200:", packet->header,
+                            packet->header_size);
+                break;
+        default:
+                dump_packet("send packet 100:", packet->header,
+                            packet->header_size);
+        }
 
         return host->template->transmit_packet(host, packet);
 }
index ee4bde182d7ecb7cf2c114a6cb157308758e9162..3a99b09238b092eaac86022fb3f581a861d92a41 100644 (file)
@@ -19,7 +19,6 @@
 EXPORT_SYMBOL(hpsb_register_lowlevel);
 EXPORT_SYMBOL(hpsb_unregister_lowlevel);
 EXPORT_SYMBOL(hpsb_get_host);
-EXPORT_SYMBOL(hpsb_get_host_list);
 EXPORT_SYMBOL(hpsb_inc_host_usage);
 EXPORT_SYMBOL(hpsb_dec_host_usage);
 
@@ -53,8 +52,3 @@ EXPORT_SYMBOL(highlevel_read);
 EXPORT_SYMBOL(highlevel_write);
 EXPORT_SYMBOL(highlevel_lock);
 EXPORT_SYMBOL(highlevel_lock64);
-
-/*
-EXPORT_SYMBOL(hpsb_dispatch_event);
-EXPORT_SYMBOL(hpsb_reg_event_handler);
-*/
index 4da40f6c43b0c9f3292a4b4152829cb9037c1acc..b8fae7ee274e2ccb5e962d15399152841e505683 100644 (file)
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+/*
+ * Things known to be working:
+ * . Async Request Transmit
+ * . Async Response Receive
+ * . Async Request Receive
+ * . Async Response Transmit
+ * . Iso Receive
+ * 
+ * Things not implemented:
+ * . Iso Transmit
+ * . DMA to user's space in iso receive mode
+ * . DMA error recovery
+ *
+ * Things to be fixed:
+ * . Config ROM
+ *
+ * Known bugs:
+ * . Self-id are not received properly if card 
+ *   is initialized with no other nodes on the
+ *   bus.
+ */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/tqueue.h>
 
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "ohci1394.h"
 
+#ifdef DBGMSG
+#undef DBGMSG
+#endif
+
+#if OHCI1394_DEBUG
+#define DBGMSG(card, fmt, args...) \
+printk(KERN_INFO "ohci1394_%d: " fmt "\n" , card , ## args)
+#else
+#define DBGMSG(card, fmt, args...)
+#endif
+
 /* print general (card independent) information */
 #define PRINT_G(level, fmt, args...) \
 printk(level "ohci1394: " fmt "\n" , ## args)
@@ -49,11 +90,18 @@ printk(level "ohci1394: " fmt "\n" , ## args)
 #define PRINT(level, card, fmt, args...) \
 printk(level "ohci1394_%d: " fmt "\n" , card , ## args)
 
+#define FAIL(fmt, args...) \
+       PRINT_G(KERN_ERR, fmt , ## args); \
+         num_of_cards--; \
+           remove_card(ohci); \
+             return 1;
+
 int supported_chips[][2] = {
-    { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394 },
-    { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_2 },
-    { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_OHCI1394 },
-    { -1, -1 }
+       { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394 },
+       { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_2 },
+       { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_OHCI1394 },
+       { PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_SONY_CXD3222 },
+       { -1, -1 }
 };
 
 static struct ti_ohci cards[MAX_OHCI1394_CARDS];
@@ -62,6 +110,8 @@ static int num_of_cards = 0;
 static int add_card(struct pci_dev *dev);
 static void remove_card(struct ti_ohci *ohci);
 static int init_driver(void);
+static void dma_trm_bh(void *data);
+static void dma_trm_reset(struct dma_trm_ctx *d);
 
 /***********************************
  * IEEE-1394 functionality section *
@@ -87,7 +137,7 @@ static int get_phy_reg(struct ti_ohci *ohci, int addr)
 
        /* wait */
        while (!(reg_read(ohci, OHCI1394_PhyControl)&0x80000000) && timeout)
-         timeout--;
+               timeout--;
 
 
        if (!timeout) {
@@ -120,7 +170,7 @@ static int set_phy_reg(struct ti_ohci *ohci, int addr, unsigned char data) {
 
        /* wait */
        while (!(reg_read(ohci, OHCI1394_PhyControl)&0x80000000) && timeout)
-         timeout--;
+               timeout--;
 
        spin_unlock(&ohci->phy_reg_lock);
 
@@ -150,31 +200,34 @@ inline static int handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
        if ((self_id_count&0x80000000) || 
            ((self_id_count&0x00FF0000) != (q[0]&0x00FF0000))) {
                PRINT(KERN_ERR, ohci->id, 
-                     "Error in reception of self-id packets");
+                     "Error in reception of self-id packets"
+                     "Self-id count: %08x q[0]: %08x",
+                     self_id_count, q[0]);
                return -1;
-       }    
-
+       }
+       
        size = ((self_id_count&0x0000EFFC)>>2) - 1;
        q++;
 
        while (size > 0) {
                if (q[0] == ~q[1]) {
-                       printk("-%d- selfid packet 0x%x rcvd\n", 
-                              ohci->id, q[0]);
+                       PRINT(KERN_INFO, ohci->id, "selfid packet 0x%x rcvd", 
+                             q[0]);
                        hpsb_selfid_received(host, q[0]);
                        if (((q[0]&0x3f000000)>>24)==phyid) {
                                lsid=q[0];
-                               printk("This node self-id is 0x%08x\n",lsid);
+                               PRINT(KERN_INFO, ohci->id, 
+                                     "This node self-id is 0x%08x", lsid);
                        }
                } else {
-                       printk("-%d- inconsistent selfid 0x%x/0x%x\n", ohci->id,
-                              q[0], q[1]);
+                       PRINT(KERN_ERR, ohci->id,
+                             "inconsistent selfid 0x%x/0x%x", q[0], q[1]);
                }
                q += 2;
                size -= 2;
        }
 
-       printk(" calling self-id complete\n");
+       PRINT(KERN_INFO, ohci->id, "calling self-id complete");
 
        hpsb_selfid_complete(host, phyid, isroot);
        return 0;
@@ -206,7 +259,7 @@ static int ohci_soft_reset(struct ti_ohci *ohci) {
        reg_write(ohci, OHCI1394_HCControlSet, 0x00010000);
   
        while ((reg_read(ohci, OHCI1394_HCControlSet)&0x00010000) && timeout) 
-         timeout--;
+               timeout--;
        if (!timeout) {
                PRINT(KERN_ERR, ohci->id, "soft reset timeout !!!");
                return -EFAULT;
@@ -215,6 +268,108 @@ static int ohci_soft_reset(struct ti_ohci *ohci) {
        return 0;
 }
 
+static int run_context(struct ti_ohci *ohci, int reg, char *msg)
+{
+       u32 nodeId;
+
+       /* check that the node id is valid */
+       nodeId = reg_read(ohci, OHCI1394_NodeID);
+       if (!(nodeId&0x80000000)) {
+               PRINT(KERN_ERR, ohci->id, 
+                     "Running dma failed because Node ID not valid");
+               return -1;
+       }
+
+       /* check that the node number != 63 */
+       if ((nodeId&0x3f)==63) {
+               PRINT(KERN_ERR, ohci->id, 
+                     "Running dma failed because Node ID == 63");
+               return -1;
+       }
+       
+       /* Run the dma context */
+       reg_write(ohci, reg, 0x8000);
+       
+       if (msg) PRINT(KERN_INFO, ohci->id, "%s", msg);
+       
+       return 0;
+}
+
+static void stop_context(struct ti_ohci *ohci, int reg, char *msg)
+{
+       int i=0;
+
+       /* stop the channel program if it's still running */
+       reg_write(ohci, reg, 0x8000);
+   
+       /* Wait until it effectively stops */
+       while (reg_read(ohci, reg) & 0x400) {
+               i++;
+               if (i>5000) {
+                       PRINT(KERN_ERR, ohci->id, 
+                             "runaway loop while stopping context...");
+                       break;
+               }
+       }
+       if (msg) PRINT(KERN_ERR, ohci->id, "%s\n dma prg stopped\n", msg);
+}
+
+/* Generate the dma receive prgs and start the context */
+static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
+{
+       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
+       int i;
+
+       stop_context(ohci, d->ctrlClear, NULL);
+
+       for (i=0; i<d->num_desc; i++) {
+               
+               /* end of descriptor list? */
+               if ((i+1) < d->num_desc) {
+                       d->prg[i]->control = (0x283C << 16) | d->buf_size;
+                       d->prg[i]->branchAddress =
+                               (virt_to_bus(d->prg[i+1]) & 0xfffffff0) | 0x1;
+               } else {
+                       d->prg[i]->control = (0x283C << 16) | d->buf_size;
+                       d->prg[i]->branchAddress =
+                               (virt_to_bus(d->prg[0]) & 0xfffffff0);
+               }
+
+               d->prg[i]->address = virt_to_bus(d->buf[i]);
+               d->prg[i]->status = d->buf_size;
+       }
+
+        d->buf_ind = 0;
+        d->buf_offset = 0;
+
+       /* Tell the controller where the first AR program is */
+       reg_write(ohci, d->cmdPtr, virt_to_bus(d->prg[0]) | 0x1);
+
+       /* Run AR context */
+       reg_write(ohci, d->ctrlSet, 0x00008000);
+
+       PRINT(KERN_INFO, ohci->id, "Receive DMA ctx=%d initialized", d->ctx);
+}
+
+/* Initialize the dma transmit context */
+static void initialize_dma_trm_ctx(struct dma_trm_ctx *d)
+{
+       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
+
+       /* Stop the context */
+       stop_context(ohci, d->ctrlClear, NULL);
+
+        d->prg_ind = 0;
+       d->sent_ind = 0;
+       d->free_prgs = d->num_desc;
+        d->branchAddrPtr = NULL;
+       d->first = NULL;
+       d->last = NULL;
+
+       PRINT(KERN_INFO, ohci->id, "AT dma ctx=%d initialized", d->ctx);
+}
+
+/* Global initialization */
 static int ohci_initialize(struct hpsb_host *host)
 {
        struct ti_ohci *ohci=host->hostdata;
@@ -255,109 +410,64 @@ static int ohci_initialize(struct hpsb_host *host)
        reg_write(ohci, OHCI1394_ConfigROMmap, 
                  virt_to_bus(ohci->csr_config_rom));
 
-#if 1                          /* Why is this step necessary ? */
        /* Write the config ROM header */
-       reg_write(ohci, OHCI1394_ConfigROMhdr,0x04040000);
+       reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->csr_config_rom[0]);
 
        /* Set bus options */
-       reg_write(ohci, OHCI1394_BusOptions, 0xf064A002);
-#endif
+       reg_write(ohci, OHCI1394_BusOptions, ohci->csr_config_rom[2]);
 
-#if 1
-       /* Accept phy packets into AR request context */ 
-       reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
-#endif
+       /* Write the GUID into the csr config rom */
+       ohci->csr_config_rom[3] = reg_read(ohci, OHCI1394_GUIDHi);
+       ohci->csr_config_rom[4] = reg_read(ohci, OHCI1394_GUIDLo);
+       
+       /* Don't accept phy packets into AR request context */ 
+       reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
 
        /* Enable link */
        reg_write(ohci, OHCI1394_HCControlSet, 0x00020000);
 
        /* Initialize IR dma */
+       for (i=0;i<4;i++) { /* FIXME : how many contexts are available ? */
+               reg_write(ohci, OHCI1394_IrRcvContextControlClear+32*i,
+                         0xffffffff);
+               reg_write(ohci, OHCI1394_IrRcvContextMatch+32*i, 0);
+               reg_write(ohci, OHCI1394_IrRcvCommandPtr+32*i, 0);
+       }
 
-       /* make sure the context isn't running, dead, or active */
-       if (!(reg_read(ohci, OHCI1394_IrRcvContextControlSet) & 0x00008F00)) {
-
-                /* initialize IR program */
-                for (i= 0; i < IR_NUM_DESC; i++) {
-
-                       /* end of descriptor list? */
-                        if ((i + 1) < IR_NUM_DESC) {
-                                ohci->IR_recv_prg[i]->control=
-                                        (0x283C << 16) | IR_RECV_BUF_SIZE;
-                                ohci->IR_recv_prg[i]->branchAddress=
-                                        (virt_to_bus(ohci->IR_recv_prg[i + 1])
-                                         & 0xfffffff0) | 0x1;
-                        } else {
-                                ohci->IR_recv_prg[i]->control=
-                                        (0x283C << 16) | IR_RECV_BUF_SIZE;
-                                ohci->IR_recv_prg[i]->branchAddress=
-                                        (virt_to_bus(ohci->IR_recv_prg[0])
-                                         & 0xfffffff0) | 0x1;
-                        }
-
-                        ohci->IR_recv_prg[i]->address=
-                                virt_to_bus(ohci->IR_recv_buf[i]);
-                        ohci->IR_recv_prg[i]->status= IR_RECV_BUF_SIZE;
-               }
-
-               /* Tell the controller where the first IR program is */
-               reg_write(ohci, OHCI1394_IrRcvCommandPtr,
-                         virt_to_bus(ohci->IR_recv_prg[0]) | 0x1 );
-
-               /* Set bufferFill, isochHeader, multichannel for IR context */
-               reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000);
+       /* Set bufferFill, isochHeader, multichannel for IR context */
+       reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000);
+                       
+       /* Set the context match register to match on all tags */
+       reg_write(ohci, OHCI1394_IrRcvContextMatch, 0xf0000000);
 
-               /* Set the context match register to match on all tags */
-               reg_write(ohci, OHCI1394_IrRcvContextMatch, 0xf0000000);
+       /* Clear the multi channel mask high and low registers */
+       reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
 
-               /* Clear the multi channel mask high and low registers */
-               reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
+       /* Clear the interrupt mask */
+       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
 
-                /* Set up isoRecvIntMask to generate interrupts for context 0
-                   (thanks to Michael Greger for seeing that I forgot this) */
-                reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001);
+       /* Set up isoRecvIntMask to generate interrupts for context 0
+          (thanks to Michael Greger for seeing that I forgot this) */
+       reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001);
 
-               /* Run IR context */
-               reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0x00008000);
-       }
+       initialize_dma_rcv_ctx(ohci->ir_context);
 
        /* Initialize AR dma */
-       /* make sure the context isn't running, dead, or active */
-       if (!(reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x00008F00)) {
-
-                /* initialize AR program */
-                for (i= 0; i < AR_RESP_NUM_DESC; i++) {
-
-                       /* end of descriptor list? */
-                        if ((i + 1) < AR_RESP_NUM_DESC) {
-                                ohci->AR_resp_prg[i]->control=
-                                 (0x283C << 16) | AR_RESP_BUF_SIZE;
-                                ohci->AR_resp_prg[i]->branchAddress=
-                                 (virt_to_bus(ohci->AR_resp_prg[i + 1])
-                                         & 0xfffffff0) | 0x1;
-                        } else {
-                                ohci->AR_resp_prg[i]->control=
-                                        (0x283C << 16) | AR_RESP_BUF_SIZE;
-                                ohci->AR_resp_prg[i]->branchAddress=
-                                        (virt_to_bus(ohci->AR_resp_prg[0])
-                                         & 0xfffffff0) | 0x1;
-                        }
-
-                        ohci->AR_resp_prg[i]->address=
-                                virt_to_bus(ohci->AR_resp_buf[i]);
-                        ohci->AR_resp_prg[i]->status= AR_RESP_BUF_SIZE;
-               }
+       initialize_dma_rcv_ctx(ohci->ar_req_context);
+       initialize_dma_rcv_ctx(ohci->ar_resp_context);
 
-               /* Tell the controller where the first AR program is */
-               reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
-                         virt_to_bus(ohci->AR_resp_prg[0]) | 0x1 );
+       /* Initialize AT dma */
+       initialize_dma_trm_ctx(ohci->at_req_context);
+       initialize_dma_trm_ctx(ohci->at_resp_context);
 
-               /* Accept phy packets into AR request context */
-               reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
-
-               /* Run AR context */
-               reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x00008000);
-       }
+       /* 
+        * Accept AT requests from all nodes. This probably 
+        * will have to be controlled from the subsystem
+        * on a per node basis.
+        * (Tip by Emilie Chung <emilie.chung@axis.com>)
+        */
+       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
 
        /* Specify AT retries */
        reg_write(ohci, OHCI1394_ATRetries, 
@@ -384,7 +494,7 @@ static int ohci_initialize(struct hpsb_host *host)
                  OHCI1394_respTxComplete |
                  OHCI1394_reqTxComplete |
                  OHCI1394_isochRx
-                 );
+               );
 
        return 1;
 }
@@ -399,126 +509,144 @@ static void ohci_remove(struct hpsb_host *host)
        }
 }
 
-
-/* This must be called with the async_queue_lock held. */
-static void send_next_async(struct ti_ohci *ohci)
+/* Insert a packet in the AT DMA fifo and generate the DMA prg */
+static void insert_packet(struct ti_ohci *ohci,
+                         struct dma_trm_ctx *d, struct hpsb_packet *packet)
 {
-       int i=0;
-       struct hpsb_packet *packet = ohci->async_queue;
-       struct dma_cmd prg;
-#if 0
-       quadlet_t *ptr = (quadlet_t *)ohci->AT_req_prg;
-#endif
-       //HPSB_TRACE();
-
-        /* stop the channel program if it's still running */
-        reg_write(ohci, OHCI1394_AsReqTrContextControlClear, 0x8000);
-   
-        /* Wait until it effectively stops */
-        while (reg_read(ohci, OHCI1394_AsReqTrContextControlSet)
-               & 0x400) {
-                i++;
-                if (i>5000) {
-                        PRINT(KERN_ERR, ohci->id, 
-                              "runaway loop in DmaAT. bailing out...");
-                        break;
-                }
-        };
-
-        if (packet->type == async)
-        {
-
-                /* re-format packet header according to ohci specification */
-                packet->header[1] = (packet->header[1] & 0xFFFF) | 
-                        (packet->header[0] & 0xFFFF0000);
-                packet->header[0] = DMA_SPEED_200 |
-                        (packet->header[0] & 0xFFFF);
-
-                if (packet->data_size) { /* block transmit */
-                        prg.control = OUTPUT_MORE_IMMEDIATE | 0x10;
-                        prg.address = 0;
-                        prg.branchAddress = 0;
-                        prg.status = 0;
-                        memcpy(ohci->AT_req_prg, &prg, 16);
-                        memcpy(ohci->AT_req_prg + 1, packet->header, 16);
-                        prg.control = OUTPUT_LAST | packet->data_size;
-                        prg.address = virt_to_bus(packet->data);
-                        memcpy(ohci->AT_req_prg + 2, &prg, 16);
-
-                        reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
-                                  virt_to_bus(ohci->AT_req_prg)|0x3);
-                }
-                else { /* quadlet transmit */
-                        prg.control = OUTPUT_LAST_IMMEDIATE |
-                                packet->header_size;
-                        prg.address = 0;
-                        prg.branchAddress = 0;
-                        prg.status = 0;
-                        memcpy(ohci->AT_req_prg, &prg, 16);
-                        memcpy(ohci->AT_req_prg + 1, packet->header, 16);
-#if 0
-                        PRINT(KERN_INFO, ohci->id,
-                              "dma_cmd: %08x %08x %08x %08x",
-                              *ptr, *(ptr+1), *(ptr+2), *(ptr+3));
-                        PRINT(KERN_INFO, ohci->id,
-                              "header: %08x %08x %08x %08x",
-                              *(ptr+4), *(ptr+5), *(ptr+6), *(ptr+7));
-#endif
-                        reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
-                                  virt_to_bus(ohci->AT_req_prg)|0x2);
-                }
-
-        }
-        else if (packet->type == raw)
-        {
-                prg.control = OUTPUT_LAST | packet->data_size;
-                prg.address = virt_to_bus(packet->data);
-                prg.branchAddress = 0;
-                prg.status = 0;
-                memcpy(ohci->AT_req_prg, &prg, 16);
-#if 0
-                PRINT(KERN_INFO, ohci->id,
-                      "dma_cmd: %08x %08x %08x %08x",
-                      *ptr, *(ptr+1), *(ptr+2), *(ptr+3));
-#endif
-                reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
-                          virt_to_bus(ohci->AT_req_prg)|0x2);
-        }
+       u32 cycleTimer;
+       int idx = d->prg_ind;
+
+       d->prg[idx].begin.address = 0;
+       d->prg[idx].begin.branchAddress = 0;
+       if (d->ctx==1) {
+               /* 
+                * For response packets, we need to put a timeout value in
+                * the 16 lower bits of the status... let's try 1 sec timeout 
+                */ 
+               cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+               d->prg[idx].begin.status = 
+                       (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | 
+                       ((cycleTimer&0x01fff000)>>12);
+
+               DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x",
+                      cycleTimer, d->prg[idx].begin.status);
+       }
+       else 
+               d->prg[idx].begin.status = 0;
+
+       d->prg[idx].data[0] = packet->speed_code<<16 |
+               (packet->header[0] & 0xFFFF);
+       d->prg[idx].data[1] = (packet->header[1] & 0xFFFF) | 
+               (packet->header[0] & 0xFFFF0000);
+       d->prg[idx].data[2] = packet->header[2];
+       d->prg[idx].data[3] = packet->header[3];
+
+       if (packet->data_size) { /* block transmit */
+               d->prg[idx].begin.control = OUTPUT_MORE_IMMEDIATE | 0x10;
+               d->prg[idx].end.control = OUTPUT_LAST | packet->data_size;
+               d->prg[idx].end.address = virt_to_bus(packet->data);
+               d->prg[idx].end.branchAddress = 0;
+               d->prg[idx].end.status = 0x4000;
+               if (d->branchAddrPtr) 
+                       *(d->branchAddrPtr) = virt_to_bus(d->prg+idx) | 0x3;
+               d->branchAddrPtr = &(d->prg[idx].end.branchAddress);
+       }
+       else { /* quadlet transmit */
+               d->prg[idx].begin.control = 
+                       OUTPUT_LAST_IMMEDIATE | packet->header_size;
+               if (d->branchAddrPtr) 
+                       *(d->branchAddrPtr) = virt_to_bus(d->prg+idx) | 0x2;
+               d->branchAddrPtr = &(d->prg[idx].begin.branchAddress);
+       }
+       d->free_prgs--;
 
-       /* run program */
-       reg_write(ohci, OHCI1394_AsReqTrContextControlSet, 0x00008000);
+       /* queue the packet in the appropriate context queue */
+       if (d->last) {
+               d->last->xnext = packet;
+               d->last = packet;
+       }
+       else {
+               d->first = packet;
+               d->last = packet;
+       }
 }
 
 static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
 {
        struct ti_ohci *ohci = host->hostdata;
-       struct hpsb_packet *p;
-       unsigned long flags;
+       struct dma_trm_ctx *d;
+       unsigned char tcode;
+       int i=50;
 
        if (packet->data_size >= 4096) {
                PRINT(KERN_ERR, ohci->id, "transmit packet data too big (%d)",
                      packet->data_size);
                return 0;
        }
-
-       //HPSB_TRACE();
        packet->xnext = NULL;
-    
-       spin_lock_irqsave(&ohci->async_queue_lock, flags);
 
-       if (ohci->async_queue == NULL) {
-               ohci->async_queue = packet;
-               send_next_async(ohci);
-       } else {
-               p = ohci->async_queue;
-               while (p->xnext != NULL) {
-                       p = p->xnext;
+       /* Decide wether we have a request or a response packet */
+       tcode = (packet->header[0]>>4)&0xf;
+       if ((tcode==TCODE_READQ)||
+           (tcode==TCODE_WRITEQ)||
+           (tcode==TCODE_READB)||
+           (tcode==TCODE_WRITEB)||
+           (tcode==TCODE_LOCK_REQUEST))
+               d = ohci->at_req_context;
+
+       else if ((tcode==TCODE_WRITE_RESPONSE)||
+                (tcode==TCODE_READQ_RESPONSE)||
+                (tcode==TCODE_READB_RESPONSE)||
+                (tcode==TCODE_LOCK_RESPONSE)) 
+               d = ohci->at_resp_context;
+
+       else {
+               PRINT(KERN_ERR, ohci->id, 
+                     "Unexpected packet tcode=%d in AT DMA", tcode);
+               return 0;
+       }
+
+       spin_lock(&d->lock);
+
+       if (d->free_prgs<1) {
+               PRINT(KERN_INFO, ohci->id, 
+                     "AT DMA ctx=%d Running out of prgs... waiting",d->ctx);
+       }
+       while (d->free_prgs<1) {
+               spin_unlock(&d->lock);
+               schedule();
+               if (i-- <0) {
+                       stop_context(ohci, d->ctrlClear, 
+                                    "AT DMA runaway loop... bailing out");
+                       return 0;
                }
-               
-               p->xnext = packet;
+               spin_lock(&d->lock);
+       }
+
+       insert_packet(ohci, d, packet);
+
+       /* Is the context running ? (should be unless it is 
+          the first packet to be sent in this context) */
+       if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) {
+               DBGMSG(ohci->id,"Starting AT DMA ctx=%d",d->ctx);
+               if (packet->data_size) 
+                       reg_write(ohci, d->cmdPtr, 
+                                 virt_to_bus(&(d->prg[d->prg_ind])) | 0x3);
+               else 
+                       reg_write(ohci, d->cmdPtr, 
+                                 virt_to_bus(&(d->prg[d->prg_ind])) | 0x2);
+
+               run_context(ohci, d->ctrlSet, NULL);
+       }
+       else {
+               DBGMSG(ohci->id,"Waking AT DMA ctx=%d",d->ctx);
+               /* wake up the dma context if necessary */
+               if (!(reg_read(ohci, d->ctrlSet) & 0x400))
+                       reg_write(ohci, d->ctrlSet, 0x1000);
        }
-    
-       spin_unlock_irqrestore(&ohci->async_queue_lock, flags);
+
+       d->prg_ind = (d->prg_ind+1)%d->num_desc;
+       spin_unlock(&d->lock);
 
        return 1;
 }
@@ -528,31 +656,29 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
        struct ti_ohci *ohci = host->hostdata;
        int retval = 0;
        unsigned long flags;
-        struct hpsb_packet *packet, *lastpacket;
-       u32 r;
 
        switch (cmd) {
-             case RESET_BUS:
+       case RESET_BUS:
                PRINT(KERN_INFO, ohci->id, "resetting bus on request%s",
                      (host->attempt_root ? " and attempting to become root"
                       : ""));
-               r = (host->attempt_root) ? 0x000041ff : 0x0000417f;
-               reg_write(ohci, OHCI1394_PhyControl, r);
+               reg_write(ohci, OHCI1394_PhyControl, 
+                         (host->attempt_root) ? 0x000041ff : 0x0000417f);
                break;
 
-             case GET_CYCLE_COUNTER:
+       case GET_CYCLE_COUNTER:
                retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
                break;
        
-             case SET_CYCLE_COUNTER:
+       case SET_CYCLE_COUNTER:
                reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg);
                break;
        
-             case SET_BUS_ID:
+       case SET_BUS_ID:
                PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err");
                break;
 
-             case ACT_CYCLE_MASTER:
+       case ACT_CYCLE_MASTER:
 #if 0
                if (arg) {
                        /* enable cycleTimer, cycleMaster, cycleSource */
@@ -564,23 +690,13 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 #endif
                break;
 
-             case CANCEL_REQUESTS:
-               spin_lock_irqsave(&ohci->async_queue_lock, flags);
-               /* stop any chip activity */
-               reg_write(ohci, OHCI1394_HCControlClear, 0x00020000);
-                packet = ohci->async_queue;
-               ohci->async_queue = NULL;                
-               spin_unlock_irqrestore(&ohci->async_queue_lock, flags);
-
-                while (packet != NULL) {
-                        lastpacket = packet;
-                        packet = packet->xnext;
-                        hpsb_packet_sent(host, lastpacket, ACKX_ABORTED);
-                }
-
+       case CANCEL_REQUESTS:
+               DBGMSG(ohci->id, "Cancel request received");
+               dma_trm_reset(ohci->at_req_context);
+               dma_trm_reset(ohci->at_resp_context);
                break;
 
-              case MODIFY_USAGE:
+       case MODIFY_USAGE:
                 if (arg) {
                         MOD_INC_USE_COUNT;
                 } else {
@@ -588,7 +704,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                 }
                 break;
 
-              case ISO_LISTEN_CHANNEL:
+       case ISO_LISTEN_CHANNEL:
 
                 spin_lock_irqsave(&ohci->IR_channel_lock, flags);
 
@@ -614,7 +730,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
                 break;
 
-              case ISO_UNLISTEN_CHANNEL:
+       case ISO_UNLISTEN_CHANNEL:
 
                 spin_lock_irqsave(&ohci->IR_channel_lock, flags);
 
@@ -642,7 +758,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
                 break;
 
-             default:
+       default:
                PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet\n",
                        cmd);
                break;
@@ -659,160 +775,118 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
  * Global stuff (interrupt handler, init/shutdown code) *
  ********************************************************/
 
-static void stop_ar_resp_context(struct ti_ohci *ohci, char *msg)
+static void dma_trm_reset(struct dma_trm_ctx *d)
 {
-       int i=0;
+       struct ti_ohci *ohci;
 
-       /* stop the channel program if it's still running */
-       reg_write(ohci, OHCI1394_AsRspRcvContextControlClear, 0x8000);
-   
-       /* Wait until it effectively stops */
-       while (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) 
-              & 0x400) {
-               i++;
-               if (i>5000) {
-                       PRINT(KERN_ERR, ohci->id, 
-                             "runaway loop in Dma Ar Resp. bailing out...");
-                       break;
-               }
+       if (d==NULL) {
+               PRINT_G(KERN_ERR, "dma_trm_reset called with NULL arg");
+               return;
+       }
+       ohci = (struct ti_ohci *)(d->ohci);
+       stop_context(ohci, d->ctrlClear, NULL);
+
+       spin_lock(&d->lock);
+
+       /* is there still any packet pending ? */
+       while(d->first) {
+               PRINT(KERN_INFO, ohci->id, 
+                     "AT dma reset ctx=%d, aborting transmission", 
+                     d->ctx);
+               hpsb_packet_sent(ohci->host, d->first, ACKX_ABORTED);
+               d->first = d->first->xnext;
        }
-       PRINT(KERN_ERR, ohci->id, "%s\n async response receive dma stopped\n", msg);
+       d->first = d->last = NULL;
+       d->branchAddrPtr=NULL;
+       d->sent_ind = d->prg_ind;
+       d->free_prgs = d->num_desc;
+       spin_unlock(&d->lock);
 }
 
 static void ohci_irq_handler(int irq, void *dev_id,
                              struct pt_regs *regs_are_unused)
 {
-       //int i;
-       static quadlet_t event,node_id;
+       quadlet_t event,node_id;
        struct ti_ohci *ohci = (struct ti_ohci *)dev_id;
        struct hpsb_host *host = ohci->host;
        int phyid = -1, isroot = 0;
 
        event=reg_read(ohci, OHCI1394_IntEventSet);
 
-       /* Clear the interrupt register */
-       reg_write(ohci, OHCI1394_IntEventClear, event);
-
-       /* PRINT(KERN_INFO, ohci->id, "int event %08X mask %08X",
-          event,reg_read(ohci, OHCI1394_IntMaskSet)); */
-
        if (event & OHCI1394_busReset) {
-#if 0
-               PRINT(KERN_INFO, ohci->id, "bus reset interrupt");
-#endif
                if (!host->in_bus_reset) {
-                       hpsb_bus_reset(host);
+                       PRINT(KERN_INFO, ohci->id, "Bus reset");
+
+                       /* Wait for the AT fifo to be flushed */
+                       dma_trm_reset(ohci->at_req_context);
+                       dma_trm_reset(ohci->at_resp_context);
+
+                       /* Subsystem call */
+                       hpsb_bus_reset(ohci->host);
+
+                       ohci->NumBusResets++;
                }
-               ohci->NumBusResets++;
        }
-       if (event & OHCI1394_RQPkt) {
-               PRINT(KERN_INFO, ohci->id, "RQPkt int received");
+       /*
+        * Problem: How can I ensure that the AT bottom half will be
+        * executed before the AR bottom half (both events may have
+        * occured within a single irq event)
+        * Quick hack: just launch it within the IRQ handler
+        */
+       if (event & OHCI1394_reqTxComplete) { 
+               struct dma_trm_ctx *d = ohci->at_req_context;
+               DBGMSG(ohci->id, "Got reqTxComplete interrupt status=0x%08X",
+                      reg_read(ohci, d->ctrlSet));
+               if (reg_read(ohci, d->ctrlSet) & 0x800)
+                       stop_context(ohci, d->ctrlClear, "reqTxComplete");
+               else
+                       dma_trm_bh((void *)d);
+       }
+       if (event & OHCI1394_respTxComplete) { 
+               struct dma_trm_ctx *d = ohci->at_resp_context;
+               DBGMSG(ohci->id, "Got respTxComplete interrupt status=0x%08X",
+                      reg_read(ohci, d->ctrlSet));
+               if (reg_read(ohci, d->ctrlSet) & 0x800)
+                       stop_context(ohci, d->ctrlClear, "respTxComplete");
+               else
+                       dma_trm_bh((void *)d);
        }
        if (event & OHCI1394_RQPkt) {
-               PRINT(KERN_INFO, ohci->id, "ControlContext: %08X",
-                     reg_read(ohci, OHCI1394_AsReqRcvContextControlSet));
+               struct dma_rcv_ctx *d = ohci->ar_req_context;
+               DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X",
+                      reg_read(ohci, d->ctrlSet));
+               if (reg_read(ohci, d->ctrlSet) & 0x800)
+                       stop_context(ohci, d->ctrlClear, "RQPkt");
+               else {
+                       queue_task(&d->task, &tq_immediate);
+                       mark_bh(IMMEDIATE_BH);
+               }
        }
        if (event & OHCI1394_RSPkt) {
-               unsigned int idx,offset,rescount;
-
-                spin_lock(&ohci->AR_resp_lock);
-
-               idx = ohci->AR_resp_buf_th_ind;
-               offset = ohci->AR_resp_buf_th_offset;
-
-               rescount = ohci->AR_resp_prg[idx]->status&0xffff;
-               ohci->AR_resp_bytes_left +=  AR_RESP_BUF_SIZE - rescount - offset;
-               offset = AR_RESP_BUF_SIZE - rescount;
-
-               if (!rescount) { /* We cross a buffer boundary */
-                       idx = (idx+1) % AR_RESP_NUM_DESC;
-
-#if 0 
-                       /* This bit of code does not work */
-                       /* Let's see how many bytes were written in the async response 
-                          receive buf since last interrupt. This is done by finding 
-                          the next active context (See OHCI Spec p91) */
-                       while (ohci->AR_resp_bytes_left <= AR_RESP_TOTAL_BUF_SIZE) {
-                               if (ohci->AR_resp_prg[idx]->status&0x04000000) break;
-                               idx = (idx+1) % AR_RESP_NUM_DESC;
-                               PRINT(KERN_INFO,ohci->id,"crossing more than one buffer boundary !!!");
-                               ohci->AR_resp_bytes_left += AR_RESP_BUF_SIZE;
-                       }
-#endif 
-                       /* ASSUMPTION: only one buffer boundary is crossed */
-                       rescount = ohci->AR_resp_prg[idx]->status&0xffff;
-                       offset = AR_RESP_BUF_SIZE - rescount;
-                       ohci->AR_resp_bytes_left += offset;
-               }
-               if (offset==AR_RESP_BUF_SIZE) {
-                       offset=0;
-                       idx = (idx+1) % AR_RESP_NUM_DESC;
-               }
-               ohci->AR_resp_buf_th_ind = idx;
-               ohci->AR_resp_buf_th_offset = offset;
-
-                /* is buffer processing too slow? (all buffers used) */
-               if (ohci->AR_resp_bytes_left > AR_RESP_TOTAL_BUF_SIZE) {
-                       stop_ar_resp_context(ohci,"async response receive processing too slow");
-                        spin_unlock(&ohci->AR_resp_lock);
-                       return;
+               struct dma_rcv_ctx *d = ohci->ar_resp_context;
+               DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X",
+                      reg_read(ohci, d->ctrlSet));
+               if (reg_read(ohci, d->ctrlSet) & 0x800)
+                       stop_context(ohci, d->ctrlClear, "RSPkt");
+               else {
+                       queue_task(&d->task, &tq_immediate);
+                       mark_bh(IMMEDIATE_BH);
                }
-                spin_unlock(&ohci->AR_resp_lock);
-
-               /* queue bottom half in immediate queue */
-               queue_task(&ohci->AR_resp_pdl_task, &tq_immediate);
-               mark_bh(IMMEDIATE_BH);
        }
        if (event & OHCI1394_isochRx) {
                quadlet_t isoRecvIntEvent;
-
-               /* ASSUMPTION: We assume there is only one context for now. */
-
-                spin_lock(&ohci->IR_recv_lock);
-
-                /* Clear the isoRecvIntEvent register (very important!) */
-                isoRecvIntEvent= reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
+               struct dma_rcv_ctx *d = ohci->ir_context;
+                isoRecvIntEvent = reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
                reg_write(ohci, OHCI1394_IsoRecvIntEventClear,
                          isoRecvIntEvent);
-
-                ohci->IR_buf_used++;
-                ohci->IR_buf_next_ind=
-                        (ohci->IR_buf_next_ind + 1) % IR_NUM_DESC;
-
-                /* is buffer processing too slow? (all buffers used) */
-               if (ohci->IR_buf_next_ind == ohci->IR_buf_last_ind) {
-                        int i= 0;
-
-                        /* stop the context */
-                       reg_write(ohci,
-                                 OHCI1394_IrRcvContextControlClear, 0x8000);
-
-                       while (reg_read(ohci, OHCI1394_IrRcvContextControlSet) 
-                              & 0x400) {
-                               i++;
-
-                               if (i>5000) {
-                                       PRINT(KERN_ERR, ohci->id, "runaway loop in DmaIR. bailing out...");
-                                       break;
-                               }
-
-                       }
-
-                        spin_unlock(&ohci->IR_recv_lock);
-                       PRINT(KERN_ERR, ohci->id,
-                              "iso receive processing too slow... stopped");
-                       return;
+               DBGMSG(ohci->id, "Got reqTxComplete interrupt status=0x%08X",
+                      reg_read(ohci, d->ctrlSet));
+               if (reg_read(ohci, d->ctrlSet) & 0x800)
+                       stop_context(ohci, d->ctrlClear, "isochRx");
+               else {
+                       queue_task(&d->task, &tq_immediate);
+                       mark_bh(IMMEDIATE_BH);
                }
-
-                /* reset status field of next descriptor */
-                ohci->IR_recv_prg[ohci->IR_buf_next_ind]->status=
-                        IR_RECV_BUF_SIZE;
-
-                spin_unlock(&ohci->IR_recv_lock);
-
-               /* queue bottom half in immediate queue */
-               queue_task(&ohci->IR_pdl_task, &tq_immediate);
-               mark_bh(IMMEDIATE_BH);
        }
        if (event & OHCI1394_selfIDComplete) {
                if (host->in_bus_reset) {
@@ -828,9 +902,13 @@ static void ohci_irq_handler(int irq, void *dev_id,
                                handle_selfid(ohci, host, phyid, isroot);
                        }
                        else 
-                         PRINT(KERN_ERR, ohci->id, 
-                               "SelfID process finished but NodeID"
-                               " not valid: %08X",node_id);
+                               PRINT(KERN_ERR, ohci->id, 
+                                     "SelfID process finished but NodeID"
+                                     " not valid: %08X",node_id);
+
+                       /* Accept Physical requests from all nodes. */
+                       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff);
+                       reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff);
                } 
                else PRINT(KERN_INFO, ohci->id, 
                           "phy reg received without reset\n");
@@ -840,316 +918,424 @@ static void ohci_irq_handler(int irq, void *dev_id,
                if (host->in_bus_reset) {
                        PRINT(KERN_INFO, ohci->id, "PhyControl: %08X", 
                              reg_read(ohci, OHCI1394_PhyControl));
-               } else printk("-%d- phy reg received without reset\n",
-                             ohci->id);
+               } else 
+                       PRINT(KERN_ERR, ohci->id, 
+                             "phy reg received without reset");
 #endif
        }
-       if (event & OHCI1394_reqTxComplete) { 
-               /* async packet sent - transmitter ready */
-               u32 ack;
-               struct hpsb_packet *packet;
-
-               if (ohci->async_queue) {
-
-                       spin_lock(&ohci->async_queue_lock);
-           
-                       ack=reg_read(ohci, OHCI1394_AsReqTrContextControlSet) 
-                         & 0xF;
-
-                       packet = ohci->async_queue;
-                       ohci->async_queue = packet->xnext;
-           
-                       if (ohci->async_queue != NULL) {
-                               send_next_async(ohci);
-                       }
-                       spin_unlock(&ohci->async_queue_lock);
-#if 0
-                       PRINT(KERN_INFO,ohci->id,
-                             "packet sent with ack code %d",ack);
-#endif
-                       hpsb_packet_sent(host, packet, ack);        
-               } else 
-                 PRINT(KERN_INFO,ohci->id,
-                       "packet sent without async_queue (self-id?)");
 
-               ohci->TxRdy++;
+       /* clear the interrupt event register */
+       reg_write(ohci, OHCI1394_IntEventClear, event);
+}
+
+/* Put the buffer back into the dma context */
+static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
+{
+       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
+       DBGMSG(ohci->id, "Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
+
+       d->prg[idx]->status = d->buf_size;
+       d->prg[idx]->branchAddress &= 0xfffffff0;
+       idx = (idx + d->num_desc - 1 ) % d->num_desc;
+       d->prg[idx]->branchAddress |= 0x1;
+
+       /* wake up the dma context if necessary */
+       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
+               PRINT(KERN_INFO, ohci->id, 
+                     "Waking dma cxt=%d ... processing is probably too slow",
+                     d->ctx);
+               reg_write(ohci, d->ctrlSet, 0x1000);
        }
+}      
 
-       ohci->NumInterrupts++;
+static int block_length(struct dma_rcv_ctx *d, int idx, 
+                        quadlet_t *buf_ptr, int offset)
+{
+       int length=0;
+
+       /* Where is the data length ? */
+       if (offset+12>=d->buf_size) 
+               length = (d->buf[(idx+1)%d->num_desc]
+                         [3-(d->buf_size-offset)/4]>>16);
+       else 
+               length = (buf_ptr[3]>>16);
+       if (length % 4) length += 4 - (length % 4);
+       return length;
 }
 
+static int packet_length(struct dma_rcv_ctx *d, int idx, 
+                        quadlet_t *buf_ptr, int offset)
+{
+       unsigned char tcode;
+       int length;
+
+       /* Let's see what kind of packet is in there */
+       tcode = (buf_ptr[0]>>4)&0xf;
+
+       if (d->ctx==0) { /* Async Receive Request */
+               if (tcode==TCODE_READQ) return 16;
+               else if (tcode==TCODE_WRITEQ ||
+                        tcode==TCODE_READB) return 20;
+               else if (tcode==TCODE_WRITEB ||
+                        tcode==TCODE_LOCK_REQUEST) {
+                       return block_length(d, idx, buf_ptr, offset) + 20;
+               }
+               else if (tcode==0xE) { /* Phy packet */
+                       return 16;
+               }
+               else return -1;
+       }
+       else if (d->ctx==1) { /* Async Receive Response */
+               if (tcode==TCODE_WRITE_RESPONSE) return 16;
+               else if (tcode==TCODE_READQ_RESPONSE) return 20;
+               else if (tcode==TCODE_READB_RESPONSE ||
+                        tcode==TCODE_LOCK_RESPONSE) {
+                       return block_length(d, idx, buf_ptr, offset) + 20;
+               }
+               else return -1;
+       }
+       else if (d->ctx==2) { /* Iso receive */
+               /* Assumption: buffer fill mode with header/trailer */
+               length = (buf_ptr[0]>>16);
+               if (length % 4) length += 4 - (length % 4);
+               return length+8;
+       }
+       return -1;
+}
 
-/* This is the bottom half that processes async response receive descriptor buffers. */
-static void ohci_ar_resp_proc_desc(void *data)
+/* Bottom half that processes dma receive buffers */
+static void dma_rcv_bh(void *data)
 {
+       struct dma_rcv_ctx *d = (struct dma_rcv_ctx*)data;
+       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
+       unsigned int split_left, idx, offset, rescount;
+       unsigned char tcode;
+       int length, bytes_left;
        quadlet_t *buf_ptr;
        char *split_ptr;
-       unsigned int split_left;
-       struct ti_ohci *ohci= (struct ti_ohci*)data;
-        unsigned int packet_length;
-        unsigned int idx,offset,tcode;
-        unsigned long flags;
        char msg[256];
 
-        spin_lock_irqsave(&ohci->AR_resp_lock, flags);
+       spin_lock(&d->lock);
 
-       idx = ohci->AR_resp_buf_bh_ind;
-       offset = ohci->AR_resp_buf_bh_offset;
+       idx = d->buf_ind;
+       offset = d->buf_offset;
+       buf_ptr = d->buf[idx] + offset/4;
 
-       buf_ptr = ohci->AR_resp_buf[idx];
-       buf_ptr += offset/4;
+       rescount = d->prg[idx]->status&0xffff;
+       bytes_left = d->buf_size - rescount - offset;
 
-        while(ohci->AR_resp_bytes_left > 0) {
-
-                /* check to see if a fatal error occurred */
-                if ((ohci->AR_resp_prg[idx]->status >> 16) & 0x800) {
-                       sprintf(msg,"fatal async response receive error -- status is %d",
-                               ohci->AR_resp_prg[idx]->status & 0x1F);
-                       stop_ar_resp_context(ohci, msg);
-                        spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
-                        return;
-                }
-
-                spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
-
-               /* Let's see what kind of packet is in there */
+       while (bytes_left>0) {
                tcode = (buf_ptr[0]>>4)&0xf;
-               if (tcode==2) /* no-data receive */
-                 packet_length=16;
-               else if (tcode==6) /* quadlet receive */
-                 packet_length=20;
-               else if (tcode==7) { /* block receive */
-                       /* Where is the data length ? */
-                       if (offset+12>=AR_RESP_BUF_SIZE) 
-                         packet_length=(ohci->AR_resp_buf[(idx+1)%AR_RESP_NUM_DESC]
-                                        [3-(AR_RESP_BUF_SIZE-offset)/4]>>16)+20;
-                       else 
-                         packet_length=(buf_ptr[3]>>16)+20;
-                        if (packet_length % 4)
-                         packet_length += 4 - (packet_length % 4);
-               }
-               else /* something is wrong */ {
-                       sprintf(msg,"unexpected packet tcode %d in async response receive buffer",tcode);
-                       stop_ar_resp_context(ohci,msg);
+               length = packet_length(d, idx, buf_ptr, offset);
+
+               if (length<4) { /* something is wrong */
+                       sprintf(msg,"unexpected tcode 0x%X in AR ctx=%d",
+                               tcode, d->ctx);
+                       stop_context(ohci, d->ctrlClear, msg);
+                       spin_unlock(&d->lock);
                        return;
                }
-               if ((offset+packet_length)>AR_RESP_BUF_SIZE) {
-                       /* we have a split packet */
-                       if (packet_length>AR_RESP_SPLIT_PACKET_BUF_SIZE) {
-                               sprintf(msg,"packet size %d bytes exceed split packet buffer size %d bytes",
-                                       packet_length,AR_RESP_SPLIT_PACKET_BUF_SIZE);
-                               stop_ar_resp_context(ohci, msg);
+
+               if ((offset+length)>d->buf_size) { /* Split packet */
+                       if (length>d->split_buf_size) {
+                               stop_context(ohci, d->ctrlClear,
+                                            "split packet size exceeded");
+                               d->buf_ind = idx;
+                               d->buf_offset = offset;
+                               spin_unlock(&d->lock);
                                return;
                        }
-                       split_left = packet_length;
-                       split_ptr = (char *)ohci->AR_resp_spb;
-                       while (split_left>0) {
-                               memcpy(split_ptr,buf_ptr,AR_RESP_BUF_SIZE-offset);
-                               split_left -= AR_RESP_BUF_SIZE-offset;
-                               split_ptr += AR_RESP_BUF_SIZE-offset;
-                               ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
-                               idx = (idx+1) % AR_RESP_NUM_DESC;
-                               buf_ptr = ohci->AR_resp_buf[idx];
-                               offset=0;
-                               while (split_left >= AR_RESP_BUF_SIZE) {
-                                       memcpy(split_ptr,buf_ptr,AR_RESP_BUF_SIZE);
-                                       split_ptr += AR_RESP_BUF_SIZE;
-                                       split_left -= AR_RESP_BUF_SIZE;
-                                       ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
-                                       idx = (idx+1) % AR_RESP_NUM_DESC;
-                                       buf_ptr = ohci->AR_resp_buf[idx];
-                               }
-                               if (split_left>0) {
-                                       memcpy(split_ptr,buf_ptr,split_left);
-                                       offset = split_left;
-                                       split_left=0;
-                                       buf_ptr += split_left/4;
-                               }
+                       if (d->prg[(idx+1)%d->num_desc]->status==d->buf_size) {
+                               /* other part of packet not written yet */
+                               /* this should never happen I think */
+                               /* anyway we'll get it on the next call */
+                               PRINT(KERN_INFO, ohci->id,
+                                     "Got only half a packet !!!");
+                               d->buf_ind = idx;
+                               d->buf_offset = offset;
+                               spin_unlock(&d->lock);
+                               return;
                        }
-#if 0
-                       PRINT(KERN_INFO,ohci->id,"AR resp: received split packet tcode=%d length=%d",
-                             tcode,packet_length);
-#endif
-                       hpsb_packet_received(ohci->host, ohci->AR_resp_spb, packet_length);
-                       ohci->AR_resp_bytes_left -= packet_length;
+                       split_left = length;
+                       split_ptr = (char *)d->spb;
+                       memcpy(split_ptr,buf_ptr,d->buf_size-offset);
+                       split_left -= d->buf_size-offset;
+                       split_ptr += d->buf_size-offset;
+                       insert_dma_buffer(d, idx);
+                       idx = (idx+1) % d->num_desc;
+                       buf_ptr = d->buf[idx];
+                       offset=0;
+                       while (split_left >= d->buf_size) {
+                               memcpy(split_ptr,buf_ptr,d->buf_size);
+                               split_ptr += d->buf_size;
+                               split_left -= d->buf_size;
+                               insert_dma_buffer(d, idx);
+                               idx = (idx+1) % d->num_desc;
+                               buf_ptr = d->buf[idx];
+                       }
+                       if (split_left>0) {
+                               memcpy(split_ptr, buf_ptr, split_left);
+                               offset = split_left;
+                               buf_ptr += offset/4;
+                       }
+
+                       /* 
+                        * We get one phy packet for each bus reset. 
+                        * we know that from now on the bus topology may
+                        * have changed. Just ignore it for the moment
+                        */
+                       if (tcode != 0xE) {
+                               DBGMSG(ohci->id, "Split packet received from"
+                                      " node %d ack=0x%02X spd=%d tcode=0x%X"
+                                      " length=%d data=0x%08x ctx=%d",
+                                      (d->spb[1]>>16)&0x3f,
+                                      (d->spb[length/4-1]>>16)&0x1f,
+                                      (d->spb[length/4-1]>>21)&0x3,
+                                      tcode, length, d->spb[3], d->ctx);
+                               hpsb_packet_received(ohci->host, d->spb, 
+                                                    length);
+                       }
+                       else 
+                               PRINT(KERN_INFO, ohci->id, 
+                                     "Got phy packet ctx=%d ... discarded",
+                                     d->ctx);
                }
                else {
-#if 0
-                       PRINT(KERN_INFO,ohci->id,"AR resp: received packet tcode=%d length=%d",
-                             tcode,packet_length);
-#endif
-                       hpsb_packet_received(ohci->host, buf_ptr, packet_length);
-                       offset += packet_length;
-                       buf_ptr += packet_length/4;
-                       ohci->AR_resp_bytes_left -= packet_length;
-                       if (offset==AR_RESP_BUF_SIZE) {
-                               ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
-                               idx = (idx+1) % AR_RESP_NUM_DESC;
-                               buf_ptr = ohci->AR_resp_buf[idx];
+                       /* 
+                        * We get one phy packet for each bus reset. 
+                        * we know that from now on the bus topology may
+                        * have changed. Just ignore it for the moment
+                        */
+                       if (tcode != 0xE) {
+                               DBGMSG(ohci->id, "Packet received from node"
+                                      " %d ack=0x%02X spd=%d tcode=0x%X"
+                                      " length=%d data=0x%08x ctx=%d",
+                                      (buf_ptr[1]>>16)&0x3f,
+                                      (buf_ptr[length/4-1]>>16)&0x1f,
+                                      (buf_ptr[length/4-1]>>21)&0x3,
+                                      tcode, length, buf_ptr[3], d->ctx);
+                               hpsb_packet_received(ohci->host, buf_ptr, 
+                                                    length);
+                       }
+                       else 
+                               PRINT(KERN_INFO, ohci->id, 
+                                     "Got phy packet ctx=%d ... discarded",
+                                     d->ctx);
+                       offset += length;
+                       buf_ptr += length/4;
+                       if (offset==d->buf_size) {
+                               insert_dma_buffer(d, idx);
+                               idx = (idx+1) % d->num_desc;
+                               buf_ptr = d->buf[idx];
                                offset=0;
                        }
                }
-               
+               rescount = d->prg[idx]->status & 0xffff;
+               bytes_left = d->buf_size - rescount - offset;
+
        }
+
+       d->buf_ind = idx;
+       d->buf_offset = offset;
+
+       spin_unlock(&d->lock);
+}
+
+/* Bottom half that processes sent packets */
+static void dma_trm_bh(void *data)
+{
+       struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
+       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
+       struct hpsb_packet *packet;
+       u32 ack;
+
+       spin_lock(&d->lock);
+
+       if (d->first==NULL) {
+               stop_context(ohci, d->ctrlClear, 
+                            "Packet sent ack received but queue is empty");
+               spin_unlock(&d->lock);
+               return;
+       }
+       packet = d->first;
+       d->first = d->first->xnext;
+       if (d->first==NULL) d->last=NULL;
+       if (packet->data_size) 
+               ack = d->prg[d->sent_ind].end.status>>16;
+       else 
+               ack = d->prg[d->sent_ind].begin.status>>16;
+       d->sent_ind = (d->sent_ind+1)%d->num_desc;
+       d->free_prgs++;
+       spin_unlock(&d->lock);
        
-       if (ohci->AR_resp_bytes_left<0) 
-         stop_ar_resp_context(ohci, "Sync problem in AR resp dma buffer");
+       DBGMSG(ohci->id, "Packet sent to node %d ack=0x%X spd=%d ctx=%d",
+              (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, d->ctx);
+       hpsb_packet_sent(ohci->host, packet, ack&0xf);
+}
+
+static int free_dma_rcv_ctx(struct dma_rcv_ctx *d)
+{
+       int i;
 
-       ohci->AR_resp_buf_bh_ind = idx;
-       ohci->AR_resp_buf_bh_offset = offset;
+       if (d==NULL) return -1;
 
-        spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
+       if (d->buf) {
+               for (i=0; i<d->num_desc; i++) 
+                       if (d->buf[i]) kfree(d->buf[i]);
+               kfree(d->buf);
+       }
+       if (d->prg) {
+               for (i=0; i<d->num_desc; i++) 
+                       if (d->prg[i]) kfree(d->prg[i]);
+               kfree(d->prg);
+       }
+       if (d->spb) kfree(d->spb);
+       
+       kfree(d);
+       
+       return 0;
 }
 
-/* This is the bottom half that processes iso receive descriptor buffers. */
-static void ohci_ir_proc_desc(void *data)
+static struct dma_rcv_ctx *
+alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
+                 int buf_size, int split_buf_size, 
+                 int ctrlSet, int ctrlClear, int cmdPtr)
 {
-       quadlet_t *buf_ptr;
-       struct ti_ohci *ohci= (struct ti_ohci*)data;
-        int bytes_left, data_length;
-        unsigned int idx;
-        unsigned long flags;
+       struct dma_rcv_ctx *d=NULL;
+       int i;
 
-        spin_lock_irqsave(&ohci->IR_recv_lock, flags);
+       d = (struct dma_rcv_ctx *)kmalloc(sizeof(struct dma_rcv_ctx), 
+                                         GFP_KERNEL);
 
-        while(ohci->IR_buf_used > 0)
-        {
-                idx= ohci->IR_buf_last_ind;
+       if (d==NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate dma_rcv_ctx");
+               return NULL;
+       }
 
-                /* check to see if a fatal error occurred */
-                if ((ohci->IR_recv_prg[idx]->status >> 16) & 0x800) {
-                        int i= 0;
+       d->ohci = (void *)ohci;
+       d->ctx = ctx;
 
-                        /* stop the context */
-                       reg_write(ohci, OHCI1394_IrRcvContextControlClear,
-                                  0x8000);
+       d->num_desc = num_desc;
+       d->buf_size = buf_size;
+       d->split_buf_size = split_buf_size;
+       d->ctrlSet = ctrlSet;
+       d->ctrlClear = ctrlClear;
+       d->cmdPtr = cmdPtr;
 
-                       while (reg_read(ohci, OHCI1394_IrRcvContextControlSet) 
-                              & 0x400) {
-                               i++;
+       d->buf = NULL;
+       d->prg = NULL;
+       d->spb = NULL;
 
-                               if (i > 5000) {
-                                       PRINT(KERN_ERR, ohci->id, "runaway loop in DmaIR. bailing out...");
-                                       break;
-                               }
+       d->buf = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL);
 
-                       }
+       if (d->buf == NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer");
+               free_dma_rcv_ctx(d);
+               return NULL;
+       }
+       memset(d->buf, 0, d->num_desc * sizeof(quadlet_t*));
 
-                        spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
-                        PRINT(KERN_ERR, ohci->id,
-                              "fatal iso receive error -- status is %d",
-                              ohci->IR_recv_prg[idx]->status & 0x1F);
-                        return;
-                }
+       d->prg = kmalloc(d->num_desc *  sizeof(struct dma_cmd*), GFP_KERNEL);
 
-                spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
+       if (d->prg == NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg");
+               free_dma_rcv_ctx(d);
+               return NULL;
+       }
+       memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd*));
 
-                buf_ptr= bus_to_virt(ohci->IR_recv_prg[idx]->address);
-                bytes_left= IR_RECV_BUF_SIZE;
+       d->spb = kmalloc(d->split_buf_size, GFP_KERNEL);
 
-                /* are we processing a split packet from last buffer */
-                if (ohci->IR_sp_bytes_left) {
+       if (d->spb == NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate split buffer");
+               free_dma_rcv_ctx(d);
+               return NULL;
+       }
 
-                        if (!ohci->IR_spb_bytes_used) {
-                                /* packet is in process of being dropped */
-                                if (ohci->IR_sp_bytes_left > bytes_left) {
-                                        ohci->IR_sp_bytes_left-= bytes_left;
-                                        bytes_left= 0;
-                                } else {
-                                        buf_ptr= bus_to_virt((unsigned long)
-                                                &((quadlet_t*)ohci->IR_recv_prg
-                                                [idx]->address)
-                                                [ohci->IR_sp_bytes_left / 4]);
-                                        bytes_left-= ohci->IR_sp_bytes_left;
-                                        ohci->IR_sp_bytes_left= 0;
-                                }
+       for (i=0; i<d->num_desc; i++) {
+                d->buf[i] = kmalloc(d->buf_size, GFP_KERNEL);
+               
+                if (d->buf[i] != NULL) {
+                       memset(d->buf[i], 0, d->buf_size);
+               } else {
+                       PRINT(KERN_ERR, ohci->id, 
+                             "failed to allocate dma buffer");
+                       free_dma_rcv_ctx(d);
+                       return NULL;
+               }
 
-                        } else {
-                                /* packet is being assembled */
-                                if (ohci->IR_sp_bytes_left > bytes_left) {
-                                        memcpy(&ohci->IR_spb
-                                               [ohci->IR_spb_bytes_used / 4],
-                                               buf_ptr, bytes_left);
-                                        ohci->IR_spb_bytes_used+= bytes_left;
-                                        ohci->IR_sp_bytes_left-= bytes_left;
-                                        bytes_left= 0;
-                                } else {
-                                        memcpy(&ohci->IR_spb
-                                               [ohci->IR_spb_bytes_used / 4],
-                                               buf_ptr,
-                                               ohci->IR_sp_bytes_left);
-                                        ohci->IR_spb_bytes_used+=
-                                                ohci->IR_sp_bytes_left;
-                                        hpsb_packet_received(ohci->host,
-                                                      ohci->IR_spb,
-                                                      ohci->IR_spb_bytes_used);
-                                        buf_ptr=
-                                                bus_to_virt((unsigned long)
-                                              &((quadlet_t*)ohci->IR_recv_prg
-                                                [idx]->address)
-                                                [ohci->IR_sp_bytes_left / 4]);
-                                        bytes_left-= ohci->IR_sp_bytes_left;
-                                        ohci->IR_sp_bytes_left= 0;
-                                        ohci->IR_spb_bytes_used= 0;
-                                }
+                d->prg[i]= kmalloc(sizeof(struct dma_cmd), GFP_KERNEL);
 
-                        }
+                if (d->prg[i] != NULL) {
+                        memset(d->prg[i], 0, sizeof(struct dma_cmd));
+               } else {
+                       PRINT(KERN_ERR, ohci->id, 
+                             "failed to allocate dma prg");
+                       free_dma_rcv_ctx(d);
+                       return NULL;
+               }
+       }
 
-                }
+        spin_lock_init(&d->lock);
 
-                while(bytes_left > 0) {
-                        data_length= (int)((buf_ptr[0] >> 16) & 0xffff);
+        /* initialize bottom handler */
+        d->task.routine = dma_rcv_bh;
+        d->task.data = (void*)d;
 
-                        if (data_length % 4)
-                                data_length+= 4 - (data_length % 4);
+       return d;
+}
 
-                        /* is this a split packet? */
-                        if ( (bytes_left - (data_length + 8)) < 0 ) {
+static int free_dma_trm_ctx(struct dma_trm_ctx *d)
+{
+       if (d==NULL) return -1;
+       if (d->prg) kfree(d->prg);
+       kfree(d);
+       return 0;
+}
 
-                                if ( (data_length + 8) <=
-                                     IR_SPLIT_PACKET_BUF_SIZE ) {
-                                        memcpy(ohci->IR_spb, buf_ptr,
-                                               bytes_left);
-                                        ohci->IR_spb_bytes_used= bytes_left;
-                                } else {
-                                        PRINT(KERN_ERR, ohci->id, "Packet too large for split packet buffer... dropping it");
-                                        PRINT(KERN_DEBUG, ohci->id, "Header: %8.8x\n", buf_ptr[0]);
-                                        ohci->IR_spb_bytes_used= 0;
-                                }
+static struct dma_trm_ctx *
+alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
+                 int ctrlSet, int ctrlClear, int cmdPtr)
+{
+       struct dma_trm_ctx *d=NULL;
 
-                                ohci->IR_sp_bytes_left=
-                                        (data_length + 8) - bytes_left;
-                        } else {
-                                hpsb_packet_received(ohci->host, buf_ptr,
-                                                     (data_length + 8));
-                                buf_ptr= bus_to_virt((unsigned long)
-                                               &((quadlet_t*)ohci->IR_recv_prg
-                                                [idx]->address)
-                                                [(IR_RECV_BUF_SIZE - bytes_left
-                                                  + data_length + 8) / 4]);
-                        }
+       d = (struct dma_trm_ctx *)kmalloc(sizeof(struct dma_trm_ctx), 
+                                         GFP_KERNEL);
 
-                        bytes_left-= (data_length + 8);
-                }
+       if (d==NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate dma_trm_ctx");
+               return NULL;
+       }
 
-                spin_lock_irqsave(&ohci->IR_recv_lock, flags);
-                ohci->IR_buf_last_ind= (idx + 1) % IR_NUM_DESC;
-                ohci->IR_buf_used--;
-        }
+       d->ohci = (void *)ohci;
+       d->ctx = ctx;
+       d->num_desc = num_desc;
+       d->ctrlSet = ctrlSet;
+       d->ctrlClear = ctrlClear;
+       d->cmdPtr = cmdPtr;
+       d->prg = NULL;
 
-        spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
+       d->prg = kmalloc(d->num_desc * sizeof(struct at_dma_prg), GFP_KERNEL);
+
+       if (d->prg == NULL) {
+               PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg");
+               free_dma_trm_ctx(d);
+               return NULL;
+       }
+       memset(d->prg, 0, d->num_desc * sizeof(struct at_dma_prg));
+
+        spin_lock_init(&d->lock);
+
+        /* initialize bottom handler */
+        d->task.routine = dma_trm_bh;
+        d->task.data = (void*)d;
+
+       return d;
 }
 
 static int add_card(struct pci_dev *dev)
 {
-#define FAIL(fmt, args...) \
-       PRINT_G(KERN_ERR, fmt , ## args); \
-         num_of_cards--; \
-           remove_card(ohci); \
-             return 1;
-
        struct ti_ohci *ohci;   /* shortcut to currently handled device */
-       int i;
 
        if (num_of_cards == MAX_OHCI1394_CARDS) {
                PRINT_G(KERN_WARNING, "cannot handle more than %d cards.  "
@@ -1185,124 +1371,51 @@ static int add_card(struct pci_dev *dev)
                FAIL("failed to allocate DMA buffer for self-id packets");
        }
 
-       /* AR dma buffer and program allocation */
-       ohci->AR_resp_buf=
-               kmalloc(AR_RESP_NUM_DESC * sizeof(quadlet_t*),
-                       GFP_KERNEL);
-
-       if (ohci->AR_resp_buf == NULL) {
-               FAIL("failed to allocate AR response receive DMA buffer");
-       }
-
-       ohci->AR_resp_prg=
-               kmalloc(AR_RESP_NUM_DESC * sizeof(struct dma_cmd*),
-                       GFP_KERNEL);
-
-       if (ohci->AR_resp_prg == NULL) {
-               FAIL("failed to allocate AR response receive DMA program");
-       }
-
-       ohci->AR_resp_spb= kmalloc(AR_RESP_SPLIT_PACKET_BUF_SIZE, GFP_KERNEL);
-
-       if (ohci->AR_resp_spb == NULL) {
-               FAIL("failed to allocate AR response split packet buffer");
-       }
-
-       for (i= 0; i < AR_RESP_NUM_DESC; i++) {
-                ohci->AR_resp_buf[i]= kmalloc(AR_RESP_BUF_SIZE, GFP_KERNEL);
-
-                if (ohci->AR_resp_buf[i] != NULL) {
-                        memset(ohci->AR_resp_buf[i], 0, AR_RESP_BUF_SIZE);
-                } else {
-                        FAIL("failed to allocate AR response DMA buffer");
-                }
-
-                ohci->AR_resp_prg[i]= kmalloc(sizeof(struct dma_cmd),
-                                                   GFP_KERNEL);
-
-                if (ohci->AR_resp_prg[i] != NULL) {
-                        memset(ohci->AR_resp_prg[i], 0,
-                               sizeof(struct dma_cmd));
-                } else {
-                        FAIL("failed to allocate AR response DMA buffer");
-                }
-
-       }
-
-        ohci->AR_resp_buf_th_ind = 0;
-        ohci->AR_resp_buf_th_offset = 0;
-        ohci->AR_resp_buf_bh_ind = 0;
-        ohci->AR_resp_buf_bh_offset = 0;
-        ohci->AR_resp_bytes_left = 0;
-        spin_lock_init(&ohci->AR_resp_lock);
-
-        /* initialize AR response receive task */
-        ohci->AR_resp_pdl_task.routine= ohci_ar_resp_proc_desc;
-        ohci->AR_resp_pdl_task.data= (void*)ohci;
-
-       /* AT dma program allocation */
-       ohci->AT_req_prg = (struct dma_cmd *) kmalloc(AT_REQ_PRG_SIZE, 
-                                                     GFP_KERNEL);
-       if (ohci->AT_req_prg != NULL) {
-               memset(ohci->AT_req_prg, 0, AT_REQ_PRG_SIZE);
-       } else {
-               FAIL("failed to allocate AT request DMA program");
-       }
-
-       /* IR dma buffer and program allocation */
-       ohci->IR_recv_buf=
-               kmalloc(IR_NUM_DESC * sizeof(quadlet_t*),
-                       GFP_KERNEL);
-
-       if (ohci->IR_recv_buf == NULL) {
-               FAIL("failed to allocate IR receive DMA buffer");
-       }
-
-       ohci->IR_recv_prg=
-               kmalloc(IR_NUM_DESC * sizeof(struct dma_cmd*),
-                       GFP_KERNEL);
-
-       if (ohci->IR_recv_prg == NULL) {
-               FAIL("failed to allocate IR receive DMA program");
-       }
-
-       ohci->IR_spb= kmalloc(IR_SPLIT_PACKET_BUF_SIZE, GFP_KERNEL);
-
-       if (ohci->IR_spb == NULL) {
-               FAIL("failed to allocate IR split packet buffer");
-       }
-
-       for (i= 0; i < IR_NUM_DESC; i++) {
-                ohci->IR_recv_buf[i]= kmalloc(IR_RECV_BUF_SIZE, GFP_KERNEL);
-
-                if (ohci->IR_recv_buf[i] != NULL) {
-                        memset(ohci->IR_recv_buf[i], 0, IR_RECV_BUF_SIZE);
-                } else {
-                        FAIL("failed to allocate IR DMA buffer");
-                }
+       ohci->ar_req_context = 
+               alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC,
+                                 AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
+                                 OHCI1394_AsReqRcvContextControlSet,
+                                 OHCI1394_AsReqRcvContextControlClear,
+                                 OHCI1394_AsReqRcvCommandPtr);
+
+       if (ohci->ar_req_context == NULL) return 1;
+
+       ohci->ar_resp_context = 
+               alloc_dma_rcv_ctx(ohci, 1, AR_RESP_NUM_DESC,
+                                 AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
+                                 OHCI1394_AsRspRcvContextControlSet,
+                                 OHCI1394_AsRspRcvContextControlClear,
+                                 OHCI1394_AsRspRcvCommandPtr);
+       
+       if (ohci->ar_resp_context == NULL) return 1;
 
-                ohci->IR_recv_prg[i]= kmalloc(sizeof(struct dma_cmd),
-                                              GFP_KERNEL);
+       ohci->at_req_context = 
+               alloc_dma_trm_ctx(ohci, 0, AT_REQ_NUM_DESC,
+                                 OHCI1394_AsReqTrContextControlSet,
+                                 OHCI1394_AsReqTrContextControlClear,
+                                 OHCI1394_AsReqTrCommandPtr);
+       
+       if (ohci->at_req_context == NULL) return 1;
 
-                if (ohci->IR_recv_prg[i] != NULL) {
-                        memset(ohci->IR_recv_prg[i], 0,
-                               sizeof(struct dma_cmd));
-                } else {
-                        FAIL("failed to allocate IR DMA buffer");
-                }
+       ohci->at_resp_context = 
+               alloc_dma_trm_ctx(ohci, 1, AT_RESP_NUM_DESC,
+                                 OHCI1394_AsRspTrContextControlSet,
+                                 OHCI1394_AsRspTrContextControlClear,
+                                 OHCI1394_AsRspTrCommandPtr);
+       
+       if (ohci->at_resp_context == NULL) return 1;
+                                     
+       ohci->ir_context =
+               alloc_dma_rcv_ctx(ohci, 2, IR_NUM_DESC,
+                                 IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
+                                 OHCI1394_IrRcvContextControlSet,
+                                 OHCI1394_IrRcvContextControlClear,
+                                 OHCI1394_IrRcvCommandPtr);
 
-       }
+       if (ohci->ir_context == NULL) return 1;
 
-        ohci->IR_buf_used= 0;
-        ohci->IR_buf_last_ind= 0;
-        ohci->IR_buf_next_ind= 0;
-        spin_lock_init(&ohci->IR_recv_lock);
-        spin_lock_init(&ohci->IR_channel_lock);
         ohci->IR_channel_usage= 0x0000000000000000;
-
-        /* initialize iso receive task */
-        ohci->IR_pdl_task.routine= ohci_ir_proc_desc;
-        ohci->IR_pdl_task.data= (void*)ohci;
+        spin_lock_init(&ohci->IR_channel_lock);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
        ohci->registers = ioremap_nocache(dev->base_address[0],
@@ -1342,6 +1455,8 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
        //unsigned char phyreg;
        //int i, nports;
        int i;
+       struct dma_rcv_ctx *d=NULL;
+       struct dma_trm_ctx *dt=NULL;
 
        p += sprintf(p,"IEEE-1394 OHCI Driver status report:\n");
        p += sprintf(p,"  bus number: 0x%x Node ID: 0x%x\n", 
@@ -1370,22 +1485,93 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
                     host->is_busmgr ? "bus_mgr" : "");
   
        p += sprintf(p,"\n---Iso Receive DMA---\n");
-        for (i= 0; i < IR_NUM_DESC; i++) {
-                p += sprintf(p, "IR_recv_buf[%d] : %p  IR_recv_prg[%d]: %p\n",
-                             i, ohci->IR_recv_buf[i], i, ohci->IR_recv_prg[i]);
+       d = ohci->ir_context;
+#if 0
+       for (i=0; i<d->num_desc; i++) {
+               p += sprintf(p, "IR buf[%d] : %p prg[%d]: %p\n",
+                            i, d->buf[i], i, d->prg[i]);
        }
+#endif
+       p += sprintf(p, "Current buf: %d offset: %d\n",
+                    d->buf_ind,d->buf_offset);
+
+       p += sprintf(p,"\n---Async Receive DMA---\n");
+       d = ohci->ar_req_context;
+#if 0
+       for (i=0; i<d->num_desc; i++) {
+               p += sprintf(p, "AR req buf[%d] : %p prg[%d]: %p\n",
+                            i, d->buf[i], i, d->prg[i]);
+       }
+#endif
+       p += sprintf(p, "Ar req current buf: %d offset: %d\n",
+                    d->buf_ind,d->buf_offset);
+
+       d = ohci->ar_resp_context;
+#if 0
+       for (i=0; i<d->num_desc; i++) {
+               p += sprintf(p, "AR resp buf[%d] : %p prg[%d]: %p\n",
+                            i, d->buf[i], i, d->prg[i]);
+       }
+#endif
+       p += sprintf(p, "AR resp current buf: %d offset: %d\n",
+                    d->buf_ind,d->buf_offset);
+
+       p += sprintf(p,"\n---Async Transmit DMA---\n");
+       dt = ohci->at_req_context;
+       p += sprintf(p, "AT req prg: %d sent: %d free: %d branchAddrPtr: %p\n",
+                    dt->prg_ind, dt->sent_ind, dt->free_prgs, 
+                    dt->branchAddrPtr);
+       p += sprintf(p, "AT req queue: first: %p last: %p\n",
+                    dt->first, dt->last);
+       dt = ohci->at_resp_context;
+#if 0
+       for (i=0; i<dt->num_desc; i++) {
+               p += sprintf(p, "------- AT resp prg[%02d] ------\n",i);
+               p += sprintf(p, "%p: control  : %08x\n",
+                            &(dt->prg[i].begin.control),
+                            dt->prg[i].begin.control);
+               p += sprintf(p, "%p: address  : %08x\n",
+                            &(dt->prg[i].begin.address),
+                            dt->prg[i].begin.address);
+               p += sprintf(p, "%p: brancAddr: %08x\n",
+                            &(dt->prg[i].begin.branchAddress),
+                            dt->prg[i].begin.branchAddress);
+               p += sprintf(p, "%p: status   : %08x\n",
+                            &(dt->prg[i].begin.status),
+                            dt->prg[i].begin.status);
+               p += sprintf(p, "%p: header[0]: %08x\n",
+                            &(dt->prg[i].data[0]),
+                            dt->prg[i].data[0]);
+               p += sprintf(p, "%p: header[1]: %08x\n",
+                            &(dt->prg[i].data[1]),
+                            dt->prg[i].data[1]);
+               p += sprintf(p, "%p: header[2]: %08x\n",
+                            &(dt->prg[i].data[2]),
+                            dt->prg[i].data[2]);
+               p += sprintf(p, "%p: header[3]: %08x\n",
+                            &(dt->prg[i].data[3]),
+                            dt->prg[i].data[3]);
+               p += sprintf(p, "%p: control  : %08x\n",
+                            &(dt->prg[i].end.control),
+                            dt->prg[i].end.control);
+               p += sprintf(p, "%p: address  : %08x\n",
+                            &(dt->prg[i].end.address),
+                            dt->prg[i].end.address);
+               p += sprintf(p, "%p: brancAddr: %08x\n",
+                            &(dt->prg[i].end.branchAddress),
+                            dt->prg[i].end.branchAddress);
+               p += sprintf(p, "%p: status   : %08x\n",
+                            &(dt->prg[i].end.status),
+                            dt->prg[i].end.status);
+       }
+#endif
+       p += sprintf(p, "AR resp prg: %d sent: %d free: %d"
+                    " branchAddrPtr: %p\n",
+                    dt->prg_ind, dt->sent_ind, dt->free_prgs, 
+                    dt->branchAddrPtr);
+       p += sprintf(p, "AT resp queue: first: %p last: %p\n",
+                    dt->first, dt->last);
 
-       
-       p += sprintf(p,"\n---Async Reponse Receive DMA---\n");
-        for (i= 0; i < AR_RESP_NUM_DESC; i++) {
-                p += sprintf(p, "AR_resp_buf[%d] : %p  AR_resp_prg[%d]: %p\n",
-                             i, ohci->AR_resp_buf[i], i, ohci->AR_resp_prg[i]);
-       }
-       p += sprintf(p, "Current AR resp buf in irq handler: %d offset: %d\n",
-                    ohci->AR_resp_buf_th_ind,ohci->AR_resp_buf_th_offset);
-       p += sprintf(p, "Current AR resp buf in bottom half: %d offset: %d\n",
-                    ohci->AR_resp_buf_bh_ind,ohci->AR_resp_buf_bh_offset);
-       
        /* ----- Register Dump ----- */
        p += sprintf(p,"\n### HC Register dump ###\n");
        SR("Version     : %08x  GUID_ROM    : %08x  ATRetries   : %08x\n",
@@ -1427,20 +1613,32 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
        SR("AsRsRvCtxCtl: %08x  AsRsRvCmdPtr: %08x  IntEvent    : %08x\n",
           OHCI1394_AsRspRcvContextControlSet, OHCI1394_AsRspRcvCommandPtr, 
           OHCI1394_IntEventSet);
-       
+       for (i=0;i<4;i++) {
+               p += sprintf(p,"IsoRCtxCtl%02d: %08x  IsoRCmdPtr%02d: %08x"
+                            "  IsoRCxtMch%02d: %08x\n", i,
+                            reg_read(ohci, 
+                                     OHCI1394_IrRcvContextControlSet+32*i),
+                            i,reg_read(ohci, OHCI1394_IrRcvCommandPtr+32*i),
+                            i,reg_read(ohci, 
+                                       OHCI1394_IrRcvContextMatch+32*i));
+       }
+
 #if 0
        p += sprintf(p,"\n### Phy Register dump ###\n");
        phyreg=get_phy_reg(ohci,1);
-       p += sprintf(p,"offset: %d val: 0x%02x -> RHB: %d IBR: %d Gap_count: %d\n",
-                    1,phyreg,(phyreg&0x80) != 0, (phyreg&0x40) !=0, phyreg&0x3f);
+       p += sprintf(p,"offset: %d val: 0x%02x -> RHB: %d"
+                    "IBR: %d Gap_count: %d\n",
+                    1,phyreg,(phyreg&0x80) != 0, 
+                    (phyreg&0x40) !=0, phyreg&0x3f);
        phyreg=get_phy_reg(ohci,2);
        nports=phyreg&0x1f;
-       p += sprintf(p,"offset: %d val: 0x%02x -> SPD: %d E  : %d Ports    : %2d\n",
-                    2,phyreg,
-                    (phyreg&0xC0)>>6, (phyreg&0x20) !=0, nports);
+       p += sprintf(p,"offset: %d val: 0x%02x -> SPD: %d"
+                    " E  : %d Ports    : %2d\n",
+                    2,phyreg, (phyreg&0xC0)>>6, (phyreg&0x20) !=0, nports);
        for (i=0;i<nports;i++) {
                phyreg=get_phy_reg(ohci,3+i);
-               p += sprintf(p,"offset: %d val: 0x%02x -> [port %d] TPA: %d TPB: %d | %s %s\n",
+               p += sprintf(p,"offset: %d val: 0x%02x -> [port %d]"
+                            " TPA: %d TPB: %d | %s %s\n",
                             3+i,phyreg,
                             i, (phyreg&0xC0)>>6, (phyreg&0x30)>>4,
                             (phyreg&0x08) ? "child" : "parent",
@@ -1454,11 +1652,6 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
                     phyreg&0x3f);
 #endif
 
-#if 0
-       p += sprintf(p,"AR_resp_prg ctrl: %08x\n",ohci->AR_resp_prg->control);
-       p += sprintf(p,"AR_resp_prg status: %08x\n",ohci->AR_resp_prg->status);
-#endif
-
        return  p - buf;
 }
 
@@ -1494,53 +1687,26 @@ struct proc_dir_entry ohci_proc_entry =
 static void remove_card(struct ti_ohci *ohci)
 {
        if (ohci->registers) 
-         iounmap(ohci->registers);
+               iounmap(ohci->registers);
 
-       /* Free AR response buffers and programs */
-       if (ohci->AR_resp_buf) {
-               int i;
-                for (i= 0; i < AR_RESP_NUM_DESC; i++) {
-                       kfree(ohci->AR_resp_buf[i]);
-               }
-               kfree(ohci->AR_resp_buf);
-       }
-       if (ohci->AR_resp_prg) {
-               int i;
-               for (i= 0; i < AR_RESP_NUM_DESC; i++) {
-                       kfree(ohci->AR_resp_prg[i]);
-               }
-               kfree(ohci->AR_resp_prg);
-       }
-       kfree(ohci->AR_resp_spb);
+       /* Free AR dma */
+       free_dma_rcv_ctx(ohci->ar_req_context);
+       free_dma_rcv_ctx(ohci->ar_resp_context);
 
-       /* Free AT request buffer and program */
-       if (ohci->AT_req_prg) 
-         kfree(ohci->AT_req_prg);
+       /* Free AT dma */
+       free_dma_trm_ctx(ohci->at_req_context);
+       free_dma_trm_ctx(ohci->at_resp_context);
 
-       /* Free Iso receive buffers and programs */
-       if (ohci->IR_recv_buf) {
-               int i;
-                for (i= 0; i < IR_NUM_DESC; i++) {
-                       kfree(ohci->IR_recv_buf[i]);
-               }
-               kfree(ohci->IR_recv_buf);
-       }
-       if (ohci->IR_recv_prg) {
-               int i;
-               for (i= 0; i < IR_NUM_DESC; i++) {
-                       kfree(ohci->IR_recv_prg[i]);
-               }
-               kfree(ohci->IR_recv_prg);
-       }
-       kfree(ohci->IR_spb);
+       /* Free IR dma */
+       free_dma_rcv_ctx(ohci->ir_context);
 
        /* Free self-id buffer */
        if (ohci->self_id_buffer)
-         kfree(ohci->self_id_buffer);
+               kfree(ohci->self_id_buffer);
        
        /* Free config rom */
        if (ohci->csr_config_rom)
-         kfree(ohci->csr_config_rom);
+               kfree(ohci->csr_config_rom);
 
        /* Free the IRQ */
        free_irq(ohci->dev->irq, ohci);
@@ -1562,13 +1728,13 @@ static int init_driver()
        PRINT_G(KERN_INFO, "looking for Ohci1394 cards");
 
        for (i = 0; supported_chips[i][0] != -1; i++) {
-           while ((dev = pci_find_device(supported_chips[i][0],
-                                         supported_chips[i][1], dev)) 
-                  != NULL) {
-               if (add_card(dev) == 0) {
-                   success = 1;
+               while ((dev = pci_find_device(supported_chips[i][0],
+                                             supported_chips[i][1], dev)) 
+                      != NULL) {
+                       if (add_card(dev) == 0) {
+                               success = 1;
+                       }
                }
-           }
        }
 
        if (success == 0) {
@@ -1593,10 +1759,8 @@ static size_t get_ohci_rom(struct hpsb_host *host, const quadlet_t **ptr)
 {
        struct ti_ohci *ohci=host->hostdata;
 
-#if 0
-       PRINT(KERN_INFO, ohci->id, "request csr_rom address: %08X",
-             (u32)ohci->csr_config_rom);
-#endif
+       DBGMSG(ohci->id, "request csr_rom address: %08X",
+              (u32)ohci->csr_config_rom);
 
        *ptr = ohci->csr_config_rom;
        return sizeof(ohci_csr_rom);
index 35d8fa2afdb302197ad8bcdf8aa1de1731599682..46d9a270fd2d11a937e6c5d17b218d133982f201 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "ieee1394_types.h"
 
+#define OHCI1394_DEBUG 1
+
 #define OHCI1394_DRIVER_NAME      "ohci1394"
 
 #ifndef PCI_DEVICE_ID_TI_OHCI1394
 #define PCI_DEVICE_ID_VIA_OHCI1394 0x3044
 #endif
 
+#ifndef PCI_VENDOR_ID_SONY
+#define PCI_VENDOR_ID_SONY 0x104d
+#endif
+
+#ifndef PCI_DEVICE_ID_SONY_CXD3222
+#define PCI_DEVICE_ID_SONY_CXD3222 0x8039
+#endif
+
 #define MAX_OHCI1394_CARDS        4
 
-#define OHCI1394_MAX_AT_REQ_RETRIES       1
-#define OHCI1394_MAX_AT_RESP_RETRIES      1
-#define OHCI1394_MAX_PHYS_RESP_RETRIES    4
+#define OHCI1394_MAX_AT_REQ_RETRIES       0x2
+#define OHCI1394_MAX_AT_RESP_RETRIES      0x2
+#define OHCI1394_MAX_PHYS_RESP_RETRIES    0x8
+
+#define AR_REQ_NUM_DESC                   4 /* number of AR req descriptors */
+#define AR_REQ_BUF_SIZE                4096 /* size of AR req buffers */
+#define AR_REQ_SPLIT_BUF_SIZE          4096 /* split packet buffer */
 
 #define AR_RESP_NUM_DESC                  4 /* number of AR resp descriptors */
 #define AR_RESP_BUF_SIZE               4096 /* size of AR resp buffers */
-#define AR_RESP_SPLIT_PACKET_BUF_SIZE   256 /* split packet buffer */
-#define AR_RESP_TOTAL_BUF_SIZE         (AR_RESP_BUF_SIZE * AR_RESP_NUM_DESC)
-#define AT_REQ_PRG_SIZE                256
+#define AR_RESP_SPLIT_BUF_SIZE         4096 /* split packet buffer */
 
-#define IR_RECV_BUF_SIZE          4096 /* 4096 bytes/buffer */
-#define IR_SPLIT_PACKET_BUF_SIZE  8192 /* size of buffer for split packets */
-#define IR_NUM_DESC               16   /* number of ISO recv descriptors */
+#define IR_NUM_DESC                      16 /* number of IR descriptors */
+#define IR_BUF_SIZE                    6480 /* 6480 bytes/buffer */
+#define IR_SPLIT_BUF_SIZE              8192 /* split packet buffer */
+
+#define AT_REQ_NUM_DESC                  32 /* number of AT req descriptors */
+#define AT_RESP_NUM_DESC                 32 /* number of AT resp descriptors */
 
 struct dma_cmd {
         u32 control;
@@ -41,6 +56,50 @@ struct dma_cmd {
         u32 status;
 };
 
+struct at_dma_prg {
+       struct dma_cmd begin;
+       quadlet_t data[4];
+       struct dma_cmd end;
+};
+
+/* DMA receive context */
+struct dma_rcv_ctx {
+       void *ohci;
+       int ctx;
+       unsigned int num_desc;
+       unsigned int buf_size;
+       unsigned int split_buf_size;
+        struct dma_cmd **prg;
+        quadlet_t **buf;
+        unsigned int buf_ind;
+        unsigned int buf_offset;
+        quadlet_t *spb;
+        spinlock_t lock;
+        struct tq_struct task;
+       int ctrlClear;
+       int ctrlSet;
+       int cmdPtr;
+};
+
+/* DMA transmit context */     
+struct dma_trm_ctx {
+       void *ohci;
+       int ctx;
+       unsigned int num_desc;
+        struct at_dma_prg *prg;
+        unsigned int prg_ind;
+        unsigned int sent_ind;
+       int free_prgs;
+        quadlet_t *branchAddrPtr;
+        struct hpsb_packet *first;
+        struct hpsb_packet *last;
+        spinlock_t lock;
+        struct tq_struct task;
+       int ctrlClear;
+       int ctrlSet;
+       int cmdPtr;
+};
+
 struct ti_ohci {
         int id; /* sequential card number */
 
@@ -54,42 +113,18 @@ struct ti_ohci {
         quadlet_t *self_id_buffer; /* dma buffer for self-id packets */
         quadlet_t *csr_config_rom; /* buffer for csr config rom */
 
-        /* asynchronous receive */
-        struct dma_cmd **AR_resp_prg;
-        quadlet_t **AR_resp_buf;
-        unsigned int AR_resp_buf_bh_ind;
-        unsigned int AR_resp_buf_bh_offset;
-        unsigned int AR_resp_buf_th_ind;
-        unsigned int AR_resp_buf_th_offset;
-       int AR_resp_bytes_left;
-        quadlet_t *AR_resp_spb;
-        spinlock_t AR_resp_lock;
-
-        /* async receive task */
-        struct tq_struct AR_resp_pdl_task;
-
-        /* asynchronous transmit */
-        struct dma_cmd *AT_req_prg;
-
-        /* isochronous receive */
-        struct dma_cmd **IR_recv_prg;
-        quadlet_t **IR_recv_buf;
-        unsigned int IR_buf_used;
-        unsigned int IR_buf_last_ind;
-        unsigned int IR_buf_next_ind;
-        spinlock_t IR_recv_lock;
-
-        /* iso recv split packet handling */
-        quadlet_t *IR_spb;
-        unsigned int IR_sp_bytes_left;
-        unsigned int IR_spb_bytes_used;
-
-        /* iso receive channel usage */
-        spinlock_t IR_channel_lock;
-        u64 IR_channel_usage;
+        /* async receive */
+       struct dma_rcv_ctx *ar_resp_context;
+       struct dma_rcv_ctx *ar_req_context;
 
-        /* iso receive task */
-        struct tq_struct IR_pdl_task;
+       /* async transmit */
+       struct dma_trm_ctx *at_resp_context;
+       struct dma_trm_ctx *at_req_context;
+
+        /* iso receive */
+       struct dma_rcv_ctx *ir_context;
+        u64 IR_channel_usage;
+        spinlock_t IR_channel_lock;
 
         /* IEEE-1394 part follows */
         struct hpsb_host *host;
@@ -98,16 +133,9 @@ struct ti_ohci {
 
         spinlock_t phy_reg_lock;
 
-        struct hpsb_packet *async_queue;
-        spinlock_t async_queue_lock;
-
-        int AR_resp_active;
         int NumBusResets;
-        int TxRdy;
-        int NumInterrupts;
 };
 
-
 /*
  * Register read and write helper functions.
  */
@@ -129,9 +157,9 @@ quadlet_t ohci_csr_rom[] = {
         /* bus info block */
         0x04040000, /* info/CRC length, CRC */
         0x31333934, /* 1394 magic number */
-        0xf064a000, /* misc. settings - FIXME */
-        0x08002856, /* vendor ID, chip ID high */
-        0x0000083E, /* chip ID low */
+        0xf07da002, /* cyc_clk_acc = 125us, max_rec = 1024 */
+        0x00000000, /* vendor ID, chip ID high (written from card info) */
+        0x00000000, /* chip ID low (written from card info) */
         /* root directory - FIXME */
         0x00090000, /* CRC length, CRC */
         0x03080028, /* vendor ID (Texas Instr.) */
index 27cbd0c7896fe544e3d0af72e9f32d9ff9947549..2809bde0832138615550a97dc4e3c145b922664f 100644 (file)
@@ -348,8 +348,8 @@ struct ti_pcl {
         struct {
                 u32 control;
                 u32 pointer;
-        } buffer[13];
-};
+        } buffer[13] __attribute__ ((packed));
+} __attribute__ ((packed));
 
 #include <linux/stddef.h>
 #define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
@@ -383,7 +383,11 @@ inline static void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
 
 inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+        return lynx->dev->base_address[1] + pclid * sizeof(struct ti_pcl);
+#else
         return lynx->dev->resource[1].start + pclid * sizeof(struct ti_pcl);
+#endif
 }
 
 #else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
index adc45896d43de23b0cfcaebe874e6e7858491599..0e63acb33134147d6bd078ec5e3a6a0ab11bb0f3 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Raw interface to the bus
  *
- * Copyright (C) 1999 Andreas E. Bombe
+ * Copyright (C) 1999, 2000 Andreas E. Bombe
  */
 
 #include <linux/kernel.h>
@@ -30,6 +30,9 @@ spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
 
 static struct hpsb_highlevel *hl_handle = NULL;
 
+static atomic_t iso_buffer_size;
+static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
+
 static void queue_complete_cb(struct pending_request *req);
 
 static struct pending_request *__alloc_pending_request(int flags)
@@ -56,6 +59,7 @@ static void free_pending_request(struct pending_request *req)
 {
         if (req->ibs) {
                 if (atomic_dec_and_test(&req->ibs->refcount)) {
+                        atomic_sub((req->data[0] >> 16) + 4, &iso_buffer_size);
                         kfree(req->ibs);
                 }
         } else if (req->free_data) {
@@ -210,6 +214,10 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
         struct iso_block_store *ibs = NULL;
         LIST_HEAD(reqs);
 
+        if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+                return;
+        }
+
         spin_lock_irqsave(&host_info_lock, flags);
         hi = find_host_info(host);
 
@@ -227,6 +235,7 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
                                               + length, SLAB_ATOMIC);
                                 if (!ibs) break;
 
+                                atomic_add(length, &iso_buffer_size);
                                 atomic_set(&ibs->refcount, 0);
                                 memcpy(ibs->data, data, length);
                         }
index 2874bad9fde03c677c322957bb3c0334304102c5..6ba85a81b1b0cbaf929eb263e0318e5658ea72ba 100644 (file)
@@ -136,8 +136,11 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
          tristate '    DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
       fi
-      tristate '    EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+      tristate '    EtherExpressPro/100 support' CONFIG_EEPRO100
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         if [ "$CONFIG_EEPRO100" = "y" -o "$CONFIG_EEPRO100" = "m" ]; then
+           bool '      Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM
+        fi
         tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390
         tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210
       fi
index 0daf888875b063e6d5581697ceadbf195d8d32ab..7da83989eca67013155fef46e64a79a95f0d5313 100644 (file)
@@ -120,7 +120,7 @@ obj-$(CONFIG_RCPCI) += rcpci.o
 obj-$(CONFIG_VORTEX) += 3c59x.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
+obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_TULIP) += tulip.o
 obj-$(CONFIG_EPIC100) += epic100.o
index 345b86c0ddb489750de4dca678c98c5b0451e0d5..8410c0cf851e202a77949e1bcbaf329dfdc57942 100644 (file)
@@ -1775,7 +1775,7 @@ static void eepro100_suspend (struct pci_dev *pdev)
        struct net_device *dev = pdev->driver_data;
        long ioaddr = dev->base_addr;
 
-       netif_stop_queue (dev);
+       netif_device_detach(dev);
        outl(PortPartialReset, ioaddr + SCBPort);
        
        /* XXX call pci_set_power_state ()? */
@@ -1787,6 +1787,7 @@ static void eepro100_resume (struct pci_dev *pdev)
        struct net_device *dev = pdev->driver_data;
        struct speedo_private *np = (struct speedo_private *)dev->priv;
 
+       netif_device_attach(dev);
        speedo_resume(dev);
        np->rx_mode = -1;
        np->flow_ctrl = np->partner = 0;
@@ -1812,6 +1813,10 @@ static void __devexit eepro100_remove_one (struct pci_dev *pdev)
 
        pci_set_power_state (pdev, sp->acpi_pwr);
 
+       pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+                                 + sizeof(struct speedo_stats),
+                           sp->tx_ring, sp->tx_ring_dma);
+
        kfree (dev);
 }
 
index 788c5660d61b6ee76594c6e6784686a6444a104c..5619b961d6727ecf35b6b76d1085c6263da41d28 100644 (file)
@@ -142,7 +142,7 @@ static const char version[] = "Linux Tulip driver version 0.9.2 (Feb 15, 2000)\n
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
-
+#include <asm/delay.h>
 
 
 /* A few user-configurable values. */
@@ -259,7 +259,7 @@ static void comet_timer(unsigned long data);
 
 enum tbl_flag {
        HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
-       HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
+       HAS_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
        HAS_PNICNWAY=0x80, HAS_NWAY143=0x40,    /* Uses internal NWay xcvr. */
        HAS_8023X=0x100,
 };
@@ -275,7 +275,7 @@ static struct tulip_chip_table {
   { "Digital DS21140 Tulip", 128, 0x0001ebef,
        HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
   { "Digital DS21143 Tulip", 128, 0x0801fbff,
-       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY143,
+       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143,
        t21142_timer },
   { "Lite-On 82c168 PNIC", 256, 0x0001ebef,
        HAS_MII | HAS_PNICNWAY, pnic_timer },
@@ -294,10 +294,10 @@ static struct tulip_chip_table {
   { "Compex 9881 PMAC", 128, 0x0001ebef,
        HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
-       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY143,
+       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_NWAY143,
        t21142_timer },
   { "Xircom tulip work-alike", 128, 0x0801fbff,
-       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY143,
+       HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143,
        t21142_timer },
   {0},
 };
@@ -316,7 +316,7 @@ enum chips {
        COMET,
        COMPEX9881,
        I21145,
-       XIRCLONE,
+       X3201_3,
 };
 
 
@@ -334,7 +334,7 @@ static struct pci_device_id tulip_pci_tbl[] __devinitdata = {
        { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
        { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
-       { 0x115d, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, XIRCLONE },
+       { 0x115d, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
        {0},
 };
 MODULE_DEVICE_TABLE(pci,tulip_pci_tbl);
@@ -465,6 +465,7 @@ struct tulip_private {
        int ttimer;
        int susp_rx;
        unsigned long nir;
+       unsigned long base_addr;
        int pad0, pad1;                                         /* Used for 8-byte alignment */
 };
 
@@ -473,7 +474,6 @@ static int read_eeprom(long ioaddr, int location, int addr_len);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static void select_media(struct net_device *dev, int startup);
-static int tulip_open(struct net_device *dev);
 /* Chip-specific media selection (timer functions prototyped above). */
 static void t21142_lnk_change(struct net_device *dev, int csr5);
 static void t21142_start_nway(struct net_device *dev);
@@ -486,7 +486,10 @@ static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int tulip_refill_rx(struct net_device *dev);
 static int tulip_rx(struct net_device *dev);
 static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int tulip_open(struct net_device *dev);
 static int tulip_close(struct net_device *dev);
+static void tulip_up(struct net_device *dev);
+static void tulip_down(struct net_device *dev);
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
@@ -725,7 +728,7 @@ subsequent_board:
 #define EE_READ_CMD            (6)
 
 /* Note: this routine returns extra data bits for size detection. */
-static int read_eeprom(long ioaddr, int location, int addr_len)
+static int __devinit read_eeprom(long ioaddr, int location, int addr_len)
 {
        int i;
        unsigned retval = 0;
@@ -893,9 +896,60 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        return;
 }
 
-\f
-static int
-tulip_open(struct net_device *dev)
+
+/* The Xircom cards are picky about when certain bits in CSR6 can be
+   manipulated.  Keith Owens <kaos@ocs.com.au>. */
+
+static void outl_CSR6 (struct tulip_private *tp, u32 newcsr6)
+{
+       long ioaddr = tp->base_addr;
+       const int strict_bits = 0x0060e202;
+       int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
+       long flags;
+
+       /* really a hw lock */
+       spin_lock_irqsave (&tp->tx_lock, flags);
+
+       if (tp->chip_id != X3201_3)
+               goto out_write;
+
+       newcsr6 &= 0x726cfeca;  /* mask out the reserved CSR6 bits that always */
+       /* read 0 on the Xircom cards */
+       newcsr6 |= 0x320c0000;  /* or in the reserved bits that always read 1 */
+       currcsr6 = inl (ioaddr + CSR6);
+       if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
+           ((currcsr6 & ~0x2002) == 0))
+               goto out_write;
+
+       /* make sure the transmitter and receiver are stopped first */
+       currcsr6 &= ~0x2002;
+       while (1) {
+               csr5 = inl (ioaddr + CSR5);
+               if (csr5 == 0xffffffff)
+                       break;  /* cannot read csr5, card removed? */
+               csr5_22_20 = csr5 & 0x700000;
+               csr5_19_17 = csr5 & 0x0e0000;
+               if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
+                   (csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
+                       break;  /* both are stopped or suspended */
+               if (!--attempts) {
+                       printk (KERN_INFO "tulip.c: outl_CSR6 too many attempts,"
+                               "csr5=0x%08x\n", csr5);
+                       goto out_write;
+               }
+               outl (currcsr6, ioaddr + CSR6);
+               udelay (1);
+       }
+
+out_write:
+       /* now it is safe to change csr6 */
+       outl (newcsr6, ioaddr + CSR6);
+
+       spin_unlock_irqrestore (&tp->lock, flags);
+}
+
+
+static void tulip_up(struct net_device *dev)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        long ioaddr = dev->base_addr;
@@ -903,19 +957,16 @@ tulip_open(struct net_device *dev)
        int i;
 
        /* Wake the chip from sleep/snooze mode. */
-       if (tp->flags & HAS_PWRDWN)
+       if (tp->flags & HAS_ACPI)
                pci_write_config_dword(tp->pdev, 0x40, 0);
 
        /* On some chip revs we must set the MII/SYM port before the reset!? */
        if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))
-               outl(0x00040000, ioaddr + CSR6);
+               outl_CSR6 (tp, 0x00040000);
 
        /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
        outl(0x00000001, ioaddr + CSR0);
 
-       if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))
-               return -EAGAIN;
-
        /* Deassert reset.
           Wait the specified 50 PCI cycles after a reset by initializing
           Tx and Rx queues and the address filter list. */
@@ -924,22 +975,6 @@ tulip_open(struct net_device *dev)
        if (tulip_debug > 1)
                printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);
 
-       MOD_INC_USE_COUNT;
-
-       spin_lock_init(&tp->tx_lock);
-       tulip_init_ring(dev);
-
-#if 0
-       if (tp->chip_id == PNIC2) {
-               u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
-               u32 addr_high = cpu_to_le16(get_unaligned((u16 *)(dev->dev_addr+4)));
-               addr_high = (dev->dev_addr[4]<<8) + (dev->dev_addr[5]<<0);
-               outl((dev->dev_addr[0]<<8) + dev->dev_addr[1] +
-                        (dev->dev_addr[2]<<24) + (dev->dev_addr[3]<<16),
-                        ioaddr + 0xB0);
-               outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
-       }
-#endif
        if (tp->flags & MC_HASH_ONLY) {
                u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
                u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
@@ -1022,7 +1057,7 @@ media_picked:
                                printk(KERN_INFO "%s: Using MII transceiver %d, status "
                                           "%4.4x.\n",
                                           dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));
-                       outl(0x82020000, ioaddr + CSR6);
+                       outl_CSR6(tp, 0x82020000);
                        tp->csr6 = 0x820E0000;
                        dev->if_port = 11;
                        outl(0x0000, ioaddr + CSR13);
@@ -1072,13 +1107,13 @@ media_picked:
                select_media(dev, 1);
 
        /* Start the chip's Tx to process setup frame. */
-       outl(tp->csr6, ioaddr + CSR6);
-       outl(tp->csr6 | 0x2000, ioaddr + CSR6);
+       outl_CSR6(tp, tp->csr6);
+       outl_CSR6(tp, tp->csr6 | 0x2000);
 
        /* Enable interrupts by setting the interrupt mask. */
        outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
        outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
-       outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+       outl_CSR6(tp, tp->csr6 | 0x2002);
        outl(0, ioaddr + CSR2);         /* Rx poll demand */
 
        if (tulip_debug > 2) {
@@ -1094,11 +1129,28 @@ media_picked:
        tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
        add_timer(&tp->timer);
 
-       netif_start_queue(dev);
+       netif_device_attach(dev);
+}
+
 
+static int
+tulip_open(struct net_device *dev)
+{
+       MOD_INC_USE_COUNT;
+       
+       if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) {
+               MOD_DEC_USE_COUNT;
+               return -EBUSY;
+       }
+
+       tulip_init_ring (dev);
+       
+       tulip_up (dev);
+       
        return 0;
 }
 
+
 /* Set up the transceiver control registers for the selected media type. */
 static void select_media(struct net_device *dev, int startup)
 {
@@ -1314,7 +1366,6 @@ static void select_media(struct net_device *dev, int startup)
   */
 static int check_duplex(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        int mii_reg1, mii_reg5, negotiated, duplex;
 
@@ -1346,8 +1397,8 @@ static int check_duplex(struct net_device *dev)
                        tp->csr6 &= ~0x00400000;
                if (tp->full_duplex) tp->csr6 |= 0x0200;
                else                             tp->csr6 &= ~0x0200;
-               outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+               outl_CSR6(tp, tp->csr6 | 0x0002);
+               outl_CSR6(tp, tp->csr6 | 0x2002);
                if (tulip_debug > 0)
                        printk(KERN_INFO "%s: Setting %s-duplex based on MII"
                                   "#%d link partner capability of %4.4x.\n",
@@ -1492,8 +1543,8 @@ static void tulip_timer(unsigned long data)
                                           medianame[tp->mtable->mleaf[tp->cur_index].media]);
                        select_media(dev, 0);
                        /* Restart the transmit process. */
-                       outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-                       outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                       outl_CSR6(tp, tp->csr6 | 0x0002);
+                       outl_CSR6(tp, tp->csr6 | 0x2002);
                        next_tick = (24*HZ)/10;
                        break;
                }
@@ -1513,6 +1564,7 @@ static void tulip_timer(unsigned long data)
        add_timer(&tp->timer);
 }
 
+
 /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
    of available transceivers.  */
 static void t21142_timer(unsigned long data)
@@ -1573,8 +1625,8 @@ static void t21142_timer(unsigned long data)
                        tp->csr6 &= 0x00D5;
                        tp->csr6 |= new_csr6;
                        outl(0x0301, ioaddr + CSR12);
-                       outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-                       outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                       outl_CSR6(tp, tp->csr6 | 0x0002);
+                       outl_CSR6(tp, tp->csr6 | 0x2002);
                }
                next_tick = 3*HZ;
        }
@@ -1583,6 +1635,7 @@ static void t21142_timer(unsigned long data)
        add_timer(&tp->timer);
 }
 
+
 static void t21142_start_nway(struct net_device *dev)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -1599,7 +1652,7 @@ static void t21142_start_nway(struct net_device *dev)
        outl(0x0001, ioaddr + CSR13);
        outl(csr14, ioaddr + CSR14);
        tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
-       outl(tp->csr6, ioaddr + CSR6);
+       outl_CSR6(tp, tp->csr6);
        if (tp->mtable  &&  tp->mtable->csr15dir) {
                outl(tp->mtable->csr15dir, ioaddr + CSR15);
                outl(tp->mtable->csr15val, ioaddr + CSR15);
@@ -1608,6 +1661,7 @@ static void t21142_start_nway(struct net_device *dev)
        outl(0x1301, ioaddr + CSR12);           /* Trigger NWAY. */
 }
 
+
 static void t21142_lnk_change(struct net_device *dev, int csr5)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -1664,12 +1718,12 @@ static void t21142_lnk_change(struct net_device *dev, int csr5)
                        outl(1, ioaddr + CSR13);
                }
 #if 0                                                  /* Restart shouldn't be needed. */
-               outl(tp->csr6 | 0x0000, ioaddr + CSR6);
+               outl_CSR6(tp, tp->csr6 | 0x0000);
                if (debug > 2)
                        printk(KERN_DEBUG "%s:  Restarting Tx and Rx, CSR5 is %8.8x.\n",
                                   dev->name, inl(ioaddr + CSR5));
 #endif
-               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+               outl_CSR6(tp, tp->csr6 | 0x2002);
                if (debug > 2)
                        printk(KERN_DEBUG "%s:  Setting CSR6 %8.8x/%x CSR12 %8.8x.\n",
                                   dev->name, tp->csr6, inl(ioaddr + CSR6),
@@ -1715,11 +1769,12 @@ static void t21142_lnk_change(struct net_device *dev, int csr5)
                tp->csr6 = 0x83860000;
                outl(0x0003FF7F, ioaddr + CSR14);
                outl(0x0301, ioaddr + CSR12);
-               outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+               outl_CSR6(tp, tp->csr6 | 0x0002);
+               outl_CSR6(tp, tp->csr6 | 0x2002);
        }
 }
 
+
 static void mxic_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
@@ -1737,6 +1792,7 @@ static void mxic_timer(unsigned long data)
        }
 }
 
+
 static void pnic_do_nway(struct net_device *dev)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -1763,12 +1819,15 @@ static void pnic_do_nway(struct net_device *dev)
                                   dev->name, phy_reg, medianame[dev->if_port]);
                if (tp->csr6 != new_csr6) {
                        tp->csr6 = new_csr6;
-                       outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
-                       outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                       /* Restart Tx */
+                       outl_CSR6(tp, tp->csr6 | 0x0002);
+                       outl_CSR6(tp, tp->csr6 | 0x2002);
                        dev->trans_start = jiffies;
                }
        }
 }
+
+
 static void pnic_lnk_change(struct net_device *dev, int csr5)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -1782,7 +1841,7 @@ static void pnic_lnk_change(struct net_device *dev, int csr5)
                outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
                if (! tp->nwayset  ||  jiffies - dev->trans_start > 1*HZ) {
                        tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
-                       outl(tp->csr6, ioaddr + CSR6);
+                       outl_CSR6(tp, tp->csr6);
                        outl(0x30, ioaddr + CSR12);
                        outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
                        dev->trans_start = jiffies;
@@ -1792,6 +1851,8 @@ static void pnic_lnk_change(struct net_device *dev, int csr5)
                outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
        }
 }
+
+
 static void pnic_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
@@ -1842,8 +1903,9 @@ static void pnic_timer(unsigned long data)
                        }
                        if (tp->csr6 != new_csr6) {
                                tp->csr6 = new_csr6;
-                               outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
-                               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                               /* Restart Tx */
+                               outl_CSR6(tp, tp->csr6 | 0x0002);
+                               outl_CSR6(tp, tp->csr6 | 0x2002);
                                dev->trans_start = jiffies;
                                if (tulip_debug > 1)
                                        printk(KERN_INFO "%s: Changing PNIC configuration to %s "
@@ -1965,8 +2027,8 @@ static void tulip_tx_timeout(struct net_device *dev)
 #endif
 
        /* Stop and restart the chip's Tx processes . */
-       outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-       outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+       outl_CSR6(tp, tp->csr6 | 0x0002);
+       outl_CSR6(tp, tp->csr6 | 0x2002);
        /* Trigger an immediate transmit demand. */
        outl(0, ioaddr + CSR1);
 
@@ -2173,8 +2235,8 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                        printk(KERN_WARNING "%s: The transmitter stopped."
                                                   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
                                                   dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
-                               outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-                               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                               outl_CSR6(tp, tp->csr6 | 0x0002);
+                               outl_CSR6(tp, tp->csr6 | 0x2002);
                        }
                        spin_unlock(&tp->tx_lock);
                }
@@ -2190,14 +2252,14 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                else
                                        tp->csr6 |= 0x00200000;  /* Store-n-forward. */
                                /* Restart the transmit process. */
-                               outl(tp->csr6 | 0x0002, ioaddr + CSR6);
-                               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                               outl_CSR6(tp, tp->csr6 | 0x0002);
+                               outl_CSR6(tp, tp->csr6 | 0x2002);
                                outl(0, ioaddr + CSR1);
                        }
                        if (csr5 & RxDied) {            /* Missed a Rx frame. */
                                tp->stats.rx_errors++;
                                tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-                               outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+                               outl_CSR6(tp, tp->csr6 | 0x2002);
                        }
                        if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
                                if (tp->link_change)
@@ -2378,64 +2440,74 @@ static int tulip_rx(struct net_device *dev)
        return received;
 }
 
-static int
-tulip_close(struct net_device *dev)
+
+static void tulip_down (struct net_device *dev)
 {
        long ioaddr = dev->base_addr;
-       struct tulip_private *tp = (struct tulip_private *)dev->priv;
-       int i;
+       struct tulip_private *tp = (struct tulip_private *) dev->priv;
 
-       netif_stop_queue(dev);
+       netif_device_detach (dev);
 
-       if (tulip_debug > 1)
-               printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
-                          dev->name, inl(ioaddr + CSR5));
+       del_timer (&tp->timer);
 
        /* Disable interrupts by clearing the interrupt mask. */
-       outl(0x00000000, ioaddr + CSR7);
+       outl (0x00000000, ioaddr + CSR7);
+
        /* Stop the Tx and Rx processes. */
-       outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6);
+       outl_CSR6 (tp, inl (ioaddr + CSR6) & ~0x2002);
+
        /* 21040 -- Leave the card in 10baseT state. */
        if (tp->chip_id == DC21040)
-               outl(0x00000004, ioaddr + CSR13);
+               outl (0x00000004, ioaddr + CSR13);
 
-       if (inl(ioaddr + CSR6) != 0xffffffff)
-               tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+       if (inl (ioaddr + CSR6) != 0xffffffff)
+               tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff;
 
-       del_timer(&tp->timer);
+       dev->if_port = tp->saved_if_port;
 
-       free_irq(dev->irq, dev);
+       /* Leave the driver in snooze, not sleep, mode. */
+       if (tp->flags & HAS_ACPI)
+               pci_write_config_dword (tp->pdev, 0x40, 0x40000000);
+}
+  
+  
+static int tulip_close (struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+       struct tulip_private *tp = (struct tulip_private *) dev->priv;
+       int i;
 
-       dev->if_port = tp->saved_if_port;
+       tulip_down (dev);
+
+       if (tulip_debug > 1)
+               printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
+                       dev->name, inl (ioaddr + CSR5));
+
+       free_irq (dev->irq, dev);
 
        /* Free all the skbuffs in the Rx queue. */
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb = tp->rx_skbuff[i];
                tp->rx_skbuff[i] = 0;
-               tp->rx_ring[i].status = 0;              /* Not owned by Tulip chip. */
+               tp->rx_ring[i].status = 0;      /* Not owned by Tulip chip. */
                tp->rx_ring[i].length = 0;
-               tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
+               tp->rx_ring[i].buffer1 = 0xBADF00D0;    /* An invalid address. */
                if (skb) {
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb (skb);
                }
        }
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (tp->tx_skbuff[i])
-                       dev_kfree_skb(tp->tx_skbuff[i]);
+                       dev_kfree_skb (tp->tx_skbuff[i]);
                tp->tx_skbuff[i] = 0;
        }
 
-       /* Leave the driver in snooze, not sleep, mode. */
-       if (tp->flags & HAS_PWRDWN)
-               pci_write_config_dword(tp->pdev, 0x40, 0x40000000);
-
        MOD_DEC_USE_COUNT;
 
        return 0;
 }
 
-static struct enet_statistics *
-tulip_get_stats(struct net_device *dev)
+static struct enet_statistics *tulip_get_stats(struct net_device *dev)
 {
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        long ioaddr = dev->base_addr;
@@ -2672,7 +2744,7 @@ static void set_rx_mode(struct net_device *dev)
                        outl(0, ioaddr + CSR1);
                }
        }
-       outl(csr6 | 0x0000, ioaddr + CSR6);
+       outl_CSR6(tp, csr6 | 0x0000);
 }
 
 
@@ -2697,10 +2769,10 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        board_idx++;
 
        if (tulip_debug > 0  &&  did_version++ == 0)
-               printk(KERN_INFO "%s", version);
+               printk (KERN_INFO "%s", version);
 
         if( pdev->subsystem_vendor == 0x1376 ){
-               printk(KERN_ERR "tulip: skipping LMC card.\n");
+               printk (KERN_ERR PFX "skipping LMC card.\n");
                return -ENODEV;
        }
        
@@ -2709,15 +2781,25 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 
        /* Make certain the data structures are quadword aligned. */
        dev = init_etherdev (NULL, sizeof (*tp));
-       if (!dev)
+       if (!dev) {
+               printk (KERN_ERR PFX "unable to allocate ether device, aborting\n");
                return -ENOMEM;
+       }
 
        /* We do a request_region() only to register /proc/ioports info. */
        /* Note that proper size is tulip_tbl[chip_idx].chip_name, but... */
-       if (!request_region (ioaddr, tulip_tbl[chip_idx].io_size, dev->name))
+       if (!request_region (ioaddr, tulip_tbl[chip_idx].io_size, dev->name)) {
+               printk (KERN_ERR PFX "unable to allocate ether device, aborting\n");
                goto err_out_free_netdev;
+       }
+
+       if (pci_enable_device(pdev)) {
+               printk (KERN_ERR PFX "cannot enable PCI device (id %04x:%04x, bus %d, devfn %d), aborting\n",
+                       pdev->vendor, pdev->device,
+                       pdev->bus->number, pdev->devfn);
+               goto err_out_free_netdev;
+       }
 
-       pci_enable_device(pdev);
        pci_set_master(pdev);
 
        tp = dev->priv;
@@ -2725,16 +2807,11 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 
        pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
 
-       /* Bring the 21041/21143 out of sleep mode.
-          Caution: Snooze mode does not work with some boards! */
-       if (tulip_tbl[chip_idx].flags & HAS_PWRDWN)
-               pci_write_config_dword(pdev, 0x40, 0x00000000);
-
        printk(KERN_INFO "%s: %s rev %d at %#3lx,",
                   dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
 
        /* Stop the chip's Tx and Rx processes. */
-       outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6);
+       outl_CSR6(tp, inl(ioaddr + CSR6) & ~0x2002);
        /* Clear the missed-packet counter. */
        (volatile int)inl(ioaddr + CSR8);
 
@@ -2836,6 +2913,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        tp->flags = tulip_tbl[chip_idx].flags;
        tp->csr0 = csr0;
        tp->pdev = pdev;
+       tp->base_addr = dev->base_addr;
 
        /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
           And the ASIX must have a burst limit or horrible things happen. */
@@ -2854,6 +2932,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 #ifdef TULIP_NO_MEDIA_SWITCH
        tp->medialock = 1;
 #endif
+       tp->tx_lock = SPIN_LOCK_UNLOCKED;
 
        /* The lower four bits are the media type. */
        if (board_idx >= 0  &&  board_idx < MAX_UNITS) {
@@ -2963,7 +3042,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                outl(0x00000000, ioaddr + CSR13);
                outl(0xFFFFFFFF, ioaddr + CSR14);
                outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
-               outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
+               outl_CSR6(tp, inl(ioaddr + CSR6) | 0x0200);
                outl(0x0000EF05, ioaddr + CSR13);
                break;
        case DC21040:
@@ -2977,10 +3056,10 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        case DC21142:
        case PNIC2:
                if (tp->mii_cnt  ||  media_cap[dev->if_port] & MediaIsMII) {
-                       outl(0x82020000, ioaddr + CSR6);
+                       outl_CSR6(tp, 0x82020000);
                        outl(0x0000, ioaddr + CSR13);
                        outl(0x0000, ioaddr + CSR14);
-                       outl(0x820E0000, ioaddr + CSR6);
+                       outl_CSR6(tp, 0x820E0000);
                } else
                        t21142_start_nway(dev);
                break;
@@ -2988,19 +3067,19 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                if ( ! tp->mii_cnt) {
                        tp->nway = 1;
                        tp->nwayset = 0;
-                       outl(0x00420000, ioaddr + CSR6);
+                       outl_CSR6(tp, 0x00420000);
                        outl(0x30, ioaddr + CSR12);
-                       outl(0x0001F078, ioaddr + 0xB8);
-                       outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+                       outl_CSR6(tp, 0x0001F078);
+                       outl_CSR6(tp, 0x0201F078); /* Turn on autonegotiation. */
                }
                break;
        case MX98713: case COMPEX9881:
-               outl(0x00000000, ioaddr + CSR6);
+               outl_CSR6(tp, 0x00000000);
                outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
                outl(0x00000001, ioaddr + CSR13);
                break;
        case MX98715: case MX98725:
-               outl(0x01a80000, ioaddr + CSR6);
+               outl_CSR6(tp, 0x01a80000);
                outl(0xFFFFFFFF, ioaddr + CSR14);
                outl(0x00001000, ioaddr + CSR12);
                break;
@@ -3009,7 +3088,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                break;
        }
 
-       if (tulip_tbl[chip_idx].flags & HAS_PWRDWN)
+       /* put the chip in snooze mode until opened */
+       if (tulip_tbl[chip_idx].flags & HAS_ACPI)
                pci_write_config_dword(pdev, 0x40, 0x40000000);
 
        return 0;
@@ -3025,20 +3105,8 @@ static void tulip_suspend (struct pci_dev *pdev)
 {
        struct net_device *dev = pdev->driver_data;
 
-       if (dev) {
-               long ioaddr = dev->base_addr;
-               struct tulip_private *tp = (struct tulip_private *)dev->priv;
-               int csr6 = inl(ioaddr + CSR6);
-               /* Disable interrupts, stop the chip, gather stats. */
-               if (csr6 != 0xffffffff) {
-                       outl(0x00000000, ioaddr + CSR7);
-                       outl(csr6 & ~0x2002, ioaddr + CSR6);
-                       tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-               }
-               tulip_close(dev);
-               /* Put the 21143 into sleep mode. */
-               pci_write_config_dword(pdev, 0x40,0x80000000);
-       }
+       if (dev && netif_device_present (dev))
+               tulip_down (dev);
 }
 
 
@@ -3046,10 +3114,8 @@ static void tulip_resume (struct pci_dev *pdev)
 {
        struct net_device *dev = pdev->driver_data;
 
-       if (dev) {
-               pci_write_config_dword(pdev, 0x40, 0x0000);
-               tulip_open(dev);
-       }
+       if (dev && !netif_device_present (dev))
+               tulip_up (dev);
 }
 
 
@@ -3079,11 +3145,7 @@ static struct pci_driver tulip_driver = {
 
 static int __init tulip_init (void)
 {
-       if (pci_register_driver (&tulip_driver) > 0)
-               return 0;
-
-       pci_unregister_driver (&tulip_driver);
-       return -ENODEV;
+       return pci_module_init (&tulip_driver);
 }
 
 
index 8b8a1f8cea49dab7d416b742e18c613293156df2..7025263d40a9427967a37b658c4454e6ed9f2545 100644 (file)
@@ -82,13 +82,14 @@ static const char *version =
 #else
 #define CB_OPT ""
 #endif
-#if defined(CONFIG_APM) || defined(CONFIG_ACPI)
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) || defined(CONFIG_ACPI)
 #define APM_OPT " [apm]"
 #else
 #define APM_OPT ""
 #endif
 #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && \
-    !defined(CONFIG_APM) && !defined(CONFIG_ACPI)
+    !defined(CONFIG_APM) && !defined(CONFIG_APM_MODULE) && \
+    !defined(CONFIG_ACPI)
 #define OPTIONS " none"
 #else
 #define OPTIONS PCI_OPT CB_OPT APM_OPT
@@ -124,7 +125,7 @@ static int cis_speed                = 300;  /* ns */
 static int io_speed            = 0;    /* ns */
 
 /* Optional features */
-#if defined(CONFIG_APM) || defined(CONFIG_ACPI)
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) || defined(CONFIG_ACPI)
 static int do_apm              = 1;
 MODULE_PARM(do_apm, "i");
 #else
index 33e38b187855542ad4a0d5ee470045951efcab1c..f897cba9a87d32fe683de18040f6dd85aeddcbdc 100644 (file)
@@ -11,7 +11,7 @@
    Copyright 1992 - 2000 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Fri Feb 11 19:43:57 2000 by makisara@kai.makisara.local
+   Last modified: Sat Feb 19 17:22:34 2000 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
@@ -169,16 +169,15 @@ static int st_int_ioctl(struct inode *inode, unsigned int cmd_in,
 \f
 
 
-
 /* Convert the result to success code */
-static int st_chk_result(Scsi_Cmnd * SCpnt)
+static int st_chk_result(Scsi_Request * SRpnt)
 {
-       int dev = TAPE_NR(SCpnt->request.rq_dev);
-       int result = SCpnt->result;
-       unsigned char *sense = SCpnt->sense_buffer, scode;
+       int dev = TAPE_NR(SRpnt->sr_request.rq_dev);
+       int result = SRpnt->sr_result;
+       unsigned char *sense = SRpnt->sr_sense_buffer, scode;
        DEB(const char *stp;)
 
-       if (!result /* && SCpnt->sense_buffer[0] == 0 */ )
+       if (!result)
                return 0;
 
        if (driver_byte(result) & DRIVER_SENSE)
@@ -192,11 +191,11 @@ static int st_chk_result(Scsi_Cmnd * SCpnt)
         if (debugging) {
                 printk(ST_DEB_MSG "st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
                       dev, result,
-                      SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
-                      SCpnt->data_cmnd[3], SCpnt->data_cmnd[4], SCpnt->data_cmnd[5],
-                      SCpnt->request_bufflen);
+                      SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
+                      SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
+                      SRpnt->sr_bufflen);
                if (driver_byte(result) & DRIVER_SENSE)
-                       print_sense("st", SCpnt);
+                       print_req_sense("st", SRpnt);
        } else ) /* end DEB */
                if (!(driver_byte(result) & DRIVER_SENSE) ||
                    ((sense[0] & 0x70) == 0x70 &&
@@ -205,11 +204,11 @@ static int st_chk_result(Scsi_Cmnd * SCpnt)
                      /* scode != UNIT_ATTENTION && */
                     scode != BLANK_CHECK &&
                     scode != VOLUME_OVERFLOW &&
-                    SCpnt->data_cmnd[0] != MODE_SENSE &&
-                    SCpnt->data_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
+                    SRpnt->sr_cmnd[0] != MODE_SENSE &&
+                    SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) {   /* Abnormal conditions for tape */
                if (driver_byte(result) & DRIVER_SENSE) {
                        printk(KERN_WARNING "st%d: Error with sense data: ", dev);
-                       print_sense("st", SCpnt);
+                       print_req_sense("st", SRpnt);
                } else
                        printk(KERN_WARNING
                               "st%d: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
@@ -220,8 +219,8 @@ static int st_chk_result(Scsi_Cmnd * SCpnt)
        if ((sense[0] & 0x70) == 0x70 &&
            scode == RECOVERED_ERROR
 #if ST_RECOVERED_WRITE_FATAL
-           && SCpnt->data_cmnd[0] != WRITE_6
-           && SCpnt->data_cmnd[0] != WRITE_FILEMARKS
+           && SRpnt->sr_cmnd[0] != WRITE_6
+           && SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
 #endif
            ) {
                scsi_tapes[dev].recover_count++;
@@ -229,9 +228,9 @@ static int st_chk_result(Scsi_Cmnd * SCpnt)
 
                 DEB(
                if (debugging) {
-                       if (SCpnt->data_cmnd[0] == READ_6)
+                       if (SRpnt->sr_cmnd[0] == READ_6)
                                stp = "read";
-                       else if (SCpnt->data_cmnd[0] == WRITE_6)
+                       else if (SRpnt->sr_cmnd[0] == WRITE_6)
                                stp = "write";
                        else
                                stp = "ioctl";
@@ -268,13 +267,13 @@ static void st_sleep_done(Scsi_Cmnd * SCpnt)
                                remainder = 0;
                        if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
                            remainder > 0)
-                               (STp->buffer)->last_result = SCpnt->result;     /* Error */
+                               (STp->buffer)->midlevel_result = SCpnt->result; /* Error */
                        else
-                               (STp->buffer)->last_result = INT_MAX;   /* OK */
+                               (STp->buffer)->midlevel_result = INT_MAX;       /* OK */
                } else
-                       (STp->buffer)->last_result = SCpnt->result;
+                       (STp->buffer)->midlevel_result = SCpnt->result;
                SCpnt->request.rq_status = RQ_SCSI_DONE;
-               (STp->buffer)->last_SCpnt = SCpnt;
+               (STp->buffer)->last_SRpnt = SCpnt->sc_request;
                DEB( STp->write_pending = 0; )
 
                up(SCpnt->request.sem);
@@ -289,47 +288,49 @@ static void st_sleep_done(Scsi_Cmnd * SCpnt)
 /* Do the scsi command. Waits until command performed if do_wait is true.
    Otherwise write_behind_check() is used to check that the command
    has finished. */
-static Scsi_Cmnd *
- st_do_scsi(Scsi_Cmnd * SCpnt, Scsi_Tape * STp, unsigned char *cmd, int bytes,
-           int timeout, int retries, int do_wait)
+static Scsi_Request *
+ st_do_scsi(Scsi_Request * SRpnt, Scsi_Tape * STp, unsigned char *cmd, int bytes,
+           int direction, int timeout, int retries, int do_wait)
 {
        unsigned char *bp;
 
-       if (SCpnt == NULL)
-               SCpnt = scsi_allocate_device(STp->device, 1, TRUE);
-               if (SCpnt == NULL) {
+       if (SRpnt == NULL)
+               SRpnt = scsi_allocate_request(STp->device);
+               if (SRpnt == NULL) {
                        DEBC( printk(KERN_ERR "st%d: Can't get SCSI request.\n",
                                     TAPE_NR(STp->devt)); );
                        if (signal_pending(current))
-                               (STp->buffer)->last_result_fatal = (-EINTR);
+                               (STp->buffer)->syscall_result = (-EINTR);
                        else
-                               (STp->buffer)->last_result_fatal = (-EBUSY);
+                               (STp->buffer)->syscall_result = (-EBUSY);
                        return NULL;
                }
 
-       cmd[1] |= (SCpnt->lun << 5) & 0xe0;
+       cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
        init_MUTEX_LOCKED(&STp->sem);
-       SCpnt->use_sg = (bytes > (STp->buffer)->sg[0].length) ?
+       SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
            (STp->buffer)->use_sg : 0;
-       if (SCpnt->use_sg) {
+       if (SRpnt->sr_use_sg) {
                bp = (char *) &((STp->buffer)->sg[0]);
-               if ((STp->buffer)->sg_segs < SCpnt->use_sg)
-                       SCpnt->use_sg = (STp->buffer)->sg_segs;
+               if ((STp->buffer)->sg_segs < SRpnt->sr_use_sg)
+                       SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
        } else
                bp = (STp->buffer)->b_data;
-       SCpnt->cmd_len = 0;
-       SCpnt->request.sem = &(STp->sem);
-       SCpnt->request.rq_status = RQ_SCSI_BUSY;
-       SCpnt->request.rq_dev = STp->devt;
+       SRpnt->sr_data_direction = direction;
+       SRpnt->sr_cmd_len = 0;
+       SRpnt->sr_request.sem = &(STp->sem);
+       SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
+       SRpnt->sr_request.rq_dev = STp->devt;
 
-       scsi_do_cmd(SCpnt, (void *) cmd, bp, bytes,
+       scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
                    st_sleep_done, timeout, retries);
 
        if (do_wait) {
-               down(SCpnt->request.sem);
-               (STp->buffer)->last_result_fatal = st_chk_result(SCpnt);
+               down(SRpnt->sr_request.sem);
+               SRpnt->sr_request.sem = NULL;
+               (STp->buffer)->syscall_result = st_chk_result(SRpnt);
        }
-       return SCpnt;
+       return SRpnt;
 }
 
 
@@ -349,9 +350,10 @@ static void write_behind_check(Scsi_Tape * STp)
         ) /* end DEB */
 
        down(&(STp->sem));
+       (STp->buffer)->last_SRpnt->sr_request.sem = NULL;
 
-       (STp->buffer)->last_result_fatal = st_chk_result((STp->buffer)->last_SCpnt);
-       scsi_release_command((STp->buffer)->last_SCpnt);
+       (STp->buffer)->syscall_result = st_chk_result((STp->buffer)->last_SRpnt);
+       scsi_release_request((STp->buffer)->last_SRpnt);
 
        if (STbuffer->writing < STbuffer->buffer_bytes)
 #if 0
@@ -380,7 +382,7 @@ static void write_behind_check(Scsi_Tape * STp)
    it messes up the block number). */
 static int cross_eof(Scsi_Tape * STp, int forward)
 {
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        unsigned char cmd[MAX_COMMAND_SIZE];
 
        cmd[0] = SPACE;
@@ -395,18 +397,19 @@ static int cross_eof(Scsi_Tape * STp, int forward)
         DEBC(printk(ST_DEB_MSG "st%d: Stepping over filemark %s.\n",
                   TAPE_NR(STp->devt), forward ? "forward" : "backward"));
 
-       SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_RETRIES, TRUE);
-       if (!SCpnt)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,
+                          STp->timeout, MAX_RETRIES, TRUE);
+       if (!SRpnt)
+               return (STp->buffer)->syscall_result;
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
 
-       if ((STp->buffer)->last_result != 0)
+       if ((STp->buffer)->midlevel_result != 0)
                printk(KERN_ERR "st%d: Stepping over filemark %s failed.\n",
                   TAPE_NR(STp->devt), forward ? "forward" : "backward");
 
-       return (STp->buffer)->last_result_fatal;
+       return (STp->buffer)->syscall_result;
 }
 
 
@@ -416,16 +419,16 @@ static int flush_write_buffer(Scsi_Tape * STp)
        int offset, transfer, blks;
        int result;
        unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        ST_partstat *STps;
 
        if ((STp->buffer)->writing) {
                write_behind_check(STp);
-               if ((STp->buffer)->last_result_fatal) {
+               if ((STp->buffer)->syscall_result) {
                         DEBC(printk(ST_DEB_MSG
                                        "st%d: Async write error (flush) %x.\n",
-                                      TAPE_NR(STp->devt), (STp->buffer)->last_result))
-                       if ((STp->buffer)->last_result == INT_MAX)
+                                      TAPE_NR(STp->devt), (STp->buffer)->midlevel_result))
+                       if ((STp->buffer)->midlevel_result == INT_MAX)
                                return (-ENOSPC);
                        return (-EIO);
                }
@@ -452,16 +455,16 @@ static int flush_write_buffer(Scsi_Tape * STp)
                cmd[3] = blks >> 8;
                cmd[4] = blks;
 
-               SCpnt = st_do_scsi(NULL, STp, cmd, transfer, STp->timeout,
-                                   MAX_WRITE_RETRIES, TRUE);
-               if (!SCpnt)
-                       return (STp->buffer)->last_result_fatal;
+               SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE,
+                                  STp->timeout, MAX_WRITE_RETRIES, TRUE);
+               if (!SRpnt)
+                       return (STp->buffer)->syscall_result;
 
                STps = &(STp->ps[STp->partition]);
-               if ((STp->buffer)->last_result_fatal != 0) {
-                       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-                           (SCpnt->sense_buffer[2] & 0x40) &&
-                           (SCpnt->sense_buffer[2] & 0x0f) == NO_SENSE) {
+               if ((STp->buffer)->syscall_result != 0) {
+                       if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
+                           (SRpnt->sr_sense_buffer[2] & 0x40) &&
+                           (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
                                STp->dirty = 0;
                                (STp->buffer)->buffer_bytes = 0;
                                result = (-ENOSPC);
@@ -477,8 +480,8 @@ static int flush_write_buffer(Scsi_Tape * STp)
                        STp->dirty = 0;
                        (STp->buffer)->buffer_bytes = 0;
                }
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
        }
        return result;
 }
@@ -585,7 +588,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
        int i, need_dma_buffer, new_session = FALSE;
        int retval;
        unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
@@ -636,7 +639,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                STp->buffer = st_buffers[i];
        (STp->buffer)->in_use = 1;
        (STp->buffer)->writing = 0;
-       (STp->buffer)->last_result_fatal = 0;
+       (STp->buffer)->syscall_result = 0;
        (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
 
        /* Compute the usable buffer size for this SCSI adapter */
@@ -663,24 +666,24 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
        memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
        cmd[0] = TEST_UNIT_READY;
 
-       SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES,
-                          TRUE);
-       if (!SCpnt) {
-               retval = (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->long_timeout,
+                          MAX_READY_RETRIES, TRUE);
+       if (!SRpnt) {
+               retval = (STp->buffer)->syscall_result;
                goto err_out;
        }
 
-       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-           (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {        /* New media? */
+       if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
+           (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {     /* New media? */
 
                /* Flush the queued UNIT ATTENTION sense data */
                for (i=0; i < 10; i++) {
                         memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
                         cmd[0] = TEST_UNIT_READY;
-                        SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, STp->long_timeout,
-                                           MAX_READY_RETRIES, TRUE);
-                        if ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
-                            (SCpnt->sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
+                        SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
+                                          STp->long_timeout, MAX_READY_RETRIES, TRUE);
+                        if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
+                            (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
                                 break;
                }
 
@@ -701,16 +704,16 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                new_session = TRUE;
        }
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                if ((STp->device)->scsi_level >= SCSI_2 &&
-                   (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-                   (SCpnt->sense_buffer[2] & 0x0f) == NOT_READY &&
-                   SCpnt->sense_buffer[12] == 0x3a) {  /* Check ASC */
+                   (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
+                   (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
+                   SRpnt->sr_sense_buffer[12] == 0x3a) {       /* Check ASC */
                        STp->ready = ST_NO_TAPE;
                } else
                        STp->ready = ST_NOT_READY;
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
                STp->density = 0;       /* Clear the erroneous "residue" */
                STp->write_prot = 0;
                STp->block_size = 0;
@@ -726,10 +729,10 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
                cmd[0] = READ_BLOCK_LIMITS;
 
-               SCpnt = st_do_scsi(SCpnt, STp, cmd, 6, STp->timeout, MAX_READY_RETRIES,
-                                   TRUE);
+               SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->timeout,
+                                  MAX_READY_RETRIES, TRUE);
 
-               if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
+               if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) {
                        STp->max_block = ((STp->buffer)->b_data[1] << 16) |
                            ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
                        STp->min_block = ((STp->buffer)->b_data[4] << 8) |
@@ -749,12 +752,13 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
        cmd[0] = MODE_SENSE;
        cmd[4] = 12;
 
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, 12, STp->timeout, MAX_READY_RETRIES, TRUE);
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->timeout,
+                          MAX_READY_RETRIES, TRUE);
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: No Mode Sense.\n", dev));
                STp->block_size = ST_DEFAULT_BLOCK;     /* Educated guess (?) */
-               (STp->buffer)->last_result_fatal = 0;   /* Prevent error propagation */
+               (STp->buffer)->syscall_result = 0;      /* Prevent error propagation */
                STp->drv_write_prot = 0;
        } else {
                 DEBC(printk(ST_DEB_MSG
@@ -779,14 +783,14 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                    !enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {
                        printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n",
                                dev, STp->block_size);
-                       scsi_release_command(SCpnt);
+                       scsi_release_request(SRpnt);
                        retval = (-EIO);
                        goto err_out;
                }
                STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
        }
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
         STp->inited = TRUE;
 
        if (STp->block_size > 0)
@@ -863,7 +867,7 @@ static int scsi_tape_flush(struct file *filp)
 {
        int result = 0, result2;
        static unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
@@ -907,29 +911,29 @@ static int scsi_tape_flush(struct file *filp)
                cmd[0] = WRITE_FILEMARKS;
                cmd[4] = 1 + STp->two_fm;
 
-               SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout,
-                                  MAX_WRITE_RETRIES, TRUE);
-               if (!SCpnt) {
-                       result = (STp->buffer)->last_result_fatal;
+               SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,
+                                  STp->timeout, MAX_WRITE_RETRIES, TRUE);
+               if (!SRpnt) {
+                       result = (STp->buffer)->syscall_result;
                        goto out;
                }
 
-               if ((STp->buffer)->last_result_fatal != 0 &&
-                   ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
-                    (SCpnt->sense_buffer[2] & 0x4f) != 0x40 ||
-                    ((SCpnt->sense_buffer[0] & 0x80) != 0 &&
-                     (SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
-                      SCpnt->sense_buffer[5] |
-                      SCpnt->sense_buffer[6]) == 0))) {
+               if ((STp->buffer)->syscall_result != 0 &&
+                   ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
+                    (SRpnt->sr_sense_buffer[2] & 0x4f) != 0x40 ||
+                    ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 &&
+                     (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] |
+                      SRpnt->sr_sense_buffer[5] |
+                      SRpnt->sr_sense_buffer[6]) == 0))) {
                        /* Filter out successful write at EOM */
-                       scsi_release_command(SCpnt);
-                       SCpnt = NULL;
+                       scsi_release_request(SRpnt);
+                       SRpnt = NULL;
                        printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
                        if (result == 0)
                                result = (-EIO);
                } else {
-                       scsi_release_command(SCpnt);
-                       SCpnt = NULL;
+                       scsi_release_request(SRpnt);
+                       SRpnt = NULL;
                        if (STps->drv_file >= 0)
                                STps->drv_file++;
                        STps->drv_block = 0;
@@ -1016,7 +1020,7 @@ static ssize_t
        int doing_write = 0;
        static unsigned char cmd[MAX_COMMAND_SIZE];
        const char *b_point;
-       Scsi_Cmnd *SCpnt = NULL;
+       Scsi_Request *SRpnt = NULL;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
@@ -1111,10 +1115,10 @@ static ssize_t
 
        if ((STp->buffer)->writing) {
                write_behind_check(STp);
-               if ((STp->buffer)->last_result_fatal) {
+               if ((STp->buffer)->syscall_result) {
                         DEBC(printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n",
-                                    dev, (STp->buffer)->last_result));
-                       if ((STp->buffer)->last_result == INT_MAX)
+                                    dev, (STp->buffer)->midlevel_result));
+                       if ((STp->buffer)->midlevel_result == INT_MAX)
                                STps->eof = ST_EOM_OK;
                        else
                                STps->eof = ST_EOM_ERROR;
@@ -1168,9 +1172,9 @@ static ssize_t
 
                i = append_to_buffer(b_point, STp->buffer, do_count);
                if (i) {
-                       if (SCpnt != NULL) {
-                               scsi_release_command(SCpnt);
-                               SCpnt = NULL;
+                       if (SRpnt != NULL) {
+                               scsi_release_request(SRpnt);
+                               SRpnt = NULL;
                        }
                        return i;
                }
@@ -1186,23 +1190,23 @@ static ssize_t
                cmd[3] = blks >> 8;
                cmd[4] = blks;
 
-               SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout,
-                                  MAX_WRITE_RETRIES, TRUE);
-               if (!SCpnt)
-                       return (STp->buffer)->last_result_fatal;
+               SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
+                                  STp->timeout, MAX_WRITE_RETRIES, TRUE);
+               if (!SRpnt)
+                       return (STp->buffer)->syscall_result;
 
-               if ((STp->buffer)->last_result_fatal != 0) {
+               if ((STp->buffer)->syscall_result != 0) {
                         DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev));
-                       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-                           (SCpnt->sense_buffer[2] & 0x40)) {
+                       if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
+                           (SRpnt->sr_sense_buffer[2] & 0x40)) {
                                if (STp->block_size != 0 &&
-                                    (SCpnt->sense_buffer[0] & 0x80) != 0)
-                                       transfer = (SCpnt->sense_buffer[3] << 24) |
-                                           (SCpnt->sense_buffer[4] << 16) |
-                                           (SCpnt->sense_buffer[5] << 8) |
-                                                SCpnt->sense_buffer[6];
+                                    (SRpnt->sr_sense_buffer[0] & 0x80) != 0)
+                                       transfer = (SRpnt->sr_sense_buffer[3] << 24) |
+                                           (SRpnt->sr_sense_buffer[4] << 16) |
+                                           (SRpnt->sr_sense_buffer[5] << 8) |
+                                                SRpnt->sr_sense_buffer[6];
                                else if (STp->block_size == 0 &&
-                                        (SCpnt->sense_buffer[2] & 0x0f) ==
+                                        (SRpnt->sr_sense_buffer[2] & 0x0f) ==
                                          VOLUME_OVERFLOW)
                                        transfer = do_count;
                                else
@@ -1239,8 +1243,8 @@ static ssize_t
                                retval = (-EIO);
                        }
 
-                       scsi_release_command(SCpnt);
-                       SCpnt = NULL;
+                       scsi_release_request(SRpnt);
+                       SRpnt = NULL;
                        (STp->buffer)->buffer_bytes = 0;
                        STp->dirty = 0;
                        if (count < total)
@@ -1264,9 +1268,9 @@ static ssize_t
                STp->dirty = 1;
                i = append_to_buffer(b_point, STp->buffer, count);
                if (i) {
-                       if (SCpnt != NULL) {
-                               scsi_release_command(SCpnt);
-                               SCpnt = NULL;
+                       if (SRpnt != NULL) {
+                               scsi_release_request(SRpnt);
+                               SRpnt = NULL;
                        }
                        return i;
                }
@@ -1274,10 +1278,10 @@ static ssize_t
                count = 0;
        }
 
-       if (doing_write && (STp->buffer)->last_result_fatal != 0) {
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
-               return (STp->buffer)->last_result_fatal;
+       if (doing_write && (STp->buffer)->syscall_result != 0) {
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
+               return (STp->buffer)->syscall_result;
        }
 
        if (STm->do_async_writes &&
@@ -1302,14 +1306,15 @@ static ssize_t
                cmd[4] = blks;
                DEB( STp->write_pending = 1; )
 
-               SCpnt = st_do_scsi(SCpnt, STp, cmd, (STp->buffer)->writing, STp->timeout,
+               SRpnt = st_do_scsi(SRpnt, STp, cmd, (STp->buffer)->writing,
+                                  SCSI_DATA_WRITE, STp->timeout,
                                   MAX_WRITE_RETRIES, FALSE);
-               if (SCpnt == NULL)
-                       return (STp->buffer)->last_result_fatal;
+               if (SRpnt == NULL)
+                       return (STp->buffer)->syscall_result;
 
-       } else if (SCpnt != NULL) {
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+       } else if (SRpnt != NULL) {
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
        }
        STps->at_sm &= (total == 0);
        if (total > 0)
@@ -1321,11 +1326,11 @@ static ssize_t
 /* Read data from the tape. Returns zero in the normal case, one if the
    eof status has changed, and the negative error code in case of a
    fatal error. Otherwise updates the buffer and the eof state. */
-static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
+static long read_tape(struct inode *inode, long count, Scsi_Request ** aSRpnt)
 {
        int transfer, blks, bytes;
        static unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
@@ -1362,49 +1367,51 @@ static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
        cmd[3] = blks >> 8;
        cmd[4] = blks;
 
-       SCpnt = *aSCpnt;
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, STp->timeout, MAX_RETRIES, TRUE);
-       *aSCpnt = SCpnt;
-       if (!SCpnt)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = *aSRpnt;
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ,
+                          STp->timeout, MAX_RETRIES, TRUE);
+       *aSRpnt = SRpnt;
+       if (!SRpnt)
+               return (STp->buffer)->syscall_result;
 
        (STp->buffer)->read_pointer = 0;
        STps->at_sm = 0;
 
        /* Something to check */
-       if ((STp->buffer)->last_result_fatal) {
+       if ((STp->buffer)->syscall_result) {
                retval = 1;
                DEBC(printk(ST_DEB_MSG "st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
                             dev,
-                            SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
-                            SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
-                            SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
-                            SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]));
-               if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) {  /* extended sense */
+                            SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
+                            SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
+                            SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
+                            SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));
+               if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {       /* extended sense */
 
-                       if ((SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK)
-                               SCpnt->sense_buffer[2] &= 0xcf; /* No need for EOM in this case */
+                       if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
+                               SRpnt->sr_sense_buffer[2] &= 0xcf;      /* No need for EOM in this case */
 
-                       if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
+                       if ((SRpnt->sr_sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
                                /* Compute the residual count */
-                               if ((SCpnt->sense_buffer[0] & 0x80) != 0)
-                                       transfer = (SCpnt->sense_buffer[3] << 24) |
-                                           (SCpnt->sense_buffer[4] << 16) |
-                                           (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
+                               if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
+                                       transfer = (SRpnt->sr_sense_buffer[3] << 24) |
+                                           (SRpnt->sr_sense_buffer[4] << 16) |
+                                           (SRpnt->sr_sense_buffer[5] << 8) |
+                                           SRpnt->sr_sense_buffer[6];
                                else
                                        transfer = 0;
                                if (STp->block_size == 0 &&
-                                   (SCpnt->sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
+                                   (SRpnt->sr_sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
                                        transfer = bytes;
 
-                               if (SCpnt->sense_buffer[2] & 0x20) {    /* ILI */
+                               if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */
                                        if (STp->block_size == 0) {
                                                if (transfer <= 0)
                                                        transfer = 0;
                                                (STp->buffer)->buffer_bytes = bytes - transfer;
                                        } else {
-                                               scsi_release_command(SCpnt);
-                                               SCpnt = *aSCpnt = NULL;
+                                               scsi_release_request(SRpnt);
+                                               SRpnt = *aSRpnt = NULL;
                                                if (transfer == blks) { /* We did not get anything, error */
                                                        printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
                                                        if (STps->drv_block >= 0)
@@ -1423,7 +1430,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
                                                if (st_int_ioctl(inode, MTBSR, 1))
                                                        return (-EIO);
                                        }
-                               } else if (SCpnt->sense_buffer[2] & 0x80) {     /* FM overrides EOM */
+                               } else if (SRpnt->sr_sense_buffer[2] & 0x80) {  /* FM overrides EOM */
                                        if (STps->eof != ST_FM_HIT)
                                                STps->eof = ST_FM_HIT;
                                        else
@@ -1436,7 +1443,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
                                         DEBC(printk(ST_DEB_MSG
                                                     "st%d: EOF detected (%d bytes read).\n",
                                                     dev, (STp->buffer)->buffer_bytes));
-                               } else if (SCpnt->sense_buffer[2] & 0x40) {
+                               } else if (SRpnt->sr_sense_buffer[2] & 0x40) {
                                        if (STps->eof == ST_FM)
                                                STps->eof = ST_EOD_1;
                                        else
@@ -1457,7 +1464,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
                                             "st%d: Tape error while reading.\n", dev));
                                STps->drv_block = (-1);
                                if (STps->eof == ST_FM &&
-                                   (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
+                                   (SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) {
                                         DEBC(printk(ST_DEB_MSG
                                                     "st%d: Zero returned for first BLANK CHECK after EOF.\n",
                                                     dev));
@@ -1468,7 +1475,7 @@ static long read_tape(struct inode *inode, long count, Scsi_Cmnd ** aSCpnt)
                }
                /* End of extended sense test */ 
                else {          /* Non-extended sense */
-                       retval = (STp->buffer)->last_result_fatal;
+                       retval = (STp->buffer)->syscall_result;
                }
 
        }
@@ -1494,7 +1501,7 @@ static ssize_t
        ssize_t total;
        ssize_t i, transfer;
        int special;
-       Scsi_Cmnd *SCpnt = NULL;
+       Scsi_Request *SRpnt = NULL;
        Scsi_Tape *STp;
        ST_mode *STm;
        ST_partstat *STps;
@@ -1587,10 +1594,10 @@ static ssize_t
 
                /* Get new data if the buffer is empty */
                if ((STp->buffer)->buffer_bytes == 0) {
-                       special = read_tape(inode, count - total, &SCpnt);
+                       special = read_tape(inode, count - total, &SRpnt);
                        if (special < 0) {      /* No need to continue read */
-                               if (SCpnt != NULL) {
-                                       scsi_release_command(SCpnt);
+                               if (SRpnt != NULL) {
+                                       scsi_release_request(SRpnt);
                                }
                                return special;
                        }
@@ -1609,9 +1616,9 @@ static ssize_t
                            (STp->buffer)->buffer_bytes : count - total;
                        i = from_buffer(STp->buffer, buf, transfer);
                        if (i) {
-                               if (SCpnt != NULL) {
-                                       scsi_release_command(SCpnt);
-                                       SCpnt = NULL;
+                               if (SRpnt != NULL) {
+                                       scsi_release_request(SRpnt);
+                                       SRpnt = NULL;
                                }
                                return i;
                        }
@@ -1626,9 +1633,9 @@ static ssize_t
        }                       /* for (total = 0, special = 0;
                                    total < count && !special; ) */
 
-       if (SCpnt != NULL) {
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+       if (SRpnt != NULL) {
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
        }
 
        /* Change the eof state if no data from tape or buffer */
@@ -1830,7 +1837,7 @@ static int st_compression(Scsi_Tape * STp, int state)
 {
        int dev;
        unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt = NULL;
+       Scsi_Request *SRpnt = NULL;
 
        if (STp->ready != ST_READY)
                return (-EIO);
@@ -1842,17 +1849,18 @@ static int st_compression(Scsi_Tape * STp, int state)
        cmd[2] = COMPRESSION_PAGE;
        cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
 
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
-       if (SCpnt == NULL)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ,
+                          STp->timeout, 0, TRUE);
+       if (SRpnt == NULL)
+               return (STp->buffer)->syscall_result;
 
-       dev = TAPE_NR(SCpnt->request.rq_dev);
+       dev = TAPE_NR(SRpnt->sr_request.rq_dev);
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression mode page not supported.\n",
                             dev));
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
                return (-EIO);
        }
         DEBC(printk(ST_DEB_MSG "st%d: Compression state is %d.\n", dev,
@@ -1861,8 +1869,8 @@ static int st_compression(Scsi_Tape * STp, int state)
        /* Check if compression can be changed */
        if (((STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] & DCC_MASK) == 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression not supported.\n", dev));
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
                return (-EIO);
        }
 
@@ -1880,19 +1888,20 @@ static int st_compression(Scsi_Tape * STp, int state)
        (STp->buffer)->b_data[0] = 0;   /* Reserved data length */
        (STp->buffer)->b_data[1] = 0;   /* Reserved media type byte */
        (STp->buffer)->b_data[MODE_HEADER_LENGTH] &= 0x3f;
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
+                          STp->timeout, 0, TRUE);
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: Compression change failed.\n", dev));
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
                return (-EIO);
        }
         DEBC(printk(ST_DEB_MSG "st%d: Compression state changed to %d.\n",
                       dev, state));
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
        STp->compression_changed = TRUE;
        return 0;
 }
@@ -1907,10 +1916,11 @@ static int st_int_ioctl(struct inode *inode,
        int i, ioctl_result;
        int chg_eof = TRUE;
        unsigned char cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
        Scsi_Tape *STp;
        ST_partstat *STps;
-       int fileno, blkno, at_sm, undone, datalen;
+       int fileno, blkno, at_sm, undone;
+       int datalen = 0, direction = SCSI_DATA_NONE;
        int dev = TAPE_NR(inode->i_rdev);
 
        STp = &(scsi_tapes[dev]);
@@ -1927,7 +1937,6 @@ static int st_int_ioctl(struct inode *inode,
        at_sm = STps->at_sm;
 
        memset(cmd, 0, MAX_COMMAND_SIZE);
-       datalen = 0;
        switch (cmd_in) {
        case MTFSFM:
                chg_eof = FALSE;        /* Changed from the FSF after this */
@@ -2169,6 +2178,7 @@ static int st_int_ioctl(struct inode *inode,
                }
                cmd[0] = MODE_SELECT;
                cmd[4] = datalen = 12;
+               direction = SCSI_DATA_WRITE;
 
                memset((STp->buffer)->b_data, 0, 12);
                if (cmd_in == MTSETDRVBUFFER)
@@ -2215,15 +2225,16 @@ static int st_int_ioctl(struct inode *inode,
                return (-ENOSYS);
        }
 
-       SCpnt = st_do_scsi(NULL, STp, cmd, datalen, timeout, MAX_RETRIES, TRUE);
-       if (!SCpnt)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
+                          timeout, MAX_RETRIES, TRUE);
+       if (!SRpnt)
+               return (STp->buffer)->syscall_result;
 
-       ioctl_result = (STp->buffer)->last_result_fatal;
+       ioctl_result = (STp->buffer)->syscall_result;
 
        if (!ioctl_result) {    /* SCSI command successful */
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
                STps->drv_block = blkno;
                STps->drv_file = fileno;
                STps->at_sm = at_sm;
@@ -2272,7 +2283,7 @@ static int st_int_ioctl(struct inode *inode,
        } else { /* SCSI command was not completely successful. Don't return
                     from this block without releasing the SCSI command block! */
 
-               if (SCpnt->sense_buffer[2] & 0x40) {
+               if (SRpnt->sr_sense_buffer[2] & 0x40) {
                        if (cmd_in != MTBSF && cmd_in != MTBSFM &&
                            cmd_in != MTBSR && cmd_in != MTBSS)
                                STps->eof = ST_EOM_OK;
@@ -2280,14 +2291,14 @@ static int st_int_ioctl(struct inode *inode,
                }
 
                undone = (
-                                (SCpnt->sense_buffer[3] << 24) +
-                                (SCpnt->sense_buffer[4] << 16) +
-                                (SCpnt->sense_buffer[5] << 8) +
-                                SCpnt->sense_buffer[6]);
+                                (SRpnt->sr_sense_buffer[3] << 24) +
+                                (SRpnt->sr_sense_buffer[4] << 16) +
+                                (SRpnt->sr_sense_buffer[5] << 8) +
+                                SRpnt->sr_sense_buffer[6]);
                if (cmd_in == MTWEOF &&
-                   (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-                   (SCpnt->sense_buffer[2] & 0x4f) == 0x40 &&
-                ((SCpnt->sense_buffer[0] & 0x80) == 0 || undone == 0)) {
+                   (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
+                   (SRpnt->sr_sense_buffer[2] & 0x4f) == 0x40 &&
+                ((SRpnt->sr_sense_buffer[0] & 0x80) == 0 || undone == 0)) {
                        ioctl_result = 0;       /* EOF written succesfully at EOM */
                        if (fileno >= 0)
                                fileno++;
@@ -2308,7 +2319,7 @@ static int st_int_ioctl(struct inode *inode,
                        STps->drv_block = 0;
                        STps->eof = ST_NOEOF;
                } else if (cmd_in == MTFSR) {
-                       if (SCpnt->sense_buffer[2] & 0x80) {    /* Hit filemark */
+                       if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */
                                if (STps->drv_file >= 0)
                                        STps->drv_file++;
                                STps->drv_block = 0;
@@ -2321,7 +2332,7 @@ static int st_int_ioctl(struct inode *inode,
                                STps->eof = ST_NOEOF;
                        }
                } else if (cmd_in == MTBSR) {
-                       if (SCpnt->sense_buffer[2] & 0x80) {    /* Hit filemark */
+                       if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */
                                STps->drv_file--;
                                STps->drv_block = (-1);
                        } else {
@@ -2338,14 +2349,14 @@ static int st_int_ioctl(struct inode *inode,
                } else if (chg_eof)
                        STps->eof = ST_NOEOF;
 
-               if ((SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK)
+               if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
                        STps->eof = ST_EOD;
 
                if (cmd_in == MTLOCK)
                        STp->door_locked = ST_LOCK_FAILS;
 
-               scsi_release_command(SCpnt);
-               SCpnt = NULL;
+               scsi_release_request(SRpnt);
+               SRpnt = NULL;
        }
 
        return ioctl_result;
@@ -2362,7 +2373,7 @@ static int get_location(struct inode *inode, unsigned int *block, int *partition
        int dev = TAPE_NR(inode->i_rdev);
        int result;
        unsigned char scmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
 
        STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY)
@@ -2377,11 +2388,12 @@ static int get_location(struct inode *inode, unsigned int *block, int *partition
                if (!logical && !STp->scsi2_logical)
                        scmd[1] = 1;
        }
-       SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES, TRUE);
-       if (!SCpnt)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->timeout,
+                          MAX_READY_RETRIES, TRUE);
+       if (!SRpnt)
+               return (STp->buffer)->syscall_result;
 
-       if ((STp->buffer)->last_result_fatal != 0 ||
+       if ((STp->buffer)->syscall_result != 0 ||
            (STp->device->scsi_level >= SCSI_2 &&
             ((STp->buffer)->b_data[0] & 4) != 0)) {
                *block = *partition = 0;
@@ -2407,8 +2419,8 @@ static int get_location(struct inode *inode, unsigned int *block, int *partition
                 DEBC(printk(ST_DEB_MSG "st%d: Got tape pos. blk %d part %d.\n", dev,
                             *block, *partition));
        }
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
 
        return result;
 }
@@ -2426,7 +2438,7 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
        unsigned int blk;
        int timeout;
        unsigned char scmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd *SCpnt;
+       Scsi_Request *SRpnt;
 
        STp = &(scsi_tapes[dev]);
        if (STp->ready != ST_READY)
@@ -2483,13 +2495,14 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
        timeout = STp->timeout;
 #endif
 
-       SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES, TRUE);
-       if (!SCpnt)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE,
+                          timeout, MAX_READY_RETRIES, TRUE);
+       if (!SRpnt)
+               return (STp->buffer)->syscall_result;
 
        STps->drv_block = STps->drv_file = (-1);
        STps->eof = ST_NOEOF;
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                result = (-EIO);
                if (STp->can_partitions &&
                    (STp->device)->scsi_level >= SCSI_2 &&
@@ -2511,8 +2524,8 @@ static int set_location(struct inode *inode, unsigned int block, int partition,
                result = 0;
        }
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
 
        return result;
 }
@@ -2561,7 +2574,7 @@ static int nbr_partitions(struct inode *inode)
 {
        int dev = TAPE_NR(inode->i_rdev), result;
        Scsi_Tape *STp;
-       Scsi_Cmnd *SCpnt = NULL;
+       Scsi_Request *SRpnt = NULL;
        unsigned char cmd[MAX_COMMAND_SIZE];
 
        STp = &(scsi_tapes[dev]);
@@ -2574,14 +2587,15 @@ static int nbr_partitions(struct inode *inode)
        cmd[2] = PART_PAGE;
        cmd[4] = 200;
 
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, STp->timeout, MAX_READY_RETRIES, TRUE);
-       if (SCpnt == NULL)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, 200, SCSI_DATA_READ, STp->timeout,
+                          MAX_READY_RETRIES, TRUE);
+       if (SRpnt == NULL)
+               return (STp->buffer)->syscall_result;
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                 DEBC(printk(ST_DEB_MSG "st%d: Can't read medium partition page.\n",
                             dev));
                result = (-EIO);
@@ -2601,7 +2615,7 @@ static int partition_tape(struct inode *inode, int size)
        int dev = TAPE_NR(inode->i_rdev), result;
        int length;
        Scsi_Tape *STp;
-       Scsi_Cmnd *SCpnt = NULL;
+       Scsi_Request *SRpnt = NULL;
        unsigned char cmd[MAX_COMMAND_SIZE], *bp;
 
        if ((result = nbr_partitions(inode)) < 0)
@@ -2638,15 +2652,15 @@ static int partition_tape(struct inode *inode, int size)
        cmd[1] = 0x10;
        cmd[4] = length + MODE_HEADER_LENGTH;
 
-       SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout,
-                          MAX_READY_RETRIES, TRUE);
-       if (SCpnt == NULL)
-               return (STp->buffer)->last_result_fatal;
+       SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
+                          STp->long_timeout, MAX_READY_RETRIES, TRUE);
+       if (SRpnt == NULL)
+               return (STp->buffer)->syscall_result;
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
+       scsi_release_request(SRpnt);
+       SRpnt = NULL;
 
-       if ((STp->buffer)->last_result_fatal != 0) {
+       if ((STp->buffer)->syscall_result != 0) {
                printk(KERN_INFO "st%d: Partitioning of tape failed.\n", dev);
                result = (-EIO);
        } else
index 2736349ae76077d76b1c9229c34430dfa960f542..e751efc28d3401a343928f02d097ec69bcf98176 100644 (file)
@@ -19,9 +19,9 @@ typedef struct {
        int buffer_bytes;
        int read_pointer;
        int writing;
-       int last_result;
-       int last_result_fatal;
-       Scsi_Cmnd *last_SCpnt;
+       int midlevel_result;
+       int syscall_result;
+       Scsi_Request *last_SRpnt;
        unsigned char *b_data;
        unsigned short use_sg;  /* zero or number of segments for this adapter */
        unsigned short sg_segs; /* total number of allocated segments */
index ae648ca99537f518e1dce45ea0f988809cac5ce6..f7e5622d19dfc5aeecf9f2dfcac47e7f715ce164 100644 (file)
@@ -2466,6 +2466,10 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
                return -1;
        if (pcidev->irq == 0) 
                return -1;
+       if (!pci_dma_supported(pcidev, 0xffffffff)) {
+               printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
+               return -1;
+       }
        if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
                printk(KERN_WARNING "es1370: out of memory\n");
                return -1;
@@ -2589,7 +2593,7 @@ static void __devinit es1370_remove(struct pci_dev *dev)
        dev->driver_data = NULL;
 }
 
-static const struct pci_device_id id_table[] __devinitdata = {
+static struct pci_device_id id_table[] __devinitdata = {
        { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
        { 0, 0, 0, 0, 0, 0 }
 };
index eab41fb7dc03465ff41b0bb762c0d3831057d7d0..feeb11956ff86efa62c399d4ce1dc963f51f4507 100644 (file)
@@ -2624,6 +2624,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
                return -1;
        if (pcidev->irq == 0) 
                return -1;
+       if (!pci_dma_supported(pcidev, 0xffffffff)) {
+               printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
+               return -1;
+       }
        if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
                printk(KERN_WARNING "es1371: out of memory\n");
                return -1;
@@ -2788,7 +2792,7 @@ static void __devinit es1371_remove(struct pci_dev *dev)
        dev->driver_data = NULL;
 }
 
-static const struct pci_device_id id_table[] __devinitdata = {
+static struct pci_device_id id_table[] __devinitdata = {
        { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
        { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
        { PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
index 4f188a653abe7f5cc924b8aaa5d369c95d4a5619..f61503b2feb56f478a1209cda965381c63281861 100644 (file)
@@ -67,7 +67,7 @@
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
  *                       Integrated (aka redid 8-)) APM support patch by Zach Brown
  *    07.02.2000   0.13  Use pci_alloc_consistent and pci_register_driver
- *
+ *    19.02.2000   0.14  Use pci_dma_supported to determine if recording should be disabled
  */
 
 /*****************************************************************************/
@@ -412,7 +412,7 @@ extern inline void dealloc_dmabuf(struct solo1_state *s, struct dmabuf *db)
        db->mapped = db->ready = 0;
 }
 
-static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, unsigned long dmamask)
+static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db)
 {
        int order;
        unsigned bytespersec;
@@ -422,7 +422,6 @@ static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, unsigned long d
        db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
        if (!db->rawbuf) {
                db->ready = db->mapped = 0;
-               s->dev->dma_mask = dmamask;
                 for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
                        if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
                                break;
@@ -469,7 +468,10 @@ extern inline int prog_dmabuf_adc(struct solo1_state *s)
        int c;
 
        stop_adc(s);
-       if ((c = prog_dmabuf(s, &s->dma_adc, 0xffffff)))
+       /* check if PCI implementation supports 24bit busmaster DMA */
+       if (s->dev->dma_mask > 0xffffff)
+               return -EIO;
+       if ((c = prog_dmabuf(s, &s->dma_adc)))
                return c;
        va = s->dma_adc.dmaaddr;
        if ((va & ~((1<<24)-1)))
@@ -494,7 +496,7 @@ extern inline int prog_dmabuf_dac(struct solo1_state *s)
        int c;
 
        stop_dac(s);
-       if ((c = prog_dmabuf(s, &s->dma_dac, 0xffffffff)))
+       if ((c = prog_dmabuf(s, &s->dma_dac)))
                return c;
        memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80, s->dma_dac.dmasize); /* almost correct for U16 */
        va = s->dma_dac.dmaaddr;
@@ -2194,6 +2196,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
 {
        struct solo1_state *s;
        struct pm_dev *pmdev;
+       dma_addr_t dma_mask;
 
        if (!RSRCISIOREGION(pcidev, 0) ||
            !RSRCISIOREGION(pcidev, 1) ||
@@ -2202,6 +2205,14 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
                return -1;
        if (pcidev->irq == 0)
                return -1;
+       if (pci_dma_supported(pcidev, 0x00ffffff)) {
+               dma_mask = 0x00ffffff; /* this enables playback and recording */
+       } else if (pci_dma_supported(pcidev, 0xffffffff)) {
+               dma_mask = 0xffffffff; /* this enables only playback, as the recording BMDMA can handle only 24bits  */
+       } else {
+               printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
+               return -1;
+       }
        if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
                printk(KERN_WARNING "solo1: out of memory\n");
                return -1;
@@ -2259,7 +2270,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
                goto err;
        /* store it in the driver field */
        pcidev->driver_data = s;
-       pcidev->dma_mask = 0xffffff;  /* pessimistic; play can handle 32bit addrs */
+       pcidev->dma_mask = dma_mask;
        /* put it into driver list */
        list_add_tail(&s->devs, &devs);
 
@@ -2319,7 +2330,7 @@ static void __devinit solo1_remove(struct pci_dev *dev)
        dev->driver_data = NULL;
 }
 
-static const struct pci_device_id id_table[] __devinitdata = {
+static struct pci_device_id id_table[] __devinitdata = {
        { PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
        { 0, 0, 0, 0, 0, 0 }
 };
@@ -2338,7 +2349,7 @@ static int __init init_solo1(void)
 {
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "solo1: version v0.13 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "solo1: version v0.14 time " __TIME__ " " __DATE__ "\n");
        if (!pci_register_driver(&solo1_driver)) {
                pci_unregister_driver(&solo1_driver);
                 return -ENODEV;
index 47379a3d372f680e39c913b9f5ec74bc52f8c09b..ae86b61f757d23bd5e6a90f80ba20b4f74f8a176 100644 (file)
@@ -2447,6 +2447,10 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
                return -1;
        if (pcidev->irq == 0)
                return -1;
+       if (!pci_dma_supported(pcidev, 0x00ffffff)) {
+               printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n");
+               return -1;
+       }
        /* try to allocate a DDMA resource if not already available */
        if (!RSRCISIOREGION(pcidev, RESOURCE_DDMA)) {
                pcidev->resource[RESOURCE_DDMA].start = 0;
@@ -2625,7 +2629,7 @@ static void __devinit sv_remove(struct pci_dev *dev)
        dev->driver_data = NULL;
 }
 
-static const struct pci_device_id id_table[] __devinitdata = {
+static struct pci_device_id id_table[] __devinitdata = {
        { PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
        { 0, 0, 0, 0, 0, 0 }
 };
index 7f02917c0f44bac914ed2815d8a760b7dcf1ecc8..3a0ef10b7c6f3f28dc4b3ab9eae80313e517dd85 100644 (file)
@@ -23,16 +23,12 @@ export-objs         := usb.o input.o
 
 list-multi             := usbcore.o
 usbcore-objs           := usb.o usb-debug.o usb-core.o hub.o
-usb-storage-objs       := usb_storage.o
 
 # Optional parts of multipart objects.
 
 ifeq ($(CONFIG_USB_DEVICEFS),y)
        usbcore-objs    += devio.o inode.o drivers.o devices.o
 endif
-ifeq ($(CONFIG_USB_STORAGE_DEBUG),y)
-       usb-storage-objs        += usb_storage_debug.o
-endif
 
 # Object file lists.
 
@@ -107,6 +103,3 @@ include $(TOPDIR)/Rules.make
 usbcore.o: $(usbcore-objs)
        $(LD) -r -o $@ $(usbcore-objs)
 
-usb-storage.o: $(usb-storage-objs)
-       $(LD) -r -o $@ $(usb-storage-objs)
-
index fe7d3bc2c9cc9219ffb2bb5f0a48e645509b4a73..cc03acb09a8d53e5e51aba9184903db4981867ab 100644 (file)
@@ -646,17 +646,13 @@ static struct tty_driver acm_tty_driver = {
  * Init / cleanup.
  */
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit usb_acm_cleanup(void)
 {
        usb_deregister(&acm_driver);
        tty_unregister_driver(&acm_tty_driver);
 }
 
-int init_module(void)
-#else
-int usb_acm_init(void)
-#endif
+static int __init usb_acm_init(void)
 {
        acm_tty_driver.init_termios =           tty_std_termios;
        acm_tty_driver.init_termios.c_cflag =   B9600 | CS8 | CREAD | HUPCL | CLOCAL;
@@ -672,4 +668,5 @@ int usb_acm_init(void)
        return 0;
 }
 
-__initcall(usb_acm_init);
+module_init(usb_acm_init);
+module_exit(usb_acm_cleanup);
index 0cac10898c72d22a8e8acd3a96a89efc0c2a5dc6..d780d8d9c91beae3f70e0ffcc255d28fb0305ed2 100644 (file)
@@ -502,7 +502,7 @@ static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum)
        dbg("plusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
          usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
 
-       if (usbdev->descriptor.idVendor != 0x067b || usbdev->descriptor.idProduct != 0x1)
+       if (usbdev->descriptor.idVendor != 0x067b || usbdev->descriptor.idProduct > 0x1)
                return NULL;
 
        /* We don't handle multiple configurations */
index a645dbfc23bcb47a462187a73e71aca55ea76d12..07220ad9b364e37b88a88d1b39a6186621921004 100644 (file)
@@ -432,15 +432,12 @@ static struct usb_driver usblp_driver = {
        minor:          USBLP_MINOR_BASE
 };
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit usb_printer_cleanup(void)
 {
        usb_deregister(&usblp_driver);
 }
-int init_module(void)
-#else
-int usb_printer_init(void)
-#endif
+
+static int __init usb_printer_init(void)
 {
        if (usb_register(&usblp_driver))
                return -1;
@@ -448,4 +445,5 @@ int usb_printer_init(void)
        return 0;
 }
 
-__initcall(usb_printer_init);
+module_init(usb_printer_init);
+module_exit(usb_printer_cleanup);
index 9d715d4d8d508ae1fc457cdba592606ac9f8e78d..61b14ba402a8e572f2d3beed51a78a76ab135644 100644 (file)
@@ -193,7 +193,7 @@ static const char *qh_names[] = { "control", "bulk" };
 
 void uhci_show_queues(struct uhci *uhci)
 {
-       int i, isqh;
+       int i, isqh = 0;
        struct uhci_qh *qh;
        struct uhci_td *td;
 
index 91cdf337c6ebfe5398ab880878f51a4b6d217a57..60b411761dc79810510c5a134641be9a738fcdc3 100644 (file)
@@ -33,8 +33,6 @@ int usb_audio_init(void);
 int usb_cpia_init(void);
 int usb_ibmcam_init(void);
 int usb_ov511_init(void);
-int usb_dc2xx_init(void);
-int usb_scanner_init(void);
 int usb_stor_init(void);
 int dabusb_init(void);
 int plusb_init(void);
@@ -76,9 +74,6 @@ int usb_init(void)
        usb_hub_init();
 
 #ifndef CONFIG_USB_MODULE
-#ifdef CONFIG_USB_SCANNER
-       usb_scanner_init();
-#endif
 #ifdef CONFIG_USB_AUDIO
        usb_audio_init();
 #endif
@@ -91,9 +86,6 @@ int usb_init(void)
 #ifdef CONFIG_USB_OV511
        usb_ov511_init();
 #endif
-#ifdef CONFIG_USB_DC2XX
-       usb_dc2xx_init();
-#endif
 #ifdef CONFIG_USB_STORAGE
        usb_stor_init();
 #endif
diff --git a/drivers/usb/usb-storage-debug.h b/drivers/usb/usb-storage-debug.h
new file mode 100644 (file)
index 0000000..8994c06
--- /dev/null
@@ -0,0 +1,88 @@
+#ifdef CONFIG_USB_STORAGE_DEBUG
+
+/* Debug output for Driver for USB mass storage (scsi-like) devices
+ * 
+ * (C) Michael Gee (michael@linuxspecific.com) 1999
+ *
+ */
+
+void us_show_command(Scsi_Cmnd *srb)
+{
+       char *what = NULL;
+
+       switch (srb->cmnd[0]) {
+       case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
+       case REZERO_UNIT: what = "REZERO_UNIT"; break;
+       case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
+       case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
+       case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
+       case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
+       case READ_6: what = "READ_6"; break;
+       case WRITE_6: what = "WRITE_6"; break;
+       case SEEK_6: what = "SEEK_6"; break;
+       case READ_REVERSE: what = "READ_REVERSE"; break;
+       case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
+       case SPACE: what = "SPACE"; break;
+       case INQUIRY: what = "INQUIRY"; break;
+       case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
+       case MODE_SELECT: what = "MODE_SELECT"; break;
+       case RESERVE: what = "RESERVE"; break;
+       case RELEASE: what = "RELEASE"; break;
+       case COPY: what = "COPY"; break;
+       case ERASE: what = "ERASE"; break;
+       case MODE_SENSE: what = "MODE_SENSE"; break;
+       case START_STOP: what = "START_STOP"; break;
+       case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
+       case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
+       case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
+       case SET_WINDOW: what = "SET_WINDOW"; break;
+       case READ_CAPACITY: what = "READ_CAPACITY"; break;
+       case READ_10: what = "READ_10"; break;
+       case WRITE_10: what = "WRITE_10"; break;
+       case SEEK_10: what = "SEEK_10"; break;
+       case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
+       case VERIFY: what = "VERIFY"; break;
+       case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
+       case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
+       case SEARCH_LOW: what = "SEARCH_LOW"; break;
+       case SET_LIMITS: what = "SET_LIMITS"; break;
+       case READ_POSITION: what = "READ_POSITION"; break;
+       case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
+       case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
+       case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
+       case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
+       case COMPARE: what = "COMPARE"; break;
+       case COPY_VERIFY: what = "COPY_VERIFY"; break;
+       case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
+       case READ_BUFFER: what = "READ_BUFFER"; break;
+       case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
+       case READ_LONG: what = "READ_LONG"; break;
+       case WRITE_LONG: what = "WRITE_LONG"; break;
+       case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
+       case WRITE_SAME: what = "WRITE_SAME"; break;
+       case READ_TOC: what = "READ_TOC"; break;
+       case LOG_SELECT: what = "LOG_SELECT"; break;
+       case LOG_SENSE: what = "LOG_SENSE"; break;
+       case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
+       case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
+       case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
+       case READ_12: what = "READ_12"; break;
+       case WRITE_12: what = "WRITE_12"; break;
+       case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
+       case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
+       case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
+       case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
+       case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
+       case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
+       case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
+       default: break;
+       }
+       printk(KERN_DEBUG USB_STORAGE
+              "Command %s (%d bytes)\n", what, srb->cmd_len);
+       printk(KERN_DEBUG USB_STORAGE 
+              "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+              srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], 
+              srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
+}
+
+#endif
diff --git a/drivers/usb/usb-storage.c b/drivers/usb/usb-storage.c
new file mode 100644 (file)
index 0000000..dd34058
--- /dev/null
@@ -0,0 +1,1851 @@
+/* Driver for USB Mass Storage compliant devices
+ *
+ * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *
+ * Further reference:
+ *     This driver is based on the 'USB Mass Storage Class' document. This
+ *     describes in detail the protocol used to communicate with such
+ *      devices.  Clearly, the designers had SCSI commands in mind when they
+ *      created this document.  The commands are all similar to commands
+ *      in the SCSI-II specification.
+ *
+ *     It is important to note that in a number of cases this class exhibits
+ *     class-specific exemptions from the USB specification. Notably the
+ *     usage of NAK, STALL and ACK differs from the norm, in that they are
+ *     used to communicate wait, failed and OK on commands.
+ *     Also, for certain devices, the interrupt endpoint is used to convey
+ *     status of a command.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+#include <linux/blk.h>
+#include "../scsi/scsi.h"
+#include "../scsi/hosts.h"
+#include "../scsi/sd.h"
+
+#include "usb.h"
+#include "usb-storage.h"
+#include "usb-storage-debug.h"
+
+
+/*
+ * This is the size of the structure Scsi_Host_Template.  We create
+ * an instance of this structure in this file and this is a check
+ * to see if this structure may have changed within the SCSI module.
+ * This is by no means foolproof, but it does help us some.
+ */
+#define SCSI_HOST_TEMPLATE_SIZE                        (104)
+
+/* direction table -- this indicates the direction of the data
+ * transfer for each command code -- a 1 indicates input
+ */
+unsigned char us_direction[256/8] = {
+       0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 
+       0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/*
+ * Per device data
+ */
+
+static int my_host_number;
+
+int usb_stor_debug = 1;
+
+struct us_data;
+
+typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef int (*trans_reset)(struct us_data*);
+typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+
+struct us_data {
+       struct us_data  *next;                   /* next device */
+       struct usb_device       *pusb_dev;       /* this usb_device */
+       unsigned int            flags;           /* from filter initially */
+       __u8                    ifnum;           /* interface number */
+       __u8                    ep_in;           /* in endpoint */
+       __u8                    ep_out;          /* out ....... */
+       __u8                    ep_int;          /* interrupt . */
+       __u8                    subclass;        /* as in overview */
+       __u8                    protocol;        /* .............. */
+       __u8                    attention_done;  /* force attn on first cmd */
+       trans_cmnd              transport;       /* protocol specific do cmd */
+       trans_reset             transport_reset; /* .......... device reset */
+       proto_cmnd              proto_handler;   /* protocol handler */
+       GUID(guid);                              /* unique dev id */
+       struct Scsi_Host        *host;           /* our dummy host data */
+       Scsi_Host_Template      *htmplt;         /* own host template */
+       int                     host_number;     /* to find us */
+       int                     host_no;         /* allocated by scsi */
+       Scsi_Cmnd               *srb;            /* current srb */
+       int                     action;          /* what to do */
+       wait_queue_head_t       waitq;           /* thread waits */
+       wait_queue_head_t       ip_waitq;        /* for CBI interrupts */
+       __u16                   ip_data;         /* interrupt data */
+       int                     ip_wanted;       /* needed */
+       int                     pid;             /* control thread */
+       struct semaphore        *notify;         /* wait for thread to begin */
+       void                    *irq_handle;     /* for USB int requests */
+       unsigned int            irqpipe;         /* pipe for release_irq */
+};
+
+/*
+ * kernel thread actions
+ */
+
+#define US_ACT_COMMAND         1
+#define US_ACT_ABORT           2
+#define US_ACT_DEVICE_RESET    3
+#define US_ACT_BUS_RESET       4
+#define US_ACT_HOST_RESET      5
+
+static struct us_data *us_list;
+
+static void * storage_probe(struct usb_device *dev, unsigned int ifnum);
+static void storage_disconnect(struct usb_device *dev, void *ptr);
+static struct usb_driver storage_driver = {
+       "usb-storage",
+       storage_probe,
+       storage_disconnect,
+       { NULL, NULL }
+};
+
+/***********************************************************************
+ * Data transfer routines
+ ***********************************************************************/
+
+/* Transfer one buffer (breaking into packets if necessary)
+ * Note that this function is necessary because if the device NAKs, we
+ * need to know that information directly
+ *
+ * FIXME: is the above true?  Or will the URB status show ETIMEDOUT after
+ * retrying several times allready?  Perhaps this is the way we should
+ * be going anyway?
+ */
+static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
+{
+       int max_size;
+       int this_xfer;
+       int result;
+       int partial;
+       int maxtry;
+
+       /* determine the maximum packet size for these transfers */
+       max_size = usb_maxpacket(us->pusb_dev, 
+                                pipe, usb_pipeout(pipe)) * 16;
+
+       /* while we have data left to transfer */
+       while (length) {
+
+               /* calculate how long this will be -- maximum or a remainder */
+               this_xfer = length > max_size ? max_size : length;
+               length -= this_xfer;
+
+               /* FIXME: this number is totally outrageous.  We need to pick
+                * a better (smaller) number).
+                */
+
+               /* setup the retry counter */
+               maxtry = 100;
+
+               /* set up the transfer loop */
+               do {
+                       /* transfer the data */
+                       US_DEBUGP("Bulk xfer 0x%x(%d) try #%d\n", 
+                                 (unsigned int)buf, this_xfer, 101 - maxtry);
+                       result = usb_bulk_msg(us->pusb_dev, pipe, buf,
+                                             this_xfer, &partial, HZ*5);
+                       US_DEBUGP("bulk_msg returned %d xferred %d/%d\n",
+                                 result, partial, this_xfer);
+
+                       /* if we stall, we need to clear it before we go on */
+                       if (result == -EPIPE) {
+                               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+                               usb_clear_halt(us->pusb_dev, pipe);
+                       }
+
+                       /* update to show what data was transferred */
+                       this_xfer -= partial;
+                       buf += partial;
+
+                       /* NAK - we retry a few times */
+                       if (result == -ETIMEDOUT) {
+
+                               US_DEBUGP("us_one_transfer: device NAKed\n");
+
+                               /* if our try counter reaches 0, bail out */
+                               if (!maxtry--)
+                                       return -ETIMEDOUT;
+
+                               /* just continue the while loop */
+                               continue;
+                       }
+      
+                       /* other errors (besides NAK) -- we just bail out*/
+                       if (result != 0) {
+                               US_DEBUGP("us_one_transfer: device returned error %d\n", result);
+                               return result;
+                       }
+
+                       /* continue until this transfer is done */
+               } while ( this_xfer );
+       }
+
+       /* if we get here, we're done and successful */
+       return 0;
+}
+
+static unsigned int us_transfer_length(Scsi_Cmnd *srb);
+
+/* transfer one SCSI command, using scatter-gather if requested */
+/* FIXME: what do the return codes here mean? */
+static int us_transfer(Scsi_Cmnd *srb, int dir_in)
+{
+       struct us_data *us = (struct us_data *)srb->host_scribble;
+       int i;
+       int result = -1;
+       unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
+               usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+
+       /* FIXME: stop transferring data at us_transfer_length(), not 
+        * bufflen */
+       if (srb->use_sg) {
+               struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
+
+               for (i = 0; i < srb->use_sg; i++) {
+                       result = us_one_transfer(us, pipe, sg[i].address, sg[i].length);
+                       if (result)
+                               break;
+               }
+       }
+       else
+               result = us_one_transfer(us, pipe, srb->request_buffer, 
+                                        us_transfer_length(srb));
+
+       if (result < 0)
+               US_DEBUGP("us_transfer returning error %d\n", result);
+       return result;
+}
+
+/* calculate the length of the data transfer (not the command) for any
+ * given SCSI command
+ */
+static unsigned int us_transfer_length(Scsi_Cmnd *srb)
+{
+       int i;
+       unsigned int total = 0;
+
+       /* always zero for some commands */
+       switch (srb->cmnd[0]) {
+       case SEEK_6:
+       case SEEK_10:
+       case REZERO_UNIT:
+       case ALLOW_MEDIUM_REMOVAL:
+       case START_STOP:
+       case TEST_UNIT_READY:
+               return 0;
+
+       case REQUEST_SENSE:
+       case INQUIRY:
+       case MODE_SENSE:
+               return srb->cmnd[4];
+
+       case LOG_SENSE:
+       case MODE_SENSE_10:
+               return (srb->cmnd[7] << 8) + srb->cmnd[8];
+
+       default:
+               break;
+       }
+
+       if (srb->use_sg) {
+               struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
+
+               for (i = 0; i < srb->use_sg; i++) {
+                       total += sg[i].length;
+               }
+               return total;
+       }
+       else
+               return srb->request_bufflen;
+}
+
+/***********************************************************************
+ * Protocol routines
+ ***********************************************************************/
+
+static int CB_transport(Scsi_Cmnd *srb, struct us_data *us);
+static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us);
+
+static void ufi_command(Scsi_Cmnd *srb, struct us_data *us)
+{
+       int old_cmnd = 0;
+  
+       /* fix some commands -- this is a form of mode translation
+        * UFI devices only accept 12 byte long commands 
+        *
+        * NOTE: This only works because a Scsi_Cmnd struct field contains
+        * a unsigned char cmnd[12], so we know we have storage available
+        */
+
+       /* set command length to 12 bytes (this affects the transport layer) */
+       srb->cmd_len = 12;
+
+       /* determine the correct (or minimum) data length for these commands */
+       switch (us->srb->cmnd[0]) {
+
+               /* for INQUIRY, UFI devices only ever return 36 bytes */
+       case INQUIRY:
+               us->srb->cmnd[4] = 36;
+               break;
+
+               /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
+       case MODE_SENSE:
+       case MODE_SELECT:
+               /* save the command so we can tell what it was */
+               old_cmnd = srb->cmnd[0];
+
+               srb->cmnd[11] = 0;
+               srb->cmnd[10] = 0;
+               srb->cmnd[9] = 0;
+
+               /* if we're sending data, we send all.  If getting data, 
+                * get the minimum */
+               if (srb->cmnd[0] == MODE_SELECT)
+                       srb->cmnd[8] = srb->cmnd[4];
+               else
+                       srb->cmnd[8] = 8;
+
+               srb->cmnd[7] = 0;
+               srb->cmnd[6] = 0;
+               srb->cmnd[5] = 0;
+               srb->cmnd[4] = 0;
+               srb->cmnd[3] = 0;
+               srb->cmnd[2] = srb->cmnd[2];
+               srb->cmnd[1] = srb->cmnd[1];
+               srb->cmnd[0] = srb->cmnd[0] | 0x40;
+               break;
+
+               /* again, for MODE_SENSE_10, we get the minimum (8) */
+       case MODE_SENSE_10:
+               us->srb->cmnd[7] = 0;
+               us->srb->cmnd[8] = 8;
+               break;
+               /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
+       case REQUEST_SENSE:
+               us->srb->cmnd[4] = 18;
+               break;
+
+               /* change READ_6/WRITE_6 to READ_10/WRITE_10, which 
+                * are UFI commands */
+       case WRITE_6:
+       case READ_6:
+               srb->cmnd[11] = 0;
+               srb->cmnd[10] = 0;
+               srb->cmnd[9] = 0;
+               srb->cmnd[8] = srb->cmnd[4];
+               srb->cmnd[7] = 0;
+               srb->cmnd[6] = 0;
+               srb->cmnd[5] = srb->cmnd[3];
+               srb->cmnd[4] = srb->cmnd[2];
+               srb->cmnd[3] = srb->cmnd[1] & 0x1F;
+               srb->cmnd[2] = 0;
+               srb->cmnd[1] = srb->cmnd[1] & 0xE0;
+               srb->cmnd[0] = srb->cmnd[0] | 0x20;
+               break;
+       } /* end switch on cmnd[0] */
+  
+       /* send the command to the transport layer */
+       us->srb->result = us->transport(srb, us);
+
+       /* if we have an error, we're going to do a 
+        * REQUEST_SENSE automatically */
+
+       /* FIXME: we should only do this for device 
+        * errors, not system errors */
+       if (us->srb->result) {
+               int temp_result;
+               int count;
+               void* old_request_buffer;
+
+               US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n");
+
+               /* set the result so the higher layers expect this data */
+               us->srb->result = CHECK_CONDITION;
+
+               us->srb->cmnd[0] = REQUEST_SENSE;
+               us->srb->cmnd[1] = 0;
+               us->srb->cmnd[2] = 0;
+               us->srb->cmnd[3] = 0;
+               us->srb->cmnd[4] = 18;
+               us->srb->cmnd[5] = 0;
+    
+               /* set the buffer length for transfer */
+               old_request_buffer = us->srb->request_buffer;
+               us->srb->request_bufflen = 18;
+               us->srb->request_buffer = kmalloc(18, GFP_KERNEL);
+
+               /* FIXME: what if this command fails? */
+               temp_result = us->transport(us->srb, us);
+               US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
+
+               /* copy the data from the request buffer to the sense buffer */
+               for(count = 0; count < 18; count++)
+                       us->srb->sense_buffer[count] = 
+                               ((unsigned char *)(us->srb->request_buffer))[count];
+
+               US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
+                         us->srb->sense_buffer[2] & 0xf,
+                         us->srb->sense_buffer[12], us->srb->sense_buffer[13]);
+
+               /* we're done here */
+               kfree(us->srb->request_buffer);
+               us->srb->request_buffer = old_request_buffer;
+               return;
+       }
+  
+       /* FIXME: if we need to send more data, or recieve data, we should
+        * do it here.  Then, we can do status handling here also.
+        *
+        * This includes MODE_SENSE from above
+        */
+       if (old_cmnd == MODE_SENSE) {
+               unsigned char *dta = (unsigned char *)us->srb->request_buffer;
+
+               /* calculate the new length */
+               int length = (dta[0] << 8) + dta[1] + 2;
+
+               /* copy the available data length into the structure */
+               us->srb->cmnd[7] = length >> 8;
+               us->srb->cmnd[8] = length & 0xFF;
+
+               /* send the command to the transport layer */
+               us->srb->result = us->transport(srb, us);
+
+               /* FIXME: this assumes that the 2nd attempt is always
+                * successful convert MODE_SENSE_10 return data format 
+                * to MODE_SENSE_6 format */
+               dta[0] = dta[1];        /* data len */
+               dta[1] = dta[2];        /* med type */
+               dta[2] = dta[3];        /* dev-spec prm */
+               dta[3] = dta[7];        /* block desc len */
+               printk (KERN_DEBUG USB_STORAGE
+                       "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
+                       dta[0], dta[1], dta[2], dta[3]);
+       }
+
+       /* FIXME: if this was a TEST_UNIT_READY, and we get a NOT READY/
+        * LOGICAL DRIVE NOT READY then we do a START_STOP, and retry 
+        */
+
+       /* FIXME: here is where we need to fix-up the return data from 
+        * an INQUIRY command to show ANSI SCSI rev 2
+        */
+
+       /* FIXME: The rest of this is bogus.  usb_control_msg() will only
+        * return an error if we've really honked things up.  If it just
+        * needs a START_STOP, then we'll get some data back via 
+        * REQUEST_SENSE --  either way, this belongs at a higher level
+        */
+
+#if 0
+       /* For UFI, if this is the first time we've sent this TEST_UNIT_READY 
+        * command, we can try again
+        */
+       if (!done_start && (us->subclass == US_SC_UFI)
+           && (cmd[0] == TEST_UNIT_READY) && (result < 0)) {
+    
+               /* as per spec try a start command, wait and retry */
+               wait_ms(100);
+    
+               done_start++;
+               memset(cmd, 0, sizeof(cmd));
+               cmd[0] = START_STOP;
+               cmd[4] = 1;             /* start */
+    
+               result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                        US_CBI_ADSC, 
+                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                        0, us->ifnum,
+                                        cmd, 12, HZ*5);
+               US_DEBUGP("Next usb_control_msg returns %d\n", result);
+    
+                               /* allow another retry */
+               retry++;
+               continue;
+       }
+#endif
+}
+
+static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
+{
+       unsigned int savelen = us->srb->request_bufflen;
+       unsigned int saveallocation = 0;
+
+#if 0
+       /* force attention on first command */
+       if (!us->attention_done) {
+               if (us->srb->cmnd[0] == REQUEST_SENSE) {
+                       US_DEBUGP("forcing unit attention\n");
+                       us->attention_done = 1;
+
+                       if (us->srb->result == USB_STOR_TRANSPORT_GOOD) {
+                               unsigned char *p = (unsigned char *)us->srb->request_buffer;
+       
+                               if ((p[2] & 0x0f) != UNIT_ATTENTION) {
+                                       p[2] = UNIT_ATTENTION;
+                                       p[12] = 0x29;   /* power on, reset or bus-reset */
+                                       p[13] = 0;
+                               } /* if ((p[2] & 0x0f) != UNIT_ATTENTION) */
+                       } /* if (us->srb->result == USB_STORE_TRANSPORT_GOOD) */
+               }
+       } /* if (!us->attention_done) */
+#endif
+
+       /* If the command has a variable-length payload, then we do them
+        * in two steps -- first we do the minimum, then we recalculate
+        * then length, and re-issue the command 
+        *
+        * we use savelen to remember how much buffer we really have
+        * we use savealloction to remember how much was really requested
+        */
+
+       /* FIXME: remove savelen based on mods to us_transfer_length() */
+       switch (us->srb->cmnd[0]) {
+       case REQUEST_SENSE:
+               if (us->srb->request_bufflen > 18)
+                       us->srb->request_bufflen = 18;
+               else
+                       break;
+               saveallocation = us->srb->cmnd[4];
+               us->srb->cmnd[4] = 18;
+               break;
+    
+       case INQUIRY:
+               if (us->srb->request_bufflen > 36)
+                       us->srb->request_bufflen = 36;
+               else
+                       break;
+               saveallocation = us->srb->cmnd[4];
+               us->srb->cmnd[4] = 36;
+               break;
+    
+       case MODE_SENSE:
+               if (us->srb->request_bufflen > 4)
+                       us->srb->request_bufflen = 4;
+               else
+                       break;
+               saveallocation = us->srb->cmnd[4];
+               us->srb->cmnd[4] = 4;
+               break;
+    
+       case LOG_SENSE:
+       case MODE_SENSE_10:
+               if (us->srb->request_bufflen > 8)
+                       us->srb->request_bufflen = 8;
+               else
+                       break;
+               saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8];
+               us->srb->cmnd[7] = 0;
+               us->srb->cmnd[8] = 8;
+               break;
+    
+       default:
+               break;
+       } /* end switch on cmnd[0] */
+  
+       /* This code supports devices which do not support {READ|WRITE}_6
+        * Apparently, neither Windows or MacOS will use these commands,
+        * so some devices do not support them
+        */
+       if (us->flags & US_FL_MODE_XLATE) {
+    
+               /* translate READ_6 to READ_10 */
+               if (us->srb->cmnd[0] == 0x08) {
+      
+                       /* get the control */
+                       us->srb->cmnd[9] = us->srb->cmnd[5];
+      
+                       /* get the length */
+                       us->srb->cmnd[8] = us->srb->cmnd[6];
+                       us->srb->cmnd[7] = 0;
+      
+                       /* set the reserved area to 0 */
+                       us->srb->cmnd[6] = 0;       
+      
+                       /* get LBA */
+                       us->srb->cmnd[5] = us->srb->cmnd[3];
+                       us->srb->cmnd[4] = us->srb->cmnd[2];
+                       us->srb->cmnd[3] = 0;
+                       us->srb->cmnd[2] = 0;
+      
+                       /* LUN and other info in cmnd[1] can stay */
+      
+                       /* fix command code */
+                       us->srb->cmnd[0] = 0x28;
+      
+                       US_DEBUGP("Changing READ_6 to READ_10\n");
+                       US_DEBUG(us_show_command(us->srb));
+               }
+    
+               /* translate WRITE_6 to WRITE_10 */
+               if (us->srb->cmnd[0] == 0x0A) {
+      
+                       /* get the control */
+                       us->srb->cmnd[9] = us->srb->cmnd[5];
+      
+                       /* get the length */
+                       us->srb->cmnd[8] = us->srb->cmnd[4];
+                       us->srb->cmnd[7] = 0;
+      
+                       /* set the reserved area to 0 */
+                       us->srb->cmnd[6] = 0;       
+      
+                       /* get LBA */
+                       us->srb->cmnd[5] = us->srb->cmnd[3];
+                       us->srb->cmnd[4] = us->srb->cmnd[2];
+                       us->srb->cmnd[3] = 0;
+                       us->srb->cmnd[2] = 0;
+           
+                       /* LUN and other info in cmnd[1] can stay */
+      
+                       /* fix command code */
+                       us->srb->cmnd[0] = 0x2A;
+
+                       US_DEBUGP("Changing WRITE_6 to WRITE_10\n");
+                       US_DEBUG(us_show_command(us->srb));
+               }
+       } /* end if (us->flags & US_FL_MODE_XLATE) */
+  
+       /* send the command to the transport layer */
+       us->srb->result = us->transport(us->srb, us);
+
+       /* if we have an error, we're going to do a REQUEST_SENSE 
+        * automatically */
+       /* FIXME: we should only do this for device errors, not 
+        * system errors */
+       if (us->srb->result) {
+               int temp_result;
+               int count;
+               void* old_request_buffer;
+
+               US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n");
+
+               /* set the result so the higher layers expect this data */
+               us->srb->result = CHECK_CONDITION;
+
+               us->srb->cmnd[0] = REQUEST_SENSE;
+               us->srb->cmnd[1] = 0;
+               us->srb->cmnd[2] = 0;
+               us->srb->cmnd[3] = 0;
+               us->srb->cmnd[4] = 18;
+               us->srb->cmnd[5] = 0;
+    
+               /* set the buffer length for transfer */
+               old_request_buffer = us->srb->request_buffer;
+               us->srb->request_bufflen = 18;
+               us->srb->request_buffer = kmalloc(18, GFP_KERNEL);
+
+               /* FIXME: what if this command fails? */
+               temp_result = us->transport(us->srb, us);
+               US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
+
+               /* copy the data from the request buffer to the sense buffer */
+               for(count = 0; count < 18; count++)
+                       us->srb->sense_buffer[count] = 
+                               ((unsigned char *)(us->srb->request_buffer))[count];
+
+               US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
+                         us->srb->sense_buffer[2] & 0xf,
+                         us->srb->sense_buffer[12], us->srb->sense_buffer[13]);
+
+               /* we're done here */
+               kfree(us->srb->request_buffer);
+               us->srb->request_buffer = old_request_buffer;
+               return;
+       }
+
+       if (savelen != us->srb->request_bufflen) {
+               unsigned char *p = (unsigned char *)us->srb->request_buffer;
+               unsigned int length = 0;
+    
+               /* set correct length and retry */
+               switch (us->srb->cmnd[0]) {
+
+                       /* FIXME: we should try to get all the sense data */
+               case REQUEST_SENSE:
+                       /* simply return 18 bytes */
+                       p[7] = 10;
+                       length = us->srb->request_bufflen;
+                       break;
+      
+               case INQUIRY:
+                       length = p[4] + 5 > savelen ? savelen : p[4] + 5;
+                       us->srb->cmnd[4] = length;
+                       break;
+      
+               case MODE_SENSE:
+                       US_DEBUGP("MODE_SENSE Mode data length is %d\n", p[0]);
+                       length = p[0] + 1 > savelen ? savelen : p[0] + 1;
+                       us->srb->cmnd[4] = length;
+                       break;
+      
+               case LOG_SENSE:
+                       length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4;
+                       us->srb->cmnd[7] = length >> 8;
+                       us->srb->cmnd[8] = length;
+                       break;
+      
+               case MODE_SENSE_10:
+                       US_DEBUGP("MODE_SENSE_10 Mode data length is %d\n",
+                                 (p[0] << 8) + p[1]);
+                       length = ((p[0] << 8) + p[1]) + 6 > savelen ? savelen : ((p[0] << 8) + p[1]) + 6;
+                       us->srb->cmnd[7] = length >> 8;
+                       us->srb->cmnd[8] = length;
+                       break;
+               } /* end switch on cmnd[0] */
+    
+               US_DEBUGP("Old/New length = %d/%d\n",
+                         savelen, length);
+    
+               /* issue the new command */
+               /* FIXME: this assumes that the second attempt is 
+                * always successful */
+               if (us->srb->request_bufflen != length) {
+                       US_DEBUGP("redoing cmd with len=%d\n", length);
+                       us->srb->request_bufflen = length;
+                       us->srb->result = us->transport(us->srb, us);
+               }
+    
+               /* reset back to original values */
+               us->srb->request_bufflen = savelen;
+
+               /* fix data as necessary */
+               switch (us->srb->cmnd[0]) {
+               case INQUIRY:
+                       if ((((unsigned char*)us->srb->request_buffer)[2] & 0x7) == 0) { 
+                               US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n");
+                               ((unsigned char*)us->srb->request_buffer)[2] |= 2;
+                       }
+                       /* FALL THROUGH */
+               case REQUEST_SENSE:
+               case MODE_SENSE:
+                       if (us->srb->use_sg == 0 && length > 0) {
+                               int i;
+                               printk(KERN_DEBUG "Data is");
+                               for (i = 0; i < 32 && i < length; ++i)
+                                       printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);
+                               if (i < length)
+                                       printk(" ...");
+                               printk("\n");
+                       }
+
+                       /* FIXME: is this really necessary? */
+                       us->srb->cmnd[4] = saveallocation;
+                       break;
+      
+               case LOG_SENSE:
+               case MODE_SENSE_10:
+                       /* FIXME: is this really necessary? */
+                       us->srb->cmnd[7] = saveallocation >> 8;
+                       us->srb->cmnd[8] = saveallocation;
+                       break;
+               } /* end switch on cmnd[0] */
+       } /* if good command */
+}
+
+/***********************************************************************
+ * Transport routines
+ ***********************************************************************/
+
+static int CBI_irq(int state, void *buffer, int len, void *dev_id)
+{
+       struct us_data *us = (struct us_data *)dev_id;
+
+       US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no);
+
+       /* save the data for interpretation later */
+       if (state != USB_ST_REMOVED) {
+               us->ip_data = le16_to_cpup((__u16 *)buffer);
+               US_DEBUGP("Interrupt Status 0x%x\n", us->ip_data);
+       }
+  
+       /* was this a wanted interrupt? */
+       if (us->ip_wanted) {
+               us->ip_wanted = 0;
+               wake_up(&us->ip_waitq);
+       } else {
+               US_DEBUGP("ERROR: Unwanted interrupt received!\n");
+       }
+
+       /* This return code is truly meaningless -- and I mean truly.  It gets
+        * ignored by other layers.  It used to indicate if we wanted to get
+        * another interrupt or disable the interrupt callback
+        */
+       return 0;
+}
+
+/* FIXME: this reset function doesn't really reset the port, and it
+ * should. Actually it should probably do what it's doing here, and
+ * reset the port physically
+ */
+static int CB_reset(struct us_data *us)
+{
+       unsigned char cmd[12];
+       int result;
+
+       US_DEBUGP("CB_reset\n");
+
+       memset(cmd, 0xFF, sizeof(cmd));
+       cmd[0] = SEND_DIAGNOSTIC;
+       cmd[1] = 4;
+       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                0, us->ifnum, cmd, sizeof(cmd), HZ*5);
+
+       /* long wait for reset */
+       schedule_timeout(HZ*6);
+
+       US_DEBUGP("CB_reset: clearing endpoint halt\n");
+       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
+       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
+
+       US_DEBUGP("CB_reset done\n");
+       return 0;
+}
+
+static int pop_CB_status(Scsi_Cmnd *srb);
+
+/* FIXME: we also need a CBI_command which sets up the completion
+ * interrupt, and waits for it
+ */
+static int CB_transport(Scsi_Cmnd *srb, struct us_data *us)
+{
+       int result;
+
+       US_DEBUGP("CBI gets a command:\n");
+       US_DEBUG(us_show_command(srb));
+
+       /* FIXME: we aren't setting the ip_wanted indicator early enough, which
+        * causes some commands to never complete.  This hangs the driver.
+        */
+
+       /* let's send the command via the control pipe */
+       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                0, us->ifnum,
+                                srb->cmnd, srb->cmd_len, HZ*5);
+
+       /* check the return code for the command */
+       if (result < 0) {
+               US_DEBUGP("Call to usb_control_msg() returned %d\n", result);
+
+               /* a stall is a fatal condition from the device */
+               if (result == -EPIPE) {
+                       US_DEBUGP("-- Stall on control pipe detected. Clearing\n");
+      
+                       US_DEBUGP("-- Return from usb_clear_halt() is %d\n",
+                                 usb_clear_halt(us->pusb_dev, 
+                                                usb_sndctrlpipe(us->pusb_dev, 0)));
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+
+               /* FIXME: we need to handle NAKs here */
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       /* transfer the data payload for this command, if one exists*/
+       if (us_transfer_length(srb)) {
+               result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
+               US_DEBUGP("CBI attempted to transfer data, result is 0x%x\n", result);
+
+               /* FIXME: what do the return codes from us_transfer mean? */
+               if ((result < 0) && 
+                   (result != USB_ST_DATAUNDERRUN) && 
+                   (result != USB_ST_STALL)) {
+                       return DID_ERROR << 16;
+               }
+       } /* if (us_transfer_length(srb)) */
+
+       /* get status and return it */
+       return pop_CB_status(srb);
+}
+
+/*
+ * Control/Bulk status handler
+ */
+
+static int pop_CB_status(Scsi_Cmnd *srb)
+{
+       struct us_data *us = (struct us_data *)srb->host_scribble;
+       int result = 0;
+       __u8 status[2];
+       int retry = 5;
+
+       US_DEBUGP("pop_CB_status, proto=0x%x\n", us->protocol);
+       switch (us->protocol) {
+       case US_PR_CB:
+               /* get from control */
+
+               while (retry--) {
+                       result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
+                                                USB_REQ_GET_STATUS, USB_DIR_IN |
+                                                USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+                                                0, us->ifnum, status, sizeof(status), HZ*5);
+                       if (result != USB_ST_TIMEOUT)
+                               break;
+               }
+               if (result) {
+                       US_DEBUGP("Bad AP status request %d\n", result);
+                       return DID_ABORT << 16;
+               }
+               US_DEBUGP("Got AP status 0x%x 0x%x\n", status[0], status[1]);
+               if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY &&
+                   ( (status[0] & ~3) || status[1]))
+                       return (DID_OK << 16) | 2;
+               else
+                       return USB_STOR_TRANSPORT_GOOD;
+               break;
+
+               /* FIXME: this should be in a separate function */
+       case US_PR_CBI:
+               /* get from interrupt pipe */
+
+               /* add interrupt transfer, marked for removal */
+               us->ip_wanted = 1;
+
+               /* go to sleep until we get this interrup */
+               /* FIXME: this should be changed to use a timeout */
+               sleep_on(&us->ip_waitq);
+    
+               if (us->ip_wanted) {
+                       US_DEBUGP("Did not get interrupt on CBI\n");
+                       us->ip_wanted = 0;
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+    
+               US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data);
+
+               /* UFI gives us ASC and ASCQ, like a request sense */
+               /* FIXME: is this right?  do REQUEST_SENSE and INQUIRY need special
+                * case handling?
+                */
+               if (us->subclass == US_SC_UFI) {
+                       if (srb->cmnd[0] == REQUEST_SENSE ||
+                           srb->cmnd[0] == INQUIRY)
+                               return USB_STOR_TRANSPORT_GOOD;
+                       else
+                               if (us->ip_data)
+                                       return USB_STOR_TRANSPORT_FAILED;
+                               else
+                                       return USB_STOR_TRANSPORT_GOOD;
+               }
+
+               /* otherwise, we interpret the data normally */
+               switch (us->ip_data) {
+               case 0x0001: 
+                       return USB_STOR_TRANSPORT_GOOD;
+               case 0x0002: 
+                       return USB_STOR_TRANSPORT_FAILED;
+               default: 
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+       }
+       US_DEBUGP("pop_CB_status, reached end of function\n");
+       return USB_STOR_TRANSPORT_ERROR;
+}
+
+static int Bulk_reset(struct us_data *us)
+{
+       int result;
+
+       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                US_BULK_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                US_BULK_RESET_HARD, us->ifnum,
+                                NULL, 0, HZ*5);
+       if (result)
+               US_DEBUGP("Bulk hard reset failed %d\n", result);
+       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
+       usb_clear_halt(us->pusb_dev, usb_sndbulkpipe(us->pusb_dev, us->ep_out));
+
+       /* long wait for reset */
+       schedule_timeout(HZ*6);
+
+       return result;
+}
+
+/*
+ * The bulk only protocol handler.
+ *     Uses the in and out endpoints to transfer commands and data
+ */
+static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
+{
+       struct bulk_cb_wrap bcb;
+       struct bulk_cs_wrap bcs;
+       int result;
+       int pipe;
+       int partial;
+
+       /* set up the command wrapper */
+       bcb.Signature = US_BULK_CB_SIGN;
+       bcb.DataTransferLength = us_transfer_length(srb);
+       bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
+       bcb.Tag = srb->serial_number;
+       bcb.Lun = 0;
+       bcb.Length = srb->cmd_len;
+
+       /* construct the pipe handle */
+       pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+
+       /* copy the command payload */
+       memset(bcb.CDB, 0, sizeof(bcb.CDB));
+       memcpy(bcb.CDB, srb->cmnd, bcb.Length);
+
+       /* send it to out endpoint */
+       US_DEBUGP("Bulk command S 0x%x T 0x%x L %d F %d CL %d\n",
+                 bcb.Signature, bcb.Tag, bcb.DataTransferLength,
+                 bcb.Flags, bcb.Length);
+       result = usb_bulk_msg(us->pusb_dev, pipe, &bcb,
+                             US_BULK_CB_WRAP_LEN, &partial, HZ*5);
+       US_DEBUGP("Bulk command transfer result=%d\n", result);
+
+       /* if we stall, we need to clear it before we go on */
+       if (result == -EPIPE) {
+               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+               usb_clear_halt(us->pusb_dev, pipe);
+       }
+  
+       /* if the command transfered well, then we go to the data stage */
+       /* FIXME: Regardless of the status of the data stage, we go on to the
+        * status stage.  Note that this implies that if a command is
+        * partially successful, we rely on the device reporting an error
+        * the CSW. The spec says that the device may just decide to short us.
+        */
+       if (result == 0) {
+               /* send/receive data payload, if there is any */
+               if (bcb.DataTransferLength) {
+                       result = us_transfer(srb, bcb.Flags);
+                       US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+#if 0
+                       if ((result < 0) && (result != USB_ST_DATAUNDERRUN) 
+                           && (result != USB_ST_STALL)) {
+                               US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+                               return DID_ABORT << 16;
+                       }
+#endif
+               }
+       }
+
+       /* See flow chart on pg 15 of the Bulk Only Transport spec for
+        * an explanation of how this code works.
+        */
+
+       /* construct the pipe handle */
+       pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+
+       /* get CSW for device status */
+       result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
+                             US_BULK_CS_WRAP_LEN, &partial, HZ*5);
+
+       /* did the attempt to read the CSW fail? */
+       if (result == -EPIPE) {
+               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+               usb_clear_halt(us->pusb_dev, pipe);
+
+               /* get the status again */
+               result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
+                                     US_BULK_CS_WRAP_LEN, &partial, HZ*5);
+   
+               /* if it fails again, we need a reset and return an error*/
+               if (result == -EPIPE) {
+                       Bulk_reset(us);
+                       return (DID_ABORT << 16);
+               }
+       }
+
+       /* if we still have a failure at this point, we're in trouble */
+       if (result) {
+               US_DEBUGP("Bulk status result = 0x%x\n", result);
+               return DID_ABORT << 16;
+       }
+
+       /* check bulk status */
+       US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n",
+                 bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);
+       if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||
+           bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
+               US_DEBUGP("Bulk logical error\n");
+               return DID_ABORT << 16;
+       }
+
+       /* based on the status code, we report good or bad */
+       switch (bcs.Status) {
+       case US_BULK_STAT_OK:
+               /* if there is residue, we really didn't finish the command */
+               if (bcs.Residue)
+                       return DID_ERROR << 16;
+               else
+                       return DID_OK << 16;
+
+       case US_BULK_STAT_FAIL:
+               return DID_ERROR << 16;
+
+       case US_BULK_STAT_PHASE:
+               Bulk_reset(us);
+               return DID_ERROR << 16;
+       }
+
+       return DID_OK << 16;        /* check sense required */
+}
+
+/***********************************************************************
+ * Host functions 
+ ***********************************************************************/
+
+/* detect adapter (always true ) */
+static int us_detect(struct SHT *sht)
+{
+       /* FIXME - not nice at all, but how else ? */
+       struct us_data *us = (struct us_data *)sht->proc_dir;
+       char name[32];
+
+       /* set up our name */
+       sprintf(name, "usbscsi%d", us->host_number);
+       sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL);
+       if (!sht->proc_name)
+               return 0;
+       strcpy(sht->proc_name, name);
+
+       /* we start with no /proc directory entry */
+       sht->proc_dir = NULL;
+
+       /* register the host */
+       us->host = scsi_register(sht, sizeof(us));
+       if (us->host) {
+               us->host->hostdata[0] = (unsigned long)us;
+               us->host_no = us->host->host_no;
+               return 1;
+       }
+
+       /* odd... didn't register properly.  Abort and free pointers */
+       kfree(sht->proc_name);
+       sht->proc_name = NULL;
+       sht->name = NULL;
+       return 0;
+}
+
+/* release - must be here to stop scsi
+ *     from trying to release IRQ etc.
+ *     Kill off our data
+ */
+static int us_release(struct Scsi_Host *psh)
+{
+       struct us_data *us = (struct us_data *)psh->hostdata[0];
+       struct us_data *prev = (struct us_data *)&us_list;
+
+       if (us->irq_handle) {
+               usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
+               us->irq_handle = NULL;
+       }
+       if (us->pusb_dev)
+               usb_deregister(&storage_driver);
+
+       /* FIXME - leaves hanging host template copy */
+       /* (because scsi layer uses it after removal !!!) */
+       while (prev->next != us)
+               prev = prev->next;
+       prev->next = us->next;
+       return 0;
+}
+
+/* run command */
+static int us_command( Scsi_Cmnd *srb )
+{
+       US_DEBUGP("Bad use of us_command\n");
+
+       return DID_BAD_TARGET << 16;
+}
+
+/* run command */
+static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
+{
+       struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+
+       US_DEBUGP("Command wakeup\n");
+       if (us->srb) {
+               /* busy */
+       }
+       srb->host_scribble = (unsigned char *)us;
+       us->srb = srb;
+       srb->scsi_done = done;
+       us->action = US_ACT_COMMAND;
+
+       /* wake up the process task */
+
+       wake_up_interruptible(&us->waitq);
+
+       return 0;
+}
+
+/* FIXME: This doesn't actually abort anything */
+static int us_abort( Scsi_Cmnd *srb )
+{
+       return 0;
+}
+
+static int us_bus_reset( Scsi_Cmnd *srb )
+{
+       //  struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+
+       US_DEBUGP("Bus reset requested\n");
+       //  us->transport_reset(us);
+       return SUCCESS;
+}
+
+/* FIXME: This doesn't actually reset anything */
+static int us_host_reset( Scsi_Cmnd *srb )
+{
+       return 0;
+}
+
+/***********************************************************************
+ * /proc/scsi/ functions
+ ***********************************************************************/
+
+/* we use this macro to help us write into the buffer */
+#undef SPRINTF
+#define SPRINTF(args...) do { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } while (0)
+
+int usb_stor_proc_info (char *buffer, char **start, off_t offset, 
+                       int length, int hostno, int inout)
+{
+       struct us_data *us = us_list;
+       char *pos = buffer;
+       char *tmp_ptr;
+
+       /* find our data from hostno */
+       while (us) {
+               if (us->host_no == hostno)
+                       break;
+               us = us->next;
+       }
+
+       /* if we couldn't find it, we return an error */
+       if (!us)
+               return -ESRCH;
+
+       /* if someone is sending us data, just throw it away */
+       if (inout)
+               return length;
+
+       /* print the controler name */
+       SPRINTF ("Host scsi%d: usb-storage\n", hostno);
+
+       /* print product and vendor strings */
+       tmp_ptr = kmalloc(256, GFP_KERNEL);
+       if (!us->pusb_dev || !tmp_ptr) {
+               SPRINTF("    Vendor: Unknown Vendor\n");
+               SPRINTF("   Product: Unknown Product\n");
+       } else {
+               SPRINTF("    Vendor: ");
+               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer, tmp_ptr, 256) > 0)
+                       SPRINTF("%s\n", tmp_ptr);
+               else
+                       SPRINTF("Unknown Vendor\n");
+    
+               SPRINTF("   Product: ");
+               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0)
+                       SPRINTF("%s\n", tmp_ptr);
+               else
+                       SPRINTF("Unknown Product\n");
+               kfree(tmp_ptr);
+       }
+
+       SPRINTF("  Protocol: ");
+       switch (us->protocol) {
+       case US_PR_CB:
+               SPRINTF("Control/Bulk\n");
+               break;
+    
+       case US_PR_CBI:
+               SPRINTF("Control/Bulk/Interrupt\n");
+               break;
+    
+       case US_PR_BULK:
+               SPRINTF("Bulk only\n");
+               break;
+    
+       default:
+               SPRINTF("Unknown Protocol\n");
+               break;
+       }
+
+       /* show the GUID of the device */
+       SPRINTF("      GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
+
+       /*
+        * Calculate start of next buffer, and return value.
+        */
+       *start = buffer + offset;
+
+       if ((pos - buffer) < offset)
+               return (0);
+       else if ((pos - buffer - offset) < length)
+               return (pos - buffer - offset);
+       else
+               return (length);
+}
+
+/*
+ * this defines our 'host'
+ */
+
+static Scsi_Host_Template my_host_template = {
+       NULL,                       /* next */
+       NULL,                       /* module */
+       NULL,                       /* proc_dir */
+       usb_stor_proc_info,
+       NULL,                       /* name - points to unique */
+       us_detect,
+       us_release,
+       NULL,                       /* info */
+       NULL,                       /* ioctl */
+       us_command,
+       us_queuecommand,
+       NULL,                       /* eh_strategy */
+       us_abort,
+       us_bus_reset,
+       us_bus_reset,
+       us_host_reset,
+       NULL,                       /* abort */
+       NULL,                       /* reset */
+       NULL,                       /* slave_attach */
+       NULL,                       /* bios_param */
+       NULL,                       /* select_queue_depths */
+       1,                          /* can_queue */
+       -1,                         /* this_id */
+       SG_ALL,             /* sg_tablesize */
+       1,                          /* cmd_per_lun */
+       0,                          /* present */
+       FALSE,              /* unchecked_isa_dma */
+       FALSE,              /* use_clustering */
+       TRUE,                       /* use_new_eh_code */
+       TRUE                        /* emulated */
+};
+
+static unsigned char sense_notready[] = {
+       0x70,                       /* current error */
+       0x00,
+       0x02,                       /* not ready */
+       0x00,
+       0x00,
+       0x0a,                       /* additional length */
+       0x00,
+       0x00,
+       0x00,
+       0x00,
+       0x04,                       /* not ready */
+       0x03,                       /* manual intervention */
+       0x00,
+       0x00,
+       0x00,
+       0x00
+};
+
+static int usb_stor_control_thread(void * __us)
+{
+       struct us_data *us = (struct us_data *)__us;
+       int action;
+
+       lock_kernel();
+
+       /*
+        * This thread doesn't need any user-level access,
+        * so get rid of all our resources..
+        */
+       daemonize();
+
+       sprintf(current->comm, "usbscsi%d", us->host_number);
+
+       unlock_kernel();
+
+       up(us->notify);
+
+       for(;;) {
+               siginfo_t info;
+               int unsigned long signr;
+
+               interruptible_sleep_on(&us->waitq);
+
+               action = us->action;
+               us->action = 0;
+
+               /* FIXME: we need to examine placment of break; and 
+                * scsi_done() calls */
+
+               switch (action) {
+               case US_ACT_COMMAND:
+                       /* bad device */
+                       if (us->srb->target || us->srb->lun) {
+                               US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n",
+                                          us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);
+                               us->srb->result = DID_BAD_TARGET << 16;
+
+                               us->srb->scsi_done(us->srb);
+                               us->srb = NULL;
+                               break;
+                       }
+
+                       /* our device has gone - pretend not ready */
+                       /* FIXME: we also need to handle INQUIRY here, 
+                        * probably */
+                       if (!us->pusb_dev) {
+                               if (us->srb->cmnd[0] == REQUEST_SENSE) {
+                                       memcpy(us->srb->request_buffer, sense_notready, 
+                                              sizeof(sense_notready));
+                                       us->srb->result = DID_OK << 16;
+                               } else {
+                                       us->srb->result = (DID_OK << 16) | 2;
+                               }
+
+                               us->srb->scsi_done(us->srb);
+                               us->srb = NULL;
+                               break;
+                       }
+
+                       /* we've got a command, let's do it! */
+                       US_DEBUG(us_show_command(us->srb));
+
+                       /* FIXME: this is to support Shuttle E-USB bridges, it 
+                        * appears */
+                       if (us->srb->cmnd[0] == START_STOP &&
+                           us->pusb_dev->descriptor.idProduct == 0x0001 &&
+                           us->pusb_dev->descriptor.idVendor == 0x04e6)
+                               us->srb->result = DID_OK << 16;
+                       else {
+                               us->proto_handler(us->srb, us);
+                       }
+      
+                       US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result);
+                       us->srb->scsi_done(us->srb);
+                       us->srb = NULL;
+                       break;
+      
+               case US_ACT_ABORT:
+                       break;
+
+               case US_ACT_DEVICE_RESET:
+                       break;
+
+               case US_ACT_BUS_RESET:
+                       break;
+
+               case US_ACT_HOST_RESET:
+                       break;
+
+               } /* end switch on action */
+    
+               if (signal_pending(current)) {
+                       /* sending SIGUSR1 makes us print out some info */
+                       spin_lock_irq(&current->sigmask_lock);
+                       signr = dequeue_signal(&current->blocked, &info);
+                       spin_unlock_irq(&current->sigmask_lock);
+
+                       if (signr == SIGUSR2) {
+                               usb_stor_debug = !usb_stor_debug;
+                               printk(USB_STORAGE "debug toggle = %d\n", usb_stor_debug);
+                       } else {
+                               break;      /* exit the loop on any other signal */
+                       }
+               }
+       }
+  
+       //  MOD_DEC_USE_COUNT;
+
+       printk("usb_stor_control_thread exiting\n");
+
+       /* FIXME: this is a hack to allow for debugging */
+       // scsi_unregister_module(MODULE_SCSI_HA, us->htmplt);
+
+       return 0;
+}      
+
+/* Probe to see if a new device is actually a SCSI device */
+static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
+{
+       struct usb_interface_descriptor *interface;
+       int i;
+       char mf[32];                 /* manufacturer */
+       char prod[32];               /* product */
+       char serial[32];             /* serial number */
+       struct us_data *ss = NULL;
+       unsigned int flags = 0;
+       GUID(guid);                  /* Global Unique Identifier */
+       struct us_data *prev;
+       Scsi_Host_Template *htmplt;
+       int protocol = 0;
+       int subclass = 0;
+       struct usb_interface_descriptor *altsetting = 
+               &(dev->actconfig->interface[ifnum].altsetting[0]); 
+
+       /* clear the GUID and fetch the strings */
+       GUID_CLEAR(guid);
+       memset(mf, 0, sizeof(mf));
+       memset(prod, 0, sizeof(prod));
+       memset(serial, 0, sizeof(serial));
+       if (dev->descriptor.iManufacturer)
+               usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf));
+       if (dev->descriptor.iProduct)
+               usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod));
+       if (dev->descriptor.iSerialNumber)
+               usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial));
+       
+       /* let's examine the device now */
+
+       /* We make an exception for the shuttle E-USB */
+       if (dev->descriptor.idVendor == 0x04e6 &&
+           dev->descriptor.idProduct == 0x0001) {
+               protocol = US_PR_CB;
+               subclass = US_SC_8070;      /* an assumption */
+       } else if (dev->descriptor.bDeviceClass != 0 ||
+                  altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
+                  altsetting->bInterfaceSubClass < US_SC_MIN ||
+                  altsetting->bInterfaceSubClass > US_SC_MAX) {
+               /* if it's not a mass storage, we go no further */
+               return NULL;
+       }
+
+       /* At this point, we know we've got a live one */
+       US_DEBUGP("USB Mass Storage device detected\n");
+
+       /* Create a GUID for this device */
+       if (dev->descriptor.iSerialNumber && serial[0]) {
+               /* If we have a serial number, and it's a non-NULL string */
+               make_guid(guid, dev->descriptor.idVendor, 
+                         dev->descriptor.idProduct, serial);
+       } else {
+               /* We don't have a serial number, so we use 0 */
+               make_guid(guid, dev->descriptor.idVendor, 
+                         dev->descriptor.idProduct, "0");
+       }
+
+       /* Now check if we have seen this GUID before, and restore
+        * the flags if we find it
+        */
+       for (ss = us_list; ss != NULL; ss = ss->next) {
+               if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid))    {
+                       US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
+                                 GUID_ARGS(guid));
+                       flags = ss->flags;
+                       break;
+               }
+       }
+
+       /* If ss == NULL, then this is a new device.  Allocate memory for it */
+       if (!ss) {
+               if ((ss = (struct us_data *)kmalloc(sizeof(*ss), 
+                                                   GFP_KERNEL)) == NULL) {
+                       printk(KERN_WARNING USB_STORAGE "Out of memory\n");
+                       return NULL;
+               }
+               memset(ss, 0, sizeof(struct us_data));
+       }
+
+       /* Initialize the us_data structure with some useful info */
+       interface = altsetting;
+       ss->flags = flags;
+       ss->ifnum = ifnum;
+       ss->pusb_dev = dev;
+       ss->attention_done = 0;
+
+       /* If the device has subclass and protocol, then use that.  Otherwise, 
+        * take data from the specific interface.
+        */
+       if (subclass) {
+               ss->subclass = subclass;
+               ss->protocol = protocol;
+       } else {
+               ss->subclass = interface->bInterfaceSubClass;
+               ss->protocol = interface->bInterfaceProtocol;
+       }
+
+       /* set the handler pointers based on the protocol */
+       US_DEBUGP("Transport: ");
+       switch (ss->protocol) {
+       case US_PR_CB:
+               US_DEBUGPX("Control/Bulk\n");
+               ss->transport = CB_transport;
+               ss->transport_reset = CB_reset;
+               break;
+
+       case US_PR_CBI:
+               US_DEBUGPX("Control/Bulk/Interrupt\n");
+               ss->transport = CB_transport;
+               ss->transport_reset = CB_reset;
+               break;
+
+       case US_PR_BULK:
+               US_DEBUGPX("Bulk\n");
+               ss->transport = Bulk_transport;
+               ss->transport_reset = Bulk_reset;
+               break;
+
+       default:
+               US_DEBUGPX("Unknown\n");    
+               kfree(ss);
+               return NULL;
+               break;
+       }
+
+       /*
+        * We are expecting a minimum of 2 endpoints - in and out (bulk).
+        * An optional interrupt is OK (necessary for CBI protocol).
+        * We will ignore any others.
+        */
+       for (i = 0; i < interface->bNumEndpoints; i++) {
+               /* is it an BULK endpoint? */
+               if ((interface->endpoint[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK)
+                   == USB_ENDPOINT_XFER_BULK) {
+                       if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN)
+                               ss->ep_in = interface->endpoint[i].bEndpointAddress &
+                                       USB_ENDPOINT_NUMBER_MASK;
+                       else
+                               ss->ep_out = interface->endpoint[i].bEndpointAddress &
+                                       USB_ENDPOINT_NUMBER_MASK;
+               }
+
+               /* is it an interrupt endpoint? */
+               if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 
+                   == USB_ENDPOINT_XFER_INT) {
+                       ss->ep_int = interface->endpoint[i].bEndpointAddress &
+                               USB_ENDPOINT_NUMBER_MASK;
+               }
+       }
+       US_DEBUGP("Endpoints In %d Out %d Int %d\n",
+                 ss->ep_in, ss->ep_out, ss->ep_int);
+
+       /* Do some basic sanity checks, and bail if we find a problem */
+       if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
+           !ss->ep_in || !ss->ep_out || 
+           (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
+               US_DEBUGP("Problems with device\n");
+               if (ss->host) {
+                       scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);
+                       kfree(ss->htmplt->name);
+                       kfree(ss->htmplt);
+               }
+
+               kfree(ss);
+               return NULL;
+       }
+
+       /* If this is a new device (i.e. we haven't seen it before), we need to
+        * generate a scsi host definition, and register with scsi above us 
+        */
+       if (!ss->host) {
+               /* copy the GUID we created before */
+               US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
+               memcpy(ss->guid, guid, sizeof(guid));
+
+               /* set class specific stuff */
+               US_DEBUGP("Protocol: ");
+               switch (ss->subclass) {
+               case US_SC_RBC:
+                       US_DEBUGPX("Reduced Block Commands\n");
+                       break;
+
+               case US_SC_8020:
+                       US_DEBUGPX("8020\n");
+                       break;
+
+               case US_SC_QIC:
+                       US_DEBUGPX("QIC157\n");
+                       break;
+
+               case US_SC_8070:
+                       US_DEBUGPX("8070\n");
+                       break;
+
+               case US_SC_SCSI:
+                       US_DEBUGPX("Transparent SCSI\n");
+                       ss->proto_handler = transparent_scsi_command;
+                       break;
+
+               case US_SC_UFI:
+                       US_DEBUGPX("UFI\n");
+                       ss->proto_handler = ufi_command;
+                       break;
+
+               default:
+                       US_DEBUGPX("Unknown\n");
+                       break;
+               }
+
+               /* We only handle certain protocols.  Currently, these are
+                *the only ones that devices use.
+                */
+               if ((ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_UFI)) {
+                       US_DEBUGP("Sorry, we do not support that protocol yet.\n");
+                       US_DEBUGP("If you have a device which uses one of the unsupported\n");
+                       US_DEBUGP("protocols, please contact mdharm-usb@one-eyed-alien.net\n");
+     
+                       kfree(ss);
+                       return NULL;
+               }
+
+               /* Allocate memory for the SCSI Host Template */
+               if ((htmplt = (Scsi_Host_Template *)
+                    kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
+
+                       printk(KERN_WARNING USB_STORAGE "Out of memory\n");
+
+                       kfree(ss);
+                       return NULL;
+               }
+
+               /* Initialize the host template based on the default one */
+               memcpy(htmplt, &my_host_template, sizeof(my_host_template));
+
+               /* Grab the next host number */
+               ss->host_number = my_host_number++;
+
+               /* MDD: FIXME: this is bad.  We abuse this pointer so we
+                * can pass the ss pointer to the host controler thread
+                * in us_detect
+                */
+               (struct us_data *)htmplt->proc_dir = ss; 
+
+               /* shuttle E-USB */     
+               if (dev->descriptor.idVendor == 0x04e6 &&
+                   dev->descriptor.idProduct == 0x0001) {
+                       __u8 qstat[2];
+                       int result;
+           
+                       result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
+                                                1, 0xC0,
+                                                0, ss->ifnum,
+                                                qstat, 2, HZ*5);
+                       US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]);
+                       init_waitqueue_head(&ss->ip_waitq);
+                       ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
+                       result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
+                                                255, (void *)ss, &ss->irq_handle);
+                       if (result)
+                               return NULL;
+
+                       interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
+               } else if (ss->protocol == US_PR_CBI)
+               {
+                       int result; 
+
+                       init_waitqueue_head(&ss->ip_waitq);
+
+                       /* set up the IRQ pipe and handler */
+                       /* FIXME: This needs to get the period from the device */
+                       ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
+                       result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
+                                                255, (void *)ss, &ss->irq_handle);
+                       if (result) {
+                               US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",
+                                         result);
+                       }
+               }
+    
+
+               /* start up our thread */
+               {
+                       DECLARE_MUTEX_LOCKED(sem);
+
+                       init_waitqueue_head(&ss->waitq);
+
+                       ss->notify = &sem;
+                       ss->pid = kernel_thread(usb_stor_control_thread, ss,
+                                               CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+                       if (ss->pid < 0) {
+                               printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n");
+                               kfree(htmplt);
+
+                               kfree(ss);
+                               return NULL;
+                       }
+
+                       /* wait for it to start */
+                       down(&sem);
+               }
+
+               /* now register - our detect function will be called */
+               scsi_register_module(MODULE_SCSI_HA, htmplt);
+
+               /* put us in the list */
+               prev = (struct us_data *)&us_list;
+               while (prev->next)
+                       prev = prev->next;
+               prev->next = ss;
+       }
+
+       printk(KERN_INFO "WARNING: USB Mass Storage data integrity not assured\n");
+       printk(KERN_INFO "USB Mass Storage device found at %d\n", dev->devnum);
+
+       return ss;
+}
+
+/* Handle a disconnect event from the USB core */
+static void storage_disconnect(struct usb_device *dev, void *ptr)
+{
+       struct us_data *ss = ptr;
+
+       if (!ss)
+               return;
+
+       ss->pusb_dev = NULL;
+       //  MOD_DEC_USE_COUNT;
+}
+
+
+/***********************************************************************
+ * Initialization and registration
+ ***********************************************************************/
+
+int __init usb_stor_init(void)
+{
+       //  MOD_INC_USE_COUNT;
+
+       if (sizeof(my_host_template) != SCSI_HOST_TEMPLATE_SIZE) {
+               printk(KERN_ERR "usb-storage: SCSI_HOST_TEMPLATE_SIZE does not match\n") ;
+               printk(KERN_ERR "usb-storage: expected %d bytes, got %d bytes\n", 
+                      SCSI_HOST_TEMPLATE_SIZE, sizeof(my_host_template)) ;
+
+               return -1 ;
+       }
+
+       /* register the driver, return -1 if error */
+       if (usb_register(&storage_driver) < 0)
+               return -1;
+
+       printk(KERN_INFO "USB Mass Storage support registered.\n");
+       return 0;
+}
+
+void __exit usb_stor_exit(void)
+{
+       usb_deregister(&storage_driver) ;
+}
+
+module_init(usb_stor_init) ;
+module_exit(usb_stor_exit) ;
diff --git a/drivers/usb/usb-storage.h b/drivers/usb/usb-storage.h
new file mode 100644 (file)
index 0000000..80a03f3
--- /dev/null
@@ -0,0 +1,130 @@
+/* Driver for USB mass storage - include file
+ *
+ * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *
+ */
+
+#include <linux/config.h>
+
+#define USB_STORAGE "usb-storage: "
+
+extern int usb_stor_debug;
+
+#ifdef CONFIG_USB_STORAGE_DEBUG
+void us_show_command(Scsi_Cmnd *srb);
+#define US_DEBUGP(x...) { if(usb_stor_debug) printk( KERN_DEBUG USB_STORAGE ## x ); }
+#define US_DEBUGPX(x...) { if(usb_stor_debug) printk( ## x ); }
+#define US_DEBUG(x)  { if(usb_stor_debug) x; }
+#else
+#define US_DEBUGP(x...)
+#define US_DEBUGPX(x...)
+#define US_DEBUG(x)
+#endif
+
+/* bit set if input */
+extern unsigned char us_direction[256/8];
+#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
+
+/* Sub Classes */
+
+#define US_SC_RBC      1               /* Typically, flash devices */
+#define US_SC_8020     2               /* CD-ROM */
+#define US_SC_QIC      3               /* QIC-157 Tapes */
+#define US_SC_UFI      4               /* Floppy */
+#define US_SC_8070     5               /* Removable media */
+#define US_SC_SCSI     6               /* Transparent */
+#define US_SC_MIN      US_SC_RBC
+#define US_SC_MAX      US_SC_SCSI
+
+/* Protocols */
+
+#define US_PR_CB       1               /* Control/Bulk w/o interrupt */
+#define US_PR_CBI      0               /* Control/Bulk/Interrupt */
+#define US_PR_BULK     0x50            /* bulk only */
+
+/*
+ * Bulk only data structures (Zip 100, for example)
+ */
+
+/* command block wrapper */
+struct bulk_cb_wrap {
+       __u32   Signature;              /* contains 'USBC' */
+       __u32   Tag;                    /* unique per command id */
+       __u32   DataTransferLength;     /* size of data */
+       __u8    Flags;                  /* direction in bit 0 */
+       __u8    Lun;                    /* LUN normally 0 */
+       __u8    Length;                 /* of of the CDB */
+       __u8    CDB[16];                /* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN    31
+#define US_BULK_CB_SIGN                0x43425355
+#define US_BULK_FLAG_IN                1
+#define US_BULK_FLAG_OUT       0
+
+/* command status wrapper */
+struct bulk_cs_wrap {
+       __u32   Signature;              /* should = 'USBS' */
+       __u32   Tag;                    /* same as original command */
+       __u32   Residue;                /* amount not transferred */
+       __u8    Status;                 /* see below */
+       __u8    Filler[18];
+};
+
+#define US_BULK_CS_WRAP_LEN    13
+#define US_BULK_CS_SIGN                0x53425355
+#define US_BULK_STAT_OK                0
+#define US_BULK_STAT_FAIL      1
+#define US_BULK_STAT_PHASE     2
+
+#define US_BULK_RESET          0xff
+#define US_BULK_RESET_SOFT     1
+#define US_BULK_RESET_HARD     0
+
+/*
+ * Transport return codes
+ */
+
+#define USB_STOR_TRANSPORT_GOOD    0    /* Transport good, command good    */
+#define USB_STOR_TRANSPORT_FAILED  1    /* Transport good, command failed  */
+#define USB_STOR_TRANSPORT_ERROR   2    /* Transport bad (i.e. device dead */
+
+/*
+ * CBI style
+ */
+
+#define US_CBI_ADSC            0
+
+/* 
+ * GUID definitions
+ */
+
+#define GUID(x) __u32 x[3]
+#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2])
+#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0;
+#define GUID_NONE(x) (!x[0] && !x[1] && !x[2])
+#define GUID_FORMAT "%08x%08x%08x"
+#define GUID_ARGS(x) x[0], x[1], x[2]
+
+static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial)
+{
+       pg[0] = (vendor << 16) | product;
+       pg[1] = pg[2] = 0;
+       while (*serial) {
+               pg[1] <<= 4;
+               pg[1] |= pg[2] >> 28;
+               pg[2] <<= 4;
+               if (*serial >= 'a')
+                       *serial -= 'a' - 'A';
+               pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0'
+                       : *serial - 'A' + 10;
+               serial++;
+       }
+}
+
+/* Flag definitions */
+#define US_FL_IP_STATUS              0x00000001         /* status uses interrupt */
+#define US_FL_FIXED_COMMAND   0x00000002 /* expand commands to fixed size */
+#define US_FL_MODE_XLATE      0x00000004 /* translate _6 to _10 comands for
+                                           Win/MacOS compatibility */
diff --git a/drivers/usb/usb_storage.c b/drivers/usb/usb_storage.c
deleted file mode 100644 (file)
index eea25b9..0000000
+++ /dev/null
@@ -1,1849 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- *
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Further reference:
- *     This driver is based on the 'USB Mass Storage Class' document. This
- *     describes in detail the protocol used to communicate with such
- *      devices.  Clearly, the designers had SCSI commands in mind when they
- *      created this document.  The commands are all similar to commands
- *      in the SCSI-II specification.
- *
- *     It is important to note that in a number of cases this class exhibits
- *     class-specific exemptions from the USB specification. Notably the
- *     usage of NAK, STALL and ACK differs from the norm, in that they are
- *     used to communicate wait, failed and OK on commands.
- *     Also, for certain devices, the interrupt endpoint is used to convey
- *     status of a command.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/malloc.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-#include <linux/blk.h>
-#include "../scsi/scsi.h"
-#include "../scsi/hosts.h"
-#include "../scsi/sd.h"
-
-#include "usb.h"
-#include "usb_storage.h"
-
-/*
- * This is the size of the structure Scsi_Host_Template.  We create
- * an instance of this structure in this file and this is a check
- * to see if this structure may have changed within the SCSI module.
- * This is by no means foolproof, but it does help us some.
- */
-#define SCSI_HOST_TEMPLATE_SIZE                        (104)
-
-/* direction table -- this indicates the direction of the data
- * transfer for each command code -- a 1 indicates input
- */
-unsigned char us_direction[256/8] = {
-       0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 
-       0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*
- * Per device data
- */
-
-static int my_host_number;
-
-int usb_stor_debug = 1;
-
-struct us_data;
-
-typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
-typedef int (*trans_reset)(struct us_data*);
-typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
-
-struct us_data {
-       struct us_data  *next;                   /* next device */
-       struct usb_device       *pusb_dev;       /* this usb_device */
-       unsigned int            flags;           /* from filter initially */
-       __u8                    ifnum;           /* interface number */
-       __u8                    ep_in;           /* in endpoint */
-       __u8                    ep_out;          /* out ....... */
-       __u8                    ep_int;          /* interrupt . */
-       __u8                    subclass;        /* as in overview */
-       __u8                    protocol;        /* .............. */
-       __u8                    attention_done;  /* force attn on first cmd */
-       trans_cmnd              transport;       /* protocol specific do cmd */
-       trans_reset             transport_reset; /* .......... device reset */
-       proto_cmnd              proto_handler;   /* protocol handler */
-       GUID(guid);                              /* unique dev id */
-       struct Scsi_Host        *host;           /* our dummy host data */
-       Scsi_Host_Template      *htmplt;         /* own host template */
-       int                     host_number;     /* to find us */
-       int                     host_no;         /* allocated by scsi */
-       Scsi_Cmnd               *srb;            /* current srb */
-       int                     action;          /* what to do */
-       wait_queue_head_t       waitq;           /* thread waits */
-       wait_queue_head_t       ip_waitq;        /* for CBI interrupts */
-       __u16                   ip_data;         /* interrupt data */
-       int                     ip_wanted;       /* needed */
-       int                     pid;             /* control thread */
-       struct semaphore        *notify;         /* wait for thread to begin */
-       void                    *irq_handle;     /* for USB int requests */
-       unsigned int            irqpipe;         /* pipe for release_irq */
-};
-
-/*
- * kernel thread actions
- */
-
-#define US_ACT_COMMAND         1
-#define US_ACT_ABORT           2
-#define US_ACT_DEVICE_RESET    3
-#define US_ACT_BUS_RESET       4
-#define US_ACT_HOST_RESET      5
-
-static struct us_data *us_list;
-
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum);
-static void storage_disconnect(struct usb_device *dev, void *ptr);
-static struct usb_driver storage_driver = {
-       "usb-storage",
-       storage_probe,
-       storage_disconnect,
-       { NULL, NULL }
-};
-
-/***********************************************************************
- * Data transfer routines
- ***********************************************************************/
-
-/* Transfer one buffer (breaking into packets if necessary)
- * Note that this function is necessary because if the device NAKs, we
- * need to know that information directly
- *
- * FIXME: is the above true?  Or will the URB status show ETIMEDOUT after
- * retrying several times allready?  Perhaps this is the way we should
- * be going anyway?
- */
-static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
-{
-       int max_size;
-       int this_xfer;
-       int result;
-       int partial;
-       int maxtry;
-
-       /* determine the maximum packet size for these transfers */
-       max_size = usb_maxpacket(us->pusb_dev, 
-                                pipe, usb_pipeout(pipe)) * 16;
-
-       /* while we have data left to transfer */
-       while (length) {
-
-               /* calculate how long this will be -- maximum or a remainder */
-               this_xfer = length > max_size ? max_size : length;
-               length -= this_xfer;
-
-               /* FIXME: this number is totally outrageous.  We need to pick
-                * a better (smaller) number).
-                */
-
-               /* setup the retry counter */
-               maxtry = 100;
-
-               /* set up the transfer loop */
-               do {
-                       /* transfer the data */
-                       US_DEBUGP("Bulk xfer 0x%x(%d) try #%d\n", 
-                                 (unsigned int)buf, this_xfer, 101 - maxtry);
-                       result = usb_bulk_msg(us->pusb_dev, pipe, buf,
-                                             this_xfer, &partial, HZ*5);
-                       US_DEBUGP("bulk_msg returned %d xferred %d/%d\n",
-                                 result, partial, this_xfer);
-
-                       /* if we stall, we need to clear it before we go on */
-                       if (result == -EPIPE) {
-                               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-                               usb_clear_halt(us->pusb_dev, pipe);
-                       }
-
-                       /* update to show what data was transferred */
-                       this_xfer -= partial;
-                       buf += partial;
-
-                       /* NAK - we retry a few times */
-                       if (result == -ETIMEDOUT) {
-
-                               US_DEBUGP("us_one_transfer: device NAKed\n");
-
-                               /* if our try counter reaches 0, bail out */
-                               if (!maxtry--)
-                                       return -ETIMEDOUT;
-
-                               /* just continue the while loop */
-                               continue;
-                       }
-      
-                       /* other errors (besides NAK) -- we just bail out*/
-                       if (result != 0) {
-                               US_DEBUGP("us_one_transfer: device returned error %d\n", result);
-                               return result;
-                       }
-
-                       /* continue until this transfer is done */
-               } while ( this_xfer );
-       }
-
-       /* if we get here, we're done and successful */
-       return 0;
-}
-
-static unsigned int us_transfer_length(Scsi_Cmnd *srb);
-
-/* transfer one SCSI command, using scatter-gather if requested */
-/* FIXME: what do the return codes here mean? */
-static int us_transfer(Scsi_Cmnd *srb, int dir_in)
-{
-       struct us_data *us = (struct us_data *)srb->host_scribble;
-       int i;
-       int result = -1;
-       unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
-               usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
-       /* FIXME: stop transferring data at us_transfer_length(), not 
-        * bufflen */
-       if (srb->use_sg) {
-               struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
-
-               for (i = 0; i < srb->use_sg; i++) {
-                       result = us_one_transfer(us, pipe, sg[i].address, sg[i].length);
-                       if (result)
-                               break;
-               }
-       }
-       else
-               result = us_one_transfer(us, pipe, srb->request_buffer, 
-                                        us_transfer_length(srb));
-
-       if (result < 0)
-               US_DEBUGP("us_transfer returning error %d\n", result);
-       return result;
-}
-
-/* calculate the length of the data transfer (not the command) for any
- * given SCSI command
- */
-static unsigned int us_transfer_length(Scsi_Cmnd *srb)
-{
-       int i;
-       unsigned int total = 0;
-
-       /* always zero for some commands */
-       switch (srb->cmnd[0]) {
-       case SEEK_6:
-       case SEEK_10:
-       case REZERO_UNIT:
-       case ALLOW_MEDIUM_REMOVAL:
-       case START_STOP:
-       case TEST_UNIT_READY:
-               return 0;
-
-       case REQUEST_SENSE:
-       case INQUIRY:
-       case MODE_SENSE:
-               return srb->cmnd[4];
-
-       case LOG_SENSE:
-       case MODE_SENSE_10:
-               return (srb->cmnd[7] << 8) + srb->cmnd[8];
-
-       default:
-               break;
-       }
-
-       if (srb->use_sg) {
-               struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
-
-               for (i = 0; i < srb->use_sg; i++) {
-                       total += sg[i].length;
-               }
-               return total;
-       }
-       else
-               return srb->request_bufflen;
-}
-
-/***********************************************************************
- * Protocol routines
- ***********************************************************************/
-
-static int CB_transport(Scsi_Cmnd *srb, struct us_data *us);
-static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us);
-
-static void ufi_command(Scsi_Cmnd *srb, struct us_data *us)
-{
-       int old_cmnd = 0;
-  
-       /* fix some commands -- this is a form of mode translation
-        * UFI devices only accept 12 byte long commands 
-        *
-        * NOTE: This only works because a Scsi_Cmnd struct field contains
-        * a unsigned char cmnd[12], so we know we have storage available
-        */
-
-       /* set command length to 12 bytes (this affects the transport layer) */
-       srb->cmd_len = 12;
-
-       /* determine the correct (or minimum) data length for these commands */
-       switch (us->srb->cmnd[0]) {
-
-               /* for INQUIRY, UFI devices only ever return 36 bytes */
-       case INQUIRY:
-               us->srb->cmnd[4] = 36;
-               break;
-
-               /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
-       case MODE_SENSE:
-       case MODE_SELECT:
-               /* save the command so we can tell what it was */
-               old_cmnd = srb->cmnd[0];
-
-               srb->cmnd[11] = 0;
-               srb->cmnd[10] = 0;
-               srb->cmnd[9] = 0;
-
-               /* if we're sending data, we send all.  If getting data, 
-                * get the minimum */
-               if (srb->cmnd[0] == MODE_SELECT)
-                       srb->cmnd[8] = srb->cmnd[4];
-               else
-                       srb->cmnd[8] = 8;
-
-               srb->cmnd[7] = 0;
-               srb->cmnd[6] = 0;
-               srb->cmnd[5] = 0;
-               srb->cmnd[4] = 0;
-               srb->cmnd[3] = 0;
-               srb->cmnd[2] = srb->cmnd[2];
-               srb->cmnd[1] = srb->cmnd[1];
-               srb->cmnd[0] = srb->cmnd[0] | 0x40;
-               break;
-
-               /* again, for MODE_SENSE_10, we get the minimum (8) */
-       case MODE_SENSE_10:
-               us->srb->cmnd[7] = 0;
-               us->srb->cmnd[8] = 8;
-               break;
-               /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
-       case REQUEST_SENSE:
-               us->srb->cmnd[4] = 18;
-               break;
-
-               /* change READ_6/WRITE_6 to READ_10/WRITE_10, which 
-                * are UFI commands */
-       case WRITE_6:
-       case READ_6:
-               srb->cmnd[11] = 0;
-               srb->cmnd[10] = 0;
-               srb->cmnd[9] = 0;
-               srb->cmnd[8] = srb->cmnd[4];
-               srb->cmnd[7] = 0;
-               srb->cmnd[6] = 0;
-               srb->cmnd[5] = srb->cmnd[3];
-               srb->cmnd[4] = srb->cmnd[2];
-               srb->cmnd[3] = srb->cmnd[1] & 0x1F;
-               srb->cmnd[2] = 0;
-               srb->cmnd[1] = srb->cmnd[1] & 0xE0;
-               srb->cmnd[0] = srb->cmnd[0] | 0x20;
-               break;
-       } /* end switch on cmnd[0] */
-  
-       /* send the command to the transport layer */
-       us->srb->result = us->transport(srb, us);
-
-       /* if we have an error, we're going to do a 
-        * REQUEST_SENSE automatically */
-
-       /* FIXME: we should only do this for device 
-        * errors, not system errors */
-       if (us->srb->result) {
-               int temp_result;
-               int count;
-               void* old_request_buffer;
-
-               US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n");
-
-               /* set the result so the higher layers expect this data */
-               us->srb->result = CHECK_CONDITION;
-
-               us->srb->cmnd[0] = REQUEST_SENSE;
-               us->srb->cmnd[1] = 0;
-               us->srb->cmnd[2] = 0;
-               us->srb->cmnd[3] = 0;
-               us->srb->cmnd[4] = 18;
-               us->srb->cmnd[5] = 0;
-    
-               /* set the buffer length for transfer */
-               old_request_buffer = us->srb->request_buffer;
-               us->srb->request_bufflen = 18;
-               us->srb->request_buffer = kmalloc(18, GFP_KERNEL);
-
-               /* FIXME: what if this command fails? */
-               temp_result = us->transport(us->srb, us);
-               US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
-
-               /* copy the data from the request buffer to the sense buffer */
-               for(count = 0; count < 18; count++)
-                       us->srb->sense_buffer[count] = 
-                               ((unsigned char *)(us->srb->request_buffer))[count];
-
-               US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
-                         us->srb->sense_buffer[2] & 0xf,
-                         us->srb->sense_buffer[12], us->srb->sense_buffer[13]);
-
-               /* we're done here */
-               kfree(us->srb->request_buffer);
-               us->srb->request_buffer = old_request_buffer;
-               return;
-       }
-  
-       /* FIXME: if we need to send more data, or recieve data, we should
-        * do it here.  Then, we can do status handling here also.
-        *
-        * This includes MODE_SENSE from above
-        */
-       if (old_cmnd == MODE_SENSE) {
-               unsigned char *dta = (unsigned char *)us->srb->request_buffer;
-
-               /* calculate the new length */
-               int length = (dta[0] << 8) + dta[1] + 2;
-
-               /* copy the available data length into the structure */
-               us->srb->cmnd[7] = length >> 8;
-               us->srb->cmnd[8] = length & 0xFF;
-
-               /* send the command to the transport layer */
-               us->srb->result = us->transport(srb, us);
-
-               /* FIXME: this assumes that the 2nd attempt is always
-                * successful convert MODE_SENSE_10 return data format 
-                * to MODE_SENSE_6 format */
-               dta[0] = dta[1];        /* data len */
-               dta[1] = dta[2];        /* med type */
-               dta[2] = dta[3];        /* dev-spec prm */
-               dta[3] = dta[7];        /* block desc len */
-               printk (KERN_DEBUG USB_STORAGE
-                       "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
-                       dta[0], dta[1], dta[2], dta[3]);
-       }
-
-       /* FIXME: if this was a TEST_UNIT_READY, and we get a NOT READY/
-        * LOGICAL DRIVE NOT READY then we do a START_STOP, and retry 
-        */
-
-       /* FIXME: here is where we need to fix-up the return data from 
-        * an INQUIRY command to show ANSI SCSI rev 2
-        */
-
-       /* FIXME: The rest of this is bogus.  usb_control_msg() will only
-        * return an error if we've really honked things up.  If it just
-        * needs a START_STOP, then we'll get some data back via 
-        * REQUEST_SENSE --  either way, this belongs at a higher level
-        */
-
-#if 0
-       /* For UFI, if this is the first time we've sent this TEST_UNIT_READY 
-        * command, we can try again
-        */
-       if (!done_start && (us->subclass == US_SC_UFI)
-           && (cmd[0] == TEST_UNIT_READY) && (result < 0)) {
-    
-               /* as per spec try a start command, wait and retry */
-               wait_ms(100);
-    
-               done_start++;
-               memset(cmd, 0, sizeof(cmd));
-               cmd[0] = START_STOP;
-               cmd[4] = 1;             /* start */
-    
-               result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-                                        US_CBI_ADSC, 
-                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                                        0, us->ifnum,
-                                        cmd, 12, HZ*5);
-               US_DEBUGP("Next usb_control_msg returns %d\n", result);
-    
-                               /* allow another retry */
-               retry++;
-               continue;
-       }
-#endif
-}
-
-static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
-{
-       unsigned int savelen = us->srb->request_bufflen;
-       unsigned int saveallocation = 0;
-
-#if 0
-       /* force attention on first command */
-       if (!us->attention_done) {
-               if (us->srb->cmnd[0] == REQUEST_SENSE) {
-                       US_DEBUGP("forcing unit attention\n");
-                       us->attention_done = 1;
-
-                       if (us->srb->result == USB_STOR_TRANSPORT_GOOD) {
-                               unsigned char *p = (unsigned char *)us->srb->request_buffer;
-       
-                               if ((p[2] & 0x0f) != UNIT_ATTENTION) {
-                                       p[2] = UNIT_ATTENTION;
-                                       p[12] = 0x29;   /* power on, reset or bus-reset */
-                                       p[13] = 0;
-                               } /* if ((p[2] & 0x0f) != UNIT_ATTENTION) */
-                       } /* if (us->srb->result == USB_STORE_TRANSPORT_GOOD) */
-               }
-       } /* if (!us->attention_done) */
-#endif
-
-       /* If the command has a variable-length payload, then we do them
-        * in two steps -- first we do the minimum, then we recalculate
-        * then length, and re-issue the command 
-        *
-        * we use savelen to remember how much buffer we really have
-        * we use savealloction to remember how much was really requested
-        */
-
-       /* FIXME: remove savelen based on mods to us_transfer_length() */
-       switch (us->srb->cmnd[0]) {
-       case REQUEST_SENSE:
-               if (us->srb->request_bufflen > 18)
-                       us->srb->request_bufflen = 18;
-               else
-                       break;
-               saveallocation = us->srb->cmnd[4];
-               us->srb->cmnd[4] = 18;
-               break;
-    
-       case INQUIRY:
-               if (us->srb->request_bufflen > 36)
-                       us->srb->request_bufflen = 36;
-               else
-                       break;
-               saveallocation = us->srb->cmnd[4];
-               us->srb->cmnd[4] = 36;
-               break;
-    
-       case MODE_SENSE:
-               if (us->srb->request_bufflen > 4)
-                       us->srb->request_bufflen = 4;
-               else
-                       break;
-               saveallocation = us->srb->cmnd[4];
-               us->srb->cmnd[4] = 4;
-               break;
-    
-       case LOG_SENSE:
-       case MODE_SENSE_10:
-               if (us->srb->request_bufflen > 8)
-                       us->srb->request_bufflen = 8;
-               else
-                       break;
-               saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8];
-               us->srb->cmnd[7] = 0;
-               us->srb->cmnd[8] = 8;
-               break;
-    
-       default:
-               break;
-       } /* end switch on cmnd[0] */
-  
-       /* This code supports devices which do not support {READ|WRITE}_6
-        * Apparently, neither Windows or MacOS will use these commands,
-        * so some devices do not support them
-        */
-       if (us->flags & US_FL_MODE_XLATE) {
-    
-               /* translate READ_6 to READ_10 */
-               if (us->srb->cmnd[0] == 0x08) {
-      
-                       /* get the control */
-                       us->srb->cmnd[9] = us->srb->cmnd[5];
-      
-                       /* get the length */
-                       us->srb->cmnd[8] = us->srb->cmnd[6];
-                       us->srb->cmnd[7] = 0;
-      
-                       /* set the reserved area to 0 */
-                       us->srb->cmnd[6] = 0;       
-      
-                       /* get LBA */
-                       us->srb->cmnd[5] = us->srb->cmnd[3];
-                       us->srb->cmnd[4] = us->srb->cmnd[2];
-                       us->srb->cmnd[3] = 0;
-                       us->srb->cmnd[2] = 0;
-      
-                       /* LUN and other info in cmnd[1] can stay */
-      
-                       /* fix command code */
-                       us->srb->cmnd[0] = 0x28;
-      
-                       US_DEBUGP("Changing READ_6 to READ_10\n");
-                       US_DEBUG(us_show_command(us->srb));
-               }
-    
-               /* translate WRITE_6 to WRITE_10 */
-               if (us->srb->cmnd[0] == 0x0A) {
-      
-                       /* get the control */
-                       us->srb->cmnd[9] = us->srb->cmnd[5];
-      
-                       /* get the length */
-                       us->srb->cmnd[8] = us->srb->cmnd[4];
-                       us->srb->cmnd[7] = 0;
-      
-                       /* set the reserved area to 0 */
-                       us->srb->cmnd[6] = 0;       
-      
-                       /* get LBA */
-                       us->srb->cmnd[5] = us->srb->cmnd[3];
-                       us->srb->cmnd[4] = us->srb->cmnd[2];
-                       us->srb->cmnd[3] = 0;
-                       us->srb->cmnd[2] = 0;
-           
-                       /* LUN and other info in cmnd[1] can stay */
-      
-                       /* fix command code */
-                       us->srb->cmnd[0] = 0x2A;
-
-                       US_DEBUGP("Changing WRITE_6 to WRITE_10\n");
-                       US_DEBUG(us_show_command(us->srb));
-               }
-       } /* end if (us->flags & US_FL_MODE_XLATE) */
-  
-       /* send the command to the transport layer */
-       us->srb->result = us->transport(us->srb, us);
-
-       /* if we have an error, we're going to do a REQUEST_SENSE 
-        * automatically */
-       /* FIXME: we should only do this for device errors, not 
-        * system errors */
-       if (us->srb->result) {
-               int temp_result;
-               int count;
-               void* old_request_buffer;
-
-               US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n");
-
-               /* set the result so the higher layers expect this data */
-               us->srb->result = CHECK_CONDITION;
-
-               us->srb->cmnd[0] = REQUEST_SENSE;
-               us->srb->cmnd[1] = 0;
-               us->srb->cmnd[2] = 0;
-               us->srb->cmnd[3] = 0;
-               us->srb->cmnd[4] = 18;
-               us->srb->cmnd[5] = 0;
-    
-               /* set the buffer length for transfer */
-               old_request_buffer = us->srb->request_buffer;
-               us->srb->request_bufflen = 18;
-               us->srb->request_buffer = kmalloc(18, GFP_KERNEL);
-
-               /* FIXME: what if this command fails? */
-               temp_result = us->transport(us->srb, us);
-               US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
-
-               /* copy the data from the request buffer to the sense buffer */
-               for(count = 0; count < 18; count++)
-                       us->srb->sense_buffer[count] = 
-                               ((unsigned char *)(us->srb->request_buffer))[count];
-
-               US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
-                         us->srb->sense_buffer[2] & 0xf,
-                         us->srb->sense_buffer[12], us->srb->sense_buffer[13]);
-
-               /* we're done here */
-               kfree(us->srb->request_buffer);
-               us->srb->request_buffer = old_request_buffer;
-               return;
-       }
-
-       if (savelen != us->srb->request_bufflen) {
-               unsigned char *p = (unsigned char *)us->srb->request_buffer;
-               unsigned int length = 0;
-    
-               /* set correct length and retry */
-               switch (us->srb->cmnd[0]) {
-
-                       /* FIXME: we should try to get all the sense data */
-               case REQUEST_SENSE:
-                       /* simply return 18 bytes */
-                       p[7] = 10;
-                       length = us->srb->request_bufflen;
-                       break;
-      
-               case INQUIRY:
-                       length = p[4] + 5 > savelen ? savelen : p[4] + 5;
-                       us->srb->cmnd[4] = length;
-                       break;
-      
-               case MODE_SENSE:
-                       US_DEBUGP("MODE_SENSE Mode data length is %d\n", p[0]);
-                       length = p[0] + 1 > savelen ? savelen : p[0] + 1;
-                       us->srb->cmnd[4] = length;
-                       break;
-      
-               case LOG_SENSE:
-                       length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4;
-                       us->srb->cmnd[7] = length >> 8;
-                       us->srb->cmnd[8] = length;
-                       break;
-      
-               case MODE_SENSE_10:
-                       US_DEBUGP("MODE_SENSE_10 Mode data length is %d\n",
-                                 (p[0] << 8) + p[1]);
-                       length = ((p[0] << 8) + p[1]) + 6 > savelen ? savelen : ((p[0] << 8) + p[1]) + 6;
-                       us->srb->cmnd[7] = length >> 8;
-                       us->srb->cmnd[8] = length;
-                       break;
-               } /* end switch on cmnd[0] */
-    
-               US_DEBUGP("Old/New length = %d/%d\n",
-                         savelen, length);
-    
-               /* issue the new command */
-               /* FIXME: this assumes that the second attempt is 
-                * always successful */
-               if (us->srb->request_bufflen != length) {
-                       US_DEBUGP("redoing cmd with len=%d\n", length);
-                       us->srb->request_bufflen = length;
-                       us->srb->result = us->transport(us->srb, us);
-               }
-    
-               /* reset back to original values */
-               us->srb->request_bufflen = savelen;
-
-               /* fix data as necessary */
-               switch (us->srb->cmnd[0]) {
-               case INQUIRY:
-                       if ((((unsigned char*)us->srb->request_buffer)[2] & 0x7) == 0) { 
-                               US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n");
-                               ((unsigned char*)us->srb->request_buffer)[2] |= 2;
-                       }
-                       /* FALL THROUGH */
-               case REQUEST_SENSE:
-               case MODE_SENSE:
-                       if (us->srb->use_sg == 0 && length > 0) {
-                               int i;
-                               printk(KERN_DEBUG "Data is");
-                               for (i = 0; i < 32 && i < length; ++i)
-                                       printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);
-                               if (i < length)
-                                       printk(" ...");
-                               printk("\n");
-                       }
-
-                       /* FIXME: is this really necessary? */
-                       us->srb->cmnd[4] = saveallocation;
-                       break;
-      
-               case LOG_SENSE:
-               case MODE_SENSE_10:
-                       /* FIXME: is this really necessary? */
-                       us->srb->cmnd[7] = saveallocation >> 8;
-                       us->srb->cmnd[8] = saveallocation;
-                       break;
-               } /* end switch on cmnd[0] */
-       } /* if good command */
-}
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-static int CBI_irq(int state, void *buffer, int len, void *dev_id)
-{
-       struct us_data *us = (struct us_data *)dev_id;
-
-       US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no);
-
-       /* save the data for interpretation later */
-       if (state != USB_ST_REMOVED) {
-               us->ip_data = le16_to_cpup((__u16 *)buffer);
-               US_DEBUGP("Interrupt Status 0x%x\n", us->ip_data);
-       }
-  
-       /* was this a wanted interrupt? */
-       if (us->ip_wanted) {
-               us->ip_wanted = 0;
-               wake_up(&us->ip_waitq);
-       } else {
-               US_DEBUGP("ERROR: Unwanted interrupt received!\n");
-       }
-
-       /* This return code is truly meaningless -- and I mean truly.  It gets
-        * ignored by other layers.  It used to indicate if we wanted to get
-        * another interrupt or disable the interrupt callback
-        */
-       return 0;
-}
-
-/* FIXME: this reset function doesn't really reset the port, and it
- * should. Actually it should probably do what it's doing here, and
- * reset the port physically
- */
-static int CB_reset(struct us_data *us)
-{
-       unsigned char cmd[12];
-       int result;
-
-       US_DEBUGP("CB_reset\n");
-
-       memset(cmd, 0xFF, sizeof(cmd));
-       cmd[0] = SEND_DIAGNOSTIC;
-       cmd[1] = 4;
-       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                                0, us->ifnum, cmd, sizeof(cmd), HZ*5);
-
-       /* long wait for reset */
-       schedule_timeout(HZ*6);
-
-       US_DEBUGP("CB_reset: clearing endpoint halt\n");
-       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
-       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
-
-       US_DEBUGP("CB_reset done\n");
-       return 0;
-}
-
-static int pop_CB_status(Scsi_Cmnd *srb);
-
-/* FIXME: we also need a CBI_command which sets up the completion
- * interrupt, and waits for it
- */
-static int CB_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
-       int result;
-
-       US_DEBUGP("CBI gets a command:\n");
-       US_DEBUG(us_show_command(srb));
-
-       /* FIXME: we aren't setting the ip_wanted indicator early enough, which
-        * causes some commands to never complete.  This hangs the driver.
-        */
-
-       /* let's send the command via the control pipe */
-       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                                0, us->ifnum,
-                                srb->cmnd, srb->cmd_len, HZ*5);
-
-       /* check the return code for the command */
-       if (result < 0) {
-               US_DEBUGP("Call to usb_control_msg() returned %d\n", result);
-
-               /* a stall is a fatal condition from the device */
-               if (result == -EPIPE) {
-                       US_DEBUGP("-- Stall on control pipe detected. Clearing\n");
-      
-                       US_DEBUGP("-- Return from usb_clear_halt() is %d\n",
-                                 usb_clear_halt(us->pusb_dev, 
-                                                usb_sndctrlpipe(us->pusb_dev, 0)));
-                       return USB_STOR_TRANSPORT_ERROR;
-               }
-
-               /* FIXME: we need to handle NAKs here */
-               return USB_STOR_TRANSPORT_ERROR;
-       }
-
-       /* transfer the data payload for this command, if one exists*/
-       if (us_transfer_length(srb)) {
-               result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
-               US_DEBUGP("CBI attempted to transfer data, result is 0x%x\n", result);
-
-               /* FIXME: what do the return codes from us_transfer mean? */
-               if ((result < 0) && 
-                   (result != USB_ST_DATAUNDERRUN) && 
-                   (result != USB_ST_STALL)) {
-                       return DID_ERROR << 16;
-               }
-       } /* if (us_transfer_length(srb)) */
-
-       /* get status and return it */
-       return pop_CB_status(srb);
-}
-
-/*
- * Control/Bulk status handler
- */
-
-static int pop_CB_status(Scsi_Cmnd *srb)
-{
-       struct us_data *us = (struct us_data *)srb->host_scribble;
-       int result;
-       __u8 status[2];
-       int retry = 5;
-
-       US_DEBUGP("pop_CB_status, proto=0x%x\n", us->protocol);
-       switch (us->protocol) {
-       case US_PR_CB:
-               /* get from control */
-
-               while (retry--) {
-                       result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
-                                                USB_REQ_GET_STATUS, USB_DIR_IN |
-                                                USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-                                                0, us->ifnum, status, sizeof(status), HZ*5);
-                       if (result != USB_ST_TIMEOUT)
-                               break;
-               }
-               if (result) {
-                       US_DEBUGP("Bad AP status request %d\n", result);
-                       return DID_ABORT << 16;
-               }
-               US_DEBUGP("Got AP status 0x%x 0x%x\n", status[0], status[1]);
-               if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY &&
-                   ( (status[0] & ~3) || status[1]))
-                       return (DID_OK << 16) | 2;
-               else
-                       return USB_STOR_TRANSPORT_GOOD;
-               break;
-
-               /* FIXME: this should be in a separate function */
-       case US_PR_CBI:
-               /* get from interrupt pipe */
-
-               /* add interrupt transfer, marked for removal */
-               us->ip_wanted = 1;
-
-               /* go to sleep until we get this interrup */
-               /* FIXME: this should be changed to use a timeout */
-               sleep_on(&us->ip_waitq);
-    
-               if (us->ip_wanted) {
-                       US_DEBUGP("Did not get interrupt on CBI\n");
-                       us->ip_wanted = 0;
-                       return USB_STOR_TRANSPORT_ERROR;
-               }
-    
-               US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data);
-
-               /* UFI gives us ASC and ASCQ, like a request sense */
-               /* FIXME: is this right?  do REQUEST_SENSE and INQUIRY need special
-                * case handling?
-                */
-               if (us->subclass == US_SC_UFI) {
-                       if (srb->cmnd[0] == REQUEST_SENSE ||
-                           srb->cmnd[0] == INQUIRY)
-                               return USB_STOR_TRANSPORT_GOOD;
-                       else
-                               if (us->ip_data)
-                                       return USB_STOR_TRANSPORT_FAILED;
-                               else
-                                       return USB_STOR_TRANSPORT_GOOD;
-               }
-
-               /* otherwise, we interpret the data normally */
-               switch (us->ip_data) {
-               case 0x0001: 
-                       return USB_STOR_TRANSPORT_GOOD;
-               case 0x0002: 
-                       return USB_STOR_TRANSPORT_FAILED;
-               default: 
-                       return USB_STOR_TRANSPORT_ERROR;
-               }
-       }
-       US_DEBUGP("pop_CB_status, reached end of function\n");
-       return USB_STOR_TRANSPORT_ERROR;
-}
-
-static int Bulk_reset(struct us_data *us)
-{
-       int result;
-
-       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-                                US_BULK_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                                US_BULK_RESET_HARD, us->ifnum,
-                                NULL, 0, HZ*5);
-       if (result)
-               US_DEBUGP("Bulk hard reset failed %d\n", result);
-       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
-       usb_clear_halt(us->pusb_dev, usb_sndbulkpipe(us->pusb_dev, us->ep_out));
-
-       /* long wait for reset */
-       schedule_timeout(HZ*6);
-
-       return result;
-}
-
-/*
- * The bulk only protocol handler.
- *     Uses the in and out endpoints to transfer commands and data
- */
-static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
-       struct bulk_cb_wrap bcb;
-       struct bulk_cs_wrap bcs;
-       int result;
-       int pipe;
-       int partial;
-
-       /* set up the command wrapper */
-       bcb.Signature = US_BULK_CB_SIGN;
-       bcb.DataTransferLength = us_transfer_length(srb);
-       bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
-       bcb.Tag = srb->serial_number;
-       bcb.Lun = 0;
-       bcb.Length = srb->cmd_len;
-
-       /* construct the pipe handle */
-       pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
-       /* copy the command payload */
-       memset(bcb.CDB, 0, sizeof(bcb.CDB));
-       memcpy(bcb.CDB, srb->cmnd, bcb.Length);
-
-       /* send it to out endpoint */
-       US_DEBUGP("Bulk command S 0x%x T 0x%x L %d F %d CL %d\n",
-                 bcb.Signature, bcb.Tag, bcb.DataTransferLength,
-                 bcb.Flags, bcb.Length);
-       result = usb_bulk_msg(us->pusb_dev, pipe, &bcb,
-                             US_BULK_CB_WRAP_LEN, &partial, HZ*5);
-       US_DEBUGP("Bulk command transfer result=%d\n", result);
-
-       /* if we stall, we need to clear it before we go on */
-       if (result == -EPIPE) {
-               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-               usb_clear_halt(us->pusb_dev, pipe);
-       }
-  
-       /* if the command transfered well, then we go to the data stage */
-       /* FIXME: Regardless of the status of the data stage, we go on to the
-        * status stage.  Note that this implies that if a command is
-        * partially successful, we rely on the device reporting an error
-        * the CSW. The spec says that the device may just decide to short us.
-        */
-       if (result == 0) {
-               /* send/receive data payload, if there is any */
-               if (bcb.DataTransferLength) {
-                       result = us_transfer(srb, bcb.Flags);
-                       US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-#if 0
-                       if ((result < 0) && (result != USB_ST_DATAUNDERRUN) 
-                           && (result != USB_ST_STALL)) {
-                               US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-                               return DID_ABORT << 16;
-                       }
-#endif
-               }
-       }
-
-       /* See flow chart on pg 15 of the Bulk Only Transport spec for
-        * an explanation of how this code works.
-        */
-
-       /* construct the pipe handle */
-       pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
-       /* get CSW for device status */
-       result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
-                             US_BULK_CS_WRAP_LEN, &partial, HZ*5);
-
-       /* did the attempt to read the CSW fail? */
-       if (result == -EPIPE) {
-               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-               usb_clear_halt(us->pusb_dev, pipe);
-
-               /* get the status again */
-               result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
-                                     US_BULK_CS_WRAP_LEN, &partial, HZ*5);
-   
-               /* if it fails again, we need a reset and return an error*/
-               if (result == -EPIPE) {
-                       Bulk_reset(us);
-                       return (DID_ABORT << 16);
-               }
-       }
-
-       /* if we still have a failure at this point, we're in trouble */
-       if (result) {
-               US_DEBUGP("Bulk status result = 0x%x\n", result);
-               return DID_ABORT << 16;
-       }
-
-       /* check bulk status */
-       US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n",
-                 bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);
-       if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||
-           bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
-               US_DEBUGP("Bulk logical error\n");
-               return DID_ABORT << 16;
-       }
-
-       /* based on the status code, we report good or bad */
-       switch (bcs.Status) {
-       case US_BULK_STAT_OK:
-               /* if there is residue, we really didn't finish the command */
-               if (bcs.Residue)
-                       return DID_ERROR << 16;
-               else
-                       return DID_OK << 16;
-
-       case US_BULK_STAT_FAIL:
-               return DID_ERROR << 16;
-
-       case US_BULK_STAT_PHASE:
-               Bulk_reset(us);
-               return DID_ERROR << 16;
-       }
-
-       return DID_OK << 16;        /* check sense required */
-}
-
-/***********************************************************************
- * Host functions 
- ***********************************************************************/
-
-/* detect adapter (always true ) */
-static int us_detect(struct SHT *sht)
-{
-       /* FIXME - not nice at all, but how else ? */
-       struct us_data *us = (struct us_data *)sht->proc_dir;
-       char name[32];
-
-       /* set up our name */
-       sprintf(name, "usbscsi%d", us->host_number);
-       sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL);
-       if (!sht->proc_name)
-               return 0;
-       strcpy(sht->proc_name, name);
-
-       /* we start with no /proc directory entry */
-       sht->proc_dir = NULL;
-
-       /* register the host */
-       us->host = scsi_register(sht, sizeof(us));
-       if (us->host) {
-               us->host->hostdata[0] = (unsigned long)us;
-               us->host_no = us->host->host_no;
-               return 1;
-       }
-
-       /* odd... didn't register properly.  Abort and free pointers */
-       kfree(sht->proc_name);
-       sht->proc_name = NULL;
-       sht->name = NULL;
-       return 0;
-}
-
-/* release - must be here to stop scsi
- *     from trying to release IRQ etc.
- *     Kill off our data
- */
-static int us_release(struct Scsi_Host *psh)
-{
-       struct us_data *us = (struct us_data *)psh->hostdata[0];
-       struct us_data *prev = (struct us_data *)&us_list;
-
-       if (us->irq_handle) {
-               usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
-               us->irq_handle = NULL;
-       }
-       if (us->pusb_dev)
-               usb_deregister(&storage_driver);
-
-       /* FIXME - leaves hanging host template copy */
-       /* (because scsi layer uses it after removal !!!) */
-       while (prev->next != us)
-               prev = prev->next;
-       prev->next = us->next;
-       return 0;
-}
-
-/* run command */
-static int us_command( Scsi_Cmnd *srb )
-{
-       US_DEBUGP("Bad use of us_command\n");
-
-       return DID_BAD_TARGET << 16;
-}
-
-/* run command */
-static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
-{
-       struct us_data *us = (struct us_data *)srb->host->hostdata[0];
-
-       US_DEBUGP("Command wakeup\n");
-       if (us->srb) {
-               /* busy */
-       }
-       srb->host_scribble = (unsigned char *)us;
-       us->srb = srb;
-       srb->scsi_done = done;
-       us->action = US_ACT_COMMAND;
-
-       /* wake up the process task */
-
-       wake_up_interruptible(&us->waitq);
-
-       return 0;
-}
-
-/* FIXME: This doesn't actually abort anything */
-static int us_abort( Scsi_Cmnd *srb )
-{
-       return 0;
-}
-
-static int us_bus_reset( Scsi_Cmnd *srb )
-{
-       //  struct us_data *us = (struct us_data *)srb->host->hostdata[0];
-
-       US_DEBUGP("Bus reset requested\n");
-       //  us->transport_reset(us);
-       return SUCCESS;
-}
-
-/* FIXME: This doesn't actually reset anything */
-static int us_host_reset( Scsi_Cmnd *srb )
-{
-       return 0;
-}
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) do { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } while (0)
-
-int usb_stor_proc_info (char *buffer, char **start, off_t offset, 
-                       int length, int hostno, int inout)
-{
-       struct us_data *us = us_list;
-       char *pos = buffer;
-       char *tmp_ptr;
-
-       /* find our data from hostno */
-       while (us) {
-               if (us->host_no == hostno)
-                       break;
-               us = us->next;
-       }
-
-       /* if we couldn't find it, we return an error */
-       if (!us)
-               return -ESRCH;
-
-       /* if someone is sending us data, just throw it away */
-       if (inout)
-               return length;
-
-       /* print the controler name */
-       SPRINTF ("Host scsi%d: usb-storage\n", hostno);
-
-       /* print product and vendor strings */
-       tmp_ptr = kmalloc(256, GFP_KERNEL);
-       if (!us->pusb_dev || !tmp_ptr) {
-               SPRINTF("    Vendor: Unknown Vendor\n");
-               SPRINTF("   Product: Unknown Product\n");
-       } else {
-               SPRINTF("    Vendor: ");
-               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer, tmp_ptr, 256) > 0)
-                       SPRINTF("%s\n", tmp_ptr);
-               else
-                       SPRINTF("Unknown Vendor\n");
-    
-               SPRINTF("   Product: ");
-               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0)
-                       SPRINTF("%s\n", tmp_ptr);
-               else
-                       SPRINTF("Unknown Product\n");
-               kfree(tmp_ptr);
-       }
-
-       SPRINTF("  Protocol: ");
-       switch (us->protocol) {
-       case US_PR_CB:
-               SPRINTF("Control/Bulk\n");
-               break;
-    
-       case US_PR_CBI:
-               SPRINTF("Control/Bulk/Interrupt\n");
-               break;
-    
-       case US_PR_BULK:
-               SPRINTF("Bulk only\n");
-               break;
-    
-       default:
-               SPRINTF("Unknown Protocol\n");
-               break;
-       }
-
-       /* show the GUID of the device */
-       SPRINTF("      GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
-
-       /*
-        * Calculate start of next buffer, and return value.
-        */
-       *start = buffer + offset;
-
-       if ((pos - buffer) < offset)
-               return (0);
-       else if ((pos - buffer - offset) < length)
-               return (pos - buffer - offset);
-       else
-               return (length);
-}
-
-/*
- * this defines our 'host'
- */
-
-static Scsi_Host_Template my_host_template = {
-       NULL,                       /* next */
-       NULL,                       /* module */
-       NULL,                       /* proc_dir */
-       usb_stor_proc_info,
-       NULL,                       /* name - points to unique */
-       us_detect,
-       us_release,
-       NULL,                       /* info */
-       NULL,                       /* ioctl */
-       us_command,
-       us_queuecommand,
-       NULL,                       /* eh_strategy */
-       us_abort,
-       us_bus_reset,
-       us_bus_reset,
-       us_host_reset,
-       NULL,                       /* abort */
-       NULL,                       /* reset */
-       NULL,                       /* slave_attach */
-       NULL,                       /* bios_param */
-       NULL,                       /* select_queue_depths */
-       1,                          /* can_queue */
-       -1,                         /* this_id */
-       SG_ALL,             /* sg_tablesize */
-       1,                          /* cmd_per_lun */
-       0,                          /* present */
-       FALSE,              /* unchecked_isa_dma */
-       FALSE,              /* use_clustering */
-       TRUE,                       /* use_new_eh_code */
-       TRUE                        /* emulated */
-};
-
-static unsigned char sense_notready[] = {
-       0x70,                       /* current error */
-       0x00,
-       0x02,                       /* not ready */
-       0x00,
-       0x00,
-       0x0a,                       /* additional length */
-       0x00,
-       0x00,
-       0x00,
-       0x00,
-       0x04,                       /* not ready */
-       0x03,                       /* manual intervention */
-       0x00,
-       0x00,
-       0x00,
-       0x00
-};
-
-static int usb_stor_control_thread(void * __us)
-{
-       struct us_data *us = (struct us_data *)__us;
-       int action;
-
-       lock_kernel();
-
-       /*
-        * This thread doesn't need any user-level access,
-        * so get rid of all our resources..
-        */
-       daemonize();
-
-       sprintf(current->comm, "usbscsi%d", us->host_number);
-
-       unlock_kernel();
-
-       up(us->notify);
-
-       for(;;) {
-               siginfo_t info;
-               int unsigned long signr;
-
-               interruptible_sleep_on(&us->waitq);
-
-               action = us->action;
-               us->action = 0;
-
-               /* FIXME: we need to examine placment of break; and 
-                * scsi_done() calls */
-
-               switch (action) {
-               case US_ACT_COMMAND:
-                       /* bad device */
-                       if (us->srb->target || us->srb->lun) {
-                               US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n",
-                                          us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);
-                               us->srb->result = DID_BAD_TARGET << 16;
-
-                               us->srb->scsi_done(us->srb);
-                               us->srb = NULL;
-                               break;
-                       }
-
-                       /* our device has gone - pretend not ready */
-                       /* FIXME: we also need to handle INQUIRY here, 
-                        * probably */
-                       if (!us->pusb_dev) {
-                               if (us->srb->cmnd[0] == REQUEST_SENSE) {
-                                       memcpy(us->srb->request_buffer, sense_notready, 
-                                              sizeof(sense_notready));
-                                       us->srb->result = DID_OK << 16;
-                               } else {
-                                       us->srb->result = (DID_OK << 16) | 2;
-                               }
-
-                               us->srb->scsi_done(us->srb);
-                               us->srb = NULL;
-                               break;
-                       }
-
-                       /* we've got a command, let's do it! */
-                       US_DEBUG(us_show_command(us->srb));
-
-                       /* FIXME: this is to support Shuttle E-USB bridges, it 
-                        * appears */
-                       if (us->srb->cmnd[0] == START_STOP &&
-                           us->pusb_dev->descriptor.idProduct == 0x0001 &&
-                           us->pusb_dev->descriptor.idVendor == 0x04e6)
-                               us->srb->result = DID_OK << 16;
-                       else {
-                               us->proto_handler(us->srb, us);
-                       }
-      
-                       US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result);
-                       us->srb->scsi_done(us->srb);
-                       us->srb = NULL;
-                       break;
-      
-               case US_ACT_ABORT:
-                       break;
-
-               case US_ACT_DEVICE_RESET:
-                       break;
-
-               case US_ACT_BUS_RESET:
-                       break;
-
-               case US_ACT_HOST_RESET:
-                       break;
-
-               } /* end switch on action */
-    
-               if (signal_pending(current)) {
-                       /* sending SIGUSR1 makes us print out some info */
-                       spin_lock_irq(&current->sigmask_lock);
-                       signr = dequeue_signal(&current->blocked, &info);
-                       spin_unlock_irq(&current->sigmask_lock);
-
-                       if (signr == SIGUSR2) {
-                               usb_stor_debug = !usb_stor_debug;
-                               printk(USB_STORAGE "debug toggle = %d\n", usb_stor_debug);
-                       } else {
-                               break;      /* exit the loop on any other signal */
-                       }
-               }
-       }
-  
-       //  MOD_DEC_USE_COUNT;
-
-       printk("usb_stor_control_thread exiting\n");
-
-       /* FIXME: this is a hack to allow for debugging */
-       // scsi_unregister_module(MODULE_SCSI_HA, us->htmplt);
-
-       return 0;
-}      
-
-/* Probe to see if a new device is actually a SCSI device */
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
-{
-       struct usb_interface_descriptor *interface;
-       int i;
-       char mf[32];                 /* manufacturer */
-       char prod[32];               /* product */
-       char serial[32];             /* serial number */
-       struct us_data *ss = NULL;
-       unsigned int flags = 0;
-       GUID(guid);                  /* Global Unique Identifier */
-       struct us_data *prev;
-       Scsi_Host_Template *htmplt;
-       int protocol = 0;
-       int subclass = 0;
-       struct usb_interface_descriptor *altsetting = 
-               &(dev->actconfig->interface[ifnum].altsetting[0]); 
-
-       /* clear the GUID and fetch the strings */
-       GUID_CLEAR(guid);
-       memset(mf, 0, sizeof(mf));
-       memset(prod, 0, sizeof(prod));
-       memset(serial, 0, sizeof(serial));
-       if (dev->descriptor.iManufacturer)
-               usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf));
-       if (dev->descriptor.iProduct)
-               usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod));
-       if (dev->descriptor.iSerialNumber)
-               usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial));
-       
-       /* let's examine the device now */
-
-       /* We make an exception for the shuttle E-USB */
-       if (dev->descriptor.idVendor == 0x04e6 &&
-           dev->descriptor.idProduct == 0x0001) {
-               protocol = US_PR_CB;
-               subclass = US_SC_8070;      /* an assumption */
-       } else if (dev->descriptor.bDeviceClass != 0 ||
-                  altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
-                  altsetting->bInterfaceSubClass < US_SC_MIN ||
-                  altsetting->bInterfaceSubClass > US_SC_MAX) {
-               /* if it's not a mass storage, we go no further */
-               return NULL;
-       }
-
-       /* At this point, we know we've got a live one */
-       US_DEBUGP("USB Mass Storage device detected\n");
-
-       /* Create a GUID for this device */
-       if (dev->descriptor.iSerialNumber && serial[0]) {
-               /* If we have a serial number, and it's a non-NULL string */
-               make_guid(guid, dev->descriptor.idVendor, 
-                         dev->descriptor.idProduct, serial);
-       } else {
-               /* We don't have a serial number, so we use 0 */
-               make_guid(guid, dev->descriptor.idVendor, 
-                         dev->descriptor.idProduct, "0");
-       }
-
-       /* Now check if we have seen this GUID before, and restore
-        * the flags if we find it
-        */
-       for (ss = us_list; ss != NULL; ss = ss->next) {
-               if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid))    {
-                       US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
-                                 GUID_ARGS(guid));
-                       flags = ss->flags;
-                       break;
-               }
-       }
-
-       /* If ss == NULL, then this is a new device.  Allocate memory for it */
-       if (!ss) {
-               if ((ss = (struct us_data *)kmalloc(sizeof(*ss), 
-                                                   GFP_KERNEL)) == NULL) {
-                       printk(KERN_WARNING USB_STORAGE "Out of memory\n");
-                       return NULL;
-               }
-               memset(ss, 0, sizeof(struct us_data));
-       }
-
-       /* Initialize the us_data structure with some useful info */
-       interface = altsetting;
-       ss->flags = flags;
-       ss->ifnum = ifnum;
-       ss->pusb_dev = dev;
-       ss->attention_done = 0;
-
-       /* If the device has subclass and protocol, then use that.  Otherwise, 
-        * take data from the specific interface.
-        */
-       if (subclass) {
-               ss->subclass = subclass;
-               ss->protocol = protocol;
-       } else {
-               ss->subclass = interface->bInterfaceSubClass;
-               ss->protocol = interface->bInterfaceProtocol;
-       }
-
-       /* set the handler pointers based on the protocol */
-       US_DEBUGP("Transport: ");
-       switch (ss->protocol) {
-       case US_PR_CB:
-               US_DEBUGPX("Control/Bulk\n");
-               ss->transport = CB_transport;
-               ss->transport_reset = CB_reset;
-               break;
-
-       case US_PR_CBI:
-               US_DEBUGPX("Control/Bulk/Interrupt\n");
-               ss->transport = CB_transport;
-               ss->transport_reset = CB_reset;
-               break;
-
-       case US_PR_BULK:
-               US_DEBUGPX("Bulk\n");
-               ss->transport = Bulk_transport;
-               ss->transport_reset = Bulk_reset;
-               break;
-
-       default:
-               US_DEBUGPX("Unknown\n");    
-               kfree(ss);
-               return NULL;
-               break;
-       }
-
-       /*
-        * We are expecting a minimum of 2 endpoints - in and out (bulk).
-        * An optional interrupt is OK (necessary for CBI protocol).
-        * We will ignore any others.
-        */
-       for (i = 0; i < interface->bNumEndpoints; i++) {
-               /* is it an BULK endpoint? */
-               if ((interface->endpoint[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK)
-                   == USB_ENDPOINT_XFER_BULK) {
-                       if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN)
-                               ss->ep_in = interface->endpoint[i].bEndpointAddress &
-                                       USB_ENDPOINT_NUMBER_MASK;
-                       else
-                               ss->ep_out = interface->endpoint[i].bEndpointAddress &
-                                       USB_ENDPOINT_NUMBER_MASK;
-               }
-
-               /* is it an interrupt endpoint? */
-               if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 
-                   == USB_ENDPOINT_XFER_INT) {
-                       ss->ep_int = interface->endpoint[i].bEndpointAddress &
-                               USB_ENDPOINT_NUMBER_MASK;
-               }
-       }
-       US_DEBUGP("Endpoints In %d Out %d Int %d\n",
-                 ss->ep_in, ss->ep_out, ss->ep_int);
-
-       /* Do some basic sanity checks, and bail if we find a problem */
-       if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
-           !ss->ep_in || !ss->ep_out || 
-           (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
-               US_DEBUGP("Problems with device\n");
-               if (ss->host) {
-                       scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);
-                       kfree(ss->htmplt->name);
-                       kfree(ss->htmplt);
-               }
-
-               kfree(ss);
-               return NULL;
-       }
-
-       /* If this is a new device (i.e. we haven't seen it before), we need to
-        * generate a scsi host definition, and register with scsi above us 
-        */
-       if (!ss->host) {
-               /* copy the GUID we created before */
-               US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
-               memcpy(ss->guid, guid, sizeof(guid));
-
-               /* set class specific stuff */
-               US_DEBUGP("Protocol: ");
-               switch (ss->subclass) {
-               case US_SC_RBC:
-                       US_DEBUGPX("Reduced Block Commands\n");
-                       break;
-
-               case US_SC_8020:
-                       US_DEBUGPX("8020\n");
-                       break;
-
-               case US_SC_QIC:
-                       US_DEBUGPX("QIC157\n");
-                       break;
-
-               case US_SC_8070:
-                       US_DEBUGPX("8070\n");
-                       break;
-
-               case US_SC_SCSI:
-                       US_DEBUGPX("Transparent SCSI\n");
-                       ss->proto_handler = transparent_scsi_command;
-                       break;
-
-               case US_SC_UFI:
-                       US_DEBUGPX("UFI\n");
-                       ss->proto_handler = ufi_command;
-                       break;
-
-               default:
-                       US_DEBUGPX("Unknown\n");
-                       break;
-               }
-
-               /* We only handle certain protocols.  Currently, these are
-                *the only ones that devices use.
-                */
-               if ((ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_UFI)) {
-                       US_DEBUGP("Sorry, we do not support that protocol yet.\n");
-                       US_DEBUGP("If you have a device which uses one of the unsupported\n");
-                       US_DEBUGP("protocols, please contact mdharm-usb@one-eyed-alien.net\n");
-     
-                       kfree(ss);
-                       return NULL;
-               }
-
-               /* Allocate memory for the SCSI Host Template */
-               if ((htmplt = (Scsi_Host_Template *)
-                    kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
-
-                       printk(KERN_WARNING USB_STORAGE "Out of memory\n");
-
-                       kfree(ss);
-                       return NULL;
-               }
-
-               /* Initialize the host template based on the default one */
-               memcpy(htmplt, &my_host_template, sizeof(my_host_template));
-
-               /* Grab the next host number */
-               ss->host_number = my_host_number++;
-
-               /* MDD: FIXME: this is bad.  We abuse this pointer so we
-                * can pass the ss pointer to the host controler thread
-                * in us_detect
-                */
-               (struct us_data *)htmplt->proc_dir = ss; 
-
-               /* shuttle E-USB */     
-               if (dev->descriptor.idVendor == 0x04e6 &&
-                   dev->descriptor.idProduct == 0x0001) {
-                       __u8 qstat[2];
-                       int result;
-           
-                       result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
-                                                1, 0xC0,
-                                                0, ss->ifnum,
-                                                qstat, 2, HZ*5);
-                       US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]);
-                       init_waitqueue_head(&ss->ip_waitq);
-                       ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
-                       result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
-                                                255, (void *)ss, &ss->irq_handle);
-                       if (result)
-                               return NULL;
-
-                       interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
-               } else if (ss->protocol == US_PR_CBI)
-               {
-                       int result; 
-
-                       init_waitqueue_head(&ss->ip_waitq);
-
-                       /* set up the IRQ pipe and handler */
-                       /* FIXME: This needs to get the period from the device */
-                       ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
-                       result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
-                                                255, (void *)ss, &ss->irq_handle);
-                       if (result) {
-                               US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",
-                                         result);
-                       }
-               }
-    
-
-               /* start up our thread */
-               {
-                       DECLARE_MUTEX_LOCKED(sem);
-
-                       init_waitqueue_head(&ss->waitq);
-
-                       ss->notify = &sem;
-                       ss->pid = kernel_thread(usb_stor_control_thread, ss,
-                                               CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-                       if (ss->pid < 0) {
-                               printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n");
-                               kfree(htmplt);
-
-                               kfree(ss);
-                               return NULL;
-                       }
-
-                       /* wait for it to start */
-                       down(&sem);
-               }
-
-               /* now register - our detect function will be called */
-               scsi_register_module(MODULE_SCSI_HA, htmplt);
-
-               /* put us in the list */
-               prev = (struct us_data *)&us_list;
-               while (prev->next)
-                       prev = prev->next;
-               prev->next = ss;
-       }
-
-       printk(KERN_INFO "WARNING: USB Mass Storage data integrity not assured\n");
-       printk(KERN_INFO "USB Mass Storage device found at %d\n", dev->devnum);
-
-       return ss;
-}
-
-/* Handle a disconnect event from the USB core */
-static void storage_disconnect(struct usb_device *dev, void *ptr)
-{
-       struct us_data *ss = ptr;
-
-       if (!ss)
-               return;
-
-       ss->pusb_dev = NULL;
-       //  MOD_DEC_USE_COUNT;
-}
-
-
-/***********************************************************************
- * Initialization and registration
- ***********************************************************************/
-
-int __init usb_stor_init(void)
-{
-       //  MOD_INC_USE_COUNT;
-
-       if (sizeof(my_host_template) != SCSI_HOST_TEMPLATE_SIZE) {
-               printk(KERN_ERR "usb-storage: SCSI_HOST_TEMPLATE_SIZE does not match\n") ;
-               printk(KERN_ERR "usb-storage: expected %d bytes, got %d bytes\n", 
-                      SCSI_HOST_TEMPLATE_SIZE, sizeof(my_host_template)) ;
-
-               return -1 ;
-       }
-
-       /* register the driver, return -1 if error */
-       if (usb_register(&storage_driver) < 0)
-               return -1;
-
-       printk(KERN_INFO "USB Mass Storage support registered.\n");
-       return 0;
-}
-
-void __exit usb_stor_exit(void)
-{
-       usb_deregister(&storage_driver) ;
-}
-
-module_init(usb_stor_init) ;
-module_exit(usb_stor_exit) ;
diff --git a/drivers/usb/usb_storage.h b/drivers/usb/usb_storage.h
deleted file mode 100644 (file)
index 80a03f3..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Driver for USB mass storage - include file
- *
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- */
-
-#include <linux/config.h>
-
-#define USB_STORAGE "usb-storage: "
-
-extern int usb_stor_debug;
-
-#ifdef CONFIG_USB_STORAGE_DEBUG
-void us_show_command(Scsi_Cmnd *srb);
-#define US_DEBUGP(x...) { if(usb_stor_debug) printk( KERN_DEBUG USB_STORAGE ## x ); }
-#define US_DEBUGPX(x...) { if(usb_stor_debug) printk( ## x ); }
-#define US_DEBUG(x)  { if(usb_stor_debug) x; }
-#else
-#define US_DEBUGP(x...)
-#define US_DEBUGPX(x...)
-#define US_DEBUG(x)
-#endif
-
-/* bit set if input */
-extern unsigned char us_direction[256/8];
-#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
-
-/* Sub Classes */
-
-#define US_SC_RBC      1               /* Typically, flash devices */
-#define US_SC_8020     2               /* CD-ROM */
-#define US_SC_QIC      3               /* QIC-157 Tapes */
-#define US_SC_UFI      4               /* Floppy */
-#define US_SC_8070     5               /* Removable media */
-#define US_SC_SCSI     6               /* Transparent */
-#define US_SC_MIN      US_SC_RBC
-#define US_SC_MAX      US_SC_SCSI
-
-/* Protocols */
-
-#define US_PR_CB       1               /* Control/Bulk w/o interrupt */
-#define US_PR_CBI      0               /* Control/Bulk/Interrupt */
-#define US_PR_BULK     0x50            /* bulk only */
-
-/*
- * Bulk only data structures (Zip 100, for example)
- */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
-       __u32   Signature;              /* contains 'USBC' */
-       __u32   Tag;                    /* unique per command id */
-       __u32   DataTransferLength;     /* size of data */
-       __u8    Flags;                  /* direction in bit 0 */
-       __u8    Lun;                    /* LUN normally 0 */
-       __u8    Length;                 /* of of the CDB */
-       __u8    CDB[16];                /* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN    31
-#define US_BULK_CB_SIGN                0x43425355
-#define US_BULK_FLAG_IN                1
-#define US_BULK_FLAG_OUT       0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
-       __u32   Signature;              /* should = 'USBS' */
-       __u32   Tag;                    /* same as original command */
-       __u32   Residue;                /* amount not transferred */
-       __u8    Status;                 /* see below */
-       __u8    Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN    13
-#define US_BULK_CS_SIGN                0x53425355
-#define US_BULK_STAT_OK                0
-#define US_BULK_STAT_FAIL      1
-#define US_BULK_STAT_PHASE     2
-
-#define US_BULK_RESET          0xff
-#define US_BULK_RESET_SOFT     1
-#define US_BULK_RESET_HARD     0
-
-/*
- * Transport return codes
- */
-
-#define USB_STOR_TRANSPORT_GOOD    0    /* Transport good, command good    */
-#define USB_STOR_TRANSPORT_FAILED  1    /* Transport good, command failed  */
-#define USB_STOR_TRANSPORT_ERROR   2    /* Transport bad (i.e. device dead */
-
-/*
- * CBI style
- */
-
-#define US_CBI_ADSC            0
-
-/* 
- * GUID definitions
- */
-
-#define GUID(x) __u32 x[3]
-#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2])
-#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0;
-#define GUID_NONE(x) (!x[0] && !x[1] && !x[2])
-#define GUID_FORMAT "%08x%08x%08x"
-#define GUID_ARGS(x) x[0], x[1], x[2]
-
-static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial)
-{
-       pg[0] = (vendor << 16) | product;
-       pg[1] = pg[2] = 0;
-       while (*serial) {
-               pg[1] <<= 4;
-               pg[1] |= pg[2] >> 28;
-               pg[2] <<= 4;
-               if (*serial >= 'a')
-                       *serial -= 'a' - 'A';
-               pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0'
-                       : *serial - 'A' + 10;
-               serial++;
-       }
-}
-
-/* Flag definitions */
-#define US_FL_IP_STATUS              0x00000001         /* status uses interrupt */
-#define US_FL_FIXED_COMMAND   0x00000002 /* expand commands to fixed size */
-#define US_FL_MODE_XLATE      0x00000004 /* translate _6 to _10 comands for
-                                           Win/MacOS compatibility */
diff --git a/drivers/usb/usb_storage_debug.c b/drivers/usb/usb_storage_debug.c
deleted file mode 100644 (file)
index cff8f9a..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-
-/* Driver for USB mass storage (scsi-like) devices
- * 
- * (C) Michael Gee (michael@linuxspecific.com) 1999
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/malloc.h>
-#include <linux/spinlock.h>
-
-#include <linux/blk.h>
-#include "../scsi/scsi.h"
-#include "../scsi/hosts.h"
-#include "../scsi/sd.h"
-
-#include "usb.h"
-#include "usb_storage.h"
-
-void us_show_command(Scsi_Cmnd *srb)
-{
-       char *what = NULL;
-
-       switch (srb->cmnd[0]) {
-       case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
-       case REZERO_UNIT: what = "REZERO_UNIT"; break;
-       case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
-       case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
-       case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
-       case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
-       case READ_6: what = "READ_6"; break;
-       case WRITE_6: what = "WRITE_6"; break;
-       case SEEK_6: what = "SEEK_6"; break;
-       case READ_REVERSE: what = "READ_REVERSE"; break;
-       case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
-       case SPACE: what = "SPACE"; break;
-       case INQUIRY: what = "INQUIRY"; break;
-       case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
-       case MODE_SELECT: what = "MODE_SELECT"; break;
-       case RESERVE: what = "RESERVE"; break;
-       case RELEASE: what = "RELEASE"; break;
-       case COPY: what = "COPY"; break;
-       case ERASE: what = "ERASE"; break;
-       case MODE_SENSE: what = "MODE_SENSE"; break;
-       case START_STOP: what = "START_STOP"; break;
-       case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
-       case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
-       case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
-       case SET_WINDOW: what = "SET_WINDOW"; break;
-       case READ_CAPACITY: what = "READ_CAPACITY"; break;
-       case READ_10: what = "READ_10"; break;
-       case WRITE_10: what = "WRITE_10"; break;
-       case SEEK_10: what = "SEEK_10"; break;
-       case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
-       case VERIFY: what = "VERIFY"; break;
-       case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
-       case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
-       case SEARCH_LOW: what = "SEARCH_LOW"; break;
-       case SET_LIMITS: what = "SET_LIMITS"; break;
-       case READ_POSITION: what = "READ_POSITION"; break;
-       case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
-       case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
-       case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
-       case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
-       case COMPARE: what = "COMPARE"; break;
-       case COPY_VERIFY: what = "COPY_VERIFY"; break;
-       case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
-       case READ_BUFFER: what = "READ_BUFFER"; break;
-       case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
-       case READ_LONG: what = "READ_LONG"; break;
-       case WRITE_LONG: what = "WRITE_LONG"; break;
-       case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
-       case WRITE_SAME: what = "WRITE_SAME"; break;
-       case READ_TOC: what = "READ_TOC"; break;
-       case LOG_SELECT: what = "LOG_SELECT"; break;
-       case LOG_SENSE: what = "LOG_SENSE"; break;
-       case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
-       case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
-       case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
-       case READ_12: what = "READ_12"; break;
-       case WRITE_12: what = "WRITE_12"; break;
-       case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
-       case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
-       case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
-       case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
-       case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
-       case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
-       case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
-       default: break;
-       }
-       printk(KERN_DEBUG USB_STORAGE
-              "Command %s (%d bytes)\n", what, srb->cmd_len);
-       printk(KERN_DEBUG USB_STORAGE 
-              "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-              srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], 
-              srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
-}
index beb94ca2fb66e077d72b3d47884b040e660ec38d..eb4a5f78a2ca454fe1825ce3c5ff15187630968f 100644 (file)
@@ -1,8 +1,8 @@
 #
-# Filesystem configuration
+# File system configuration
 #
 mainmenu_option next_comment
-comment 'Filesystems'
+comment 'File systems'
 
 bool 'Quota support' CONFIG_QUOTA
 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
@@ -36,46 +36,46 @@ fi
 
 tristate 'Minix fs support' CONFIG_MINIX_FS
 
-tristate 'NTFS filesystem support (read only)' CONFIG_NTFS_FS
+tristate 'NTFS file system support (read only)' CONFIG_NTFS_FS
 if [ "$CONFIG_NTFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  NTFS write support (DANGEROUS)' CONFIG_NTFS_RW
 fi
 
-tristate 'OS/2 HPFS filesystem support' CONFIG_HPFS_FS
+tristate 'OS/2 HPFS file system support' CONFIG_HPFS_FS
 
-bool '/proc filesystem support' CONFIG_PROC_FS
+bool '/proc file system support' CONFIG_PROC_FS
 
-dep_bool '/dev filesystem support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL
+dep_bool '/dev file system support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL
 dep_bool '  Debug devfs' CONFIG_DEVFS_DEBUG $CONFIG_DEVFS_FS
 
 # It compiles as a module for testing only.  It should not be used
 # as a module in general.  If we make this "tristate", a bunch of people
 # who don't know what they are doing turn it on and complain when it
 # breaks.
-dep_bool '/dev/pts filesystem for Unix98 PTYs' CONFIG_DEVPTS_FS $CONFIG_UNIX98_PTYS
+dep_bool '/dev/pts file system for Unix98 PTYs' CONFIG_DEVPTS_FS $CONFIG_UNIX98_PTYS
 
-dep_tristate 'QNX4 filesystem support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
+dep_tristate 'QNX4 file system support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
 if [ "$CONFIG_QNX4FS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  QNX4FS write support (DANGEROUS)' CONFIG_QNX4FS_RW
 fi
 
-tristate 'ROM filesystem support' CONFIG_ROMFS_FS
+tristate 'ROM file system support' CONFIG_ROMFS_FS
 
 tristate 'Second extended fs support' CONFIG_EXT2_FS
 
-tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
+tristate 'System V and Coherent file system support (read only)' CONFIG_SYSV_FS
 if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
+   bool '  SYSV file system write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
 fi
 
-tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS
+tristate 'UDF file system support (read only)' CONFIG_UDF_FS
 if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW
 fi
 
-tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
+tristate 'UFS file system support (read only)' CONFIG_UFS_FS
 if [ "$CONFIG_UFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool '  UFS filesystem write support (DANGEROUS)' CONFIG_UFS_FS_WRITE
+   bool '  UFS file system write support (DANGEROUS)' CONFIG_UFS_FS_WRITE
 fi
 
 if [ "$CONFIG_NET" = "y" ]; then
@@ -109,7 +109,7 @@ if [ "$CONFIG_INET" = "y" ]; then
    if [ "$CONFIG_NFSD_V3" = "y" ]; then
      define_bool CONFIG_LOCKD_V4 y
    fi
-   tristate 'SMB file system support (to mount WfW shares etc.)' CONFIG_SMB_FS
+   tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS
 fi
 if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
    tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS
index 50e9e98a94af7180679e8f9720b2ed636c46a26f..be8695e2bf0458d2791786a7e742e0380c9cc566 100644 (file)
@@ -47,7 +47,7 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
        i_name = cp;
        i_arg = 0;
        for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
-               /* nothing */
+               /* nothing */ ;
        while ((*cp == ' ') || (*cp == '\t'))
                *cp++ = '\0';
        if (*cp)
index ab7ac0a96719caf3f382bd39d14c9448af183c0f..a520ab40fe17e060b7bdd4b5c640384c66353db1 100644 (file)
@@ -35,7 +35,9 @@ static int ext2_update_inode(struct inode * inode, int do_sync);
  */
 void ext2_put_inode (struct inode * inode)
 {
+       lock_kernel();
        ext2_discard_prealloc (inode);
+       unlock_kernel();
 }
 
 /*
@@ -43,6 +45,8 @@ void ext2_put_inode (struct inode * inode)
  */
 void ext2_delete_inode (struct inode * inode)
 {
+       lock_kernel();
+
        if (is_bad_inode(inode) ||
            inode->i_ino == EXT2_ACL_IDX_INO ||
            inode->i_ino == EXT2_ACL_DATA_INO)
@@ -54,6 +58,8 @@ void ext2_delete_inode (struct inode * inode)
        if (inode->i_blocks)
                ext2_truncate (inode);
        ext2_free_inode (inode);
+
+       unlock_kernel();
 }
 
 #define inode_bmap(inode, nr) (le32_to_cpu((inode)->u.ext2_i.i_data[(nr)]))
@@ -893,7 +899,9 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
 
 void ext2_write_inode (struct inode * inode)
 {
+       lock_kernel();
        ext2_update_inode (inode, 0);
+       unlock_kernel();
 }
 
 int ext2_sync_inode (struct inode *inode)
index ee65ef82f254886dc9a82c400ec67dee57df6b94..b7fecce66034d08885bba59195bf819818999d7a 100644 (file)
@@ -159,8 +159,10 @@ static inline void write_inode(struct inode *inode)
 static inline void sync_one(struct inode *inode)
 {
        if (inode->i_state & I_LOCK) {
+               __iget(inode);
                spin_unlock(&inode_lock);
                __wait_on_inode(inode);
+               iput(inode);
                spin_lock(&inode_lock);
        } else {
                list_del(&inode->i_list);
@@ -253,6 +255,8 @@ void clear_inode(struct inode *inode)
                BUG();
        if (!(inode->i_state & I_FREEING))
                BUG();
+       if (inode->i_state & I_CLEAR)
+               BUG();
        wait_on_inode(inode);
        if (IS_QUOTAINIT(inode))
                DQUOT_DROP(inode);
@@ -262,7 +266,7 @@ void clear_inode(struct inode *inode)
                bdput(inode->i_bdev);
                inode->i_bdev = NULL;
        }
-       inode->i_state = 0;
+       inode->i_state = I_CLEAR;
 }
 
 /*
@@ -377,6 +381,8 @@ void prune_icache(int goal)
 
                entry = entry->prev;
                inode = INODE(tmp);
+               if (inode->i_state & (I_FREEING|I_CLEAR))
+                       BUG();
                if (!CAN_UNUSE(inode))
                        continue;
                if (inode->i_count)
@@ -603,6 +609,11 @@ struct inode *igrab(struct inode *inode)
        if (!(inode->i_state & I_FREEING))
                __iget(inode);
        else
+               /*
+                * Handle the case where s_op->clear_inode is not been
+                * called yet, and somebody is calling igrab
+                * while the inode is getting freed.
+                */
                inode = NULL;
        spin_unlock(&inode_lock);
        if (inode)
@@ -669,32 +680,39 @@ void iput(struct inode *inode)
                                list_del(&inode->i_list);
                                INIT_LIST_HEAD(&inode->i_list);
                                inode->i_state|=I_FREEING;
+                               spin_unlock(&inode_lock);
+
+                               destroy = 1;
                                if (op && op->delete_inode) {
                                        void (*delete)(struct inode *) = op->delete_inode;
-                                       spin_unlock(&inode_lock);
                                        if (inode->i_data.nrpages)
                                                truncate_inode_pages(&inode->i_data, 0);
+                                       /* s_op->delete_inode internally recalls clear_inode() */
                                        delete(inode);
-                                       spin_lock(&inode_lock);
-                               }
-                       }
-                       if (list_empty(&inode->i_hash)) {
-                               list_del(&inode->i_list);
-                               INIT_LIST_HEAD(&inode->i_list);
-                               inode->i_state|=I_FREEING;
-                               spin_unlock(&inode_lock);
-                               clear_inode(inode);
-                               destroy = 1;
+                               } else
+                                       clear_inode(inode);
+                               if (inode->i_state != I_CLEAR)
+                                       BUG();
+
                                spin_lock(&inode_lock);
-                       }
-                       else
-                       {
-                               if (!(inode->i_state & I_DIRTY)) {
+                       } else {
+                               if (!list_empty(&inode->i_hash)) {
+                                       if (!(inode->i_state & I_DIRTY)) {
+                                               list_del(&inode->i_list);
+                                               list_add(&inode->i_list,
+                                                        &inode_unused);
+                                       }
+                                       inodes_stat.nr_unused++;
+                               } else {
+                                       /* magic nfs path */
                                        list_del(&inode->i_list);
-                                       list_add(&inode->i_list,
-                                                &inode_unused);
+                                       INIT_LIST_HEAD(&inode->i_list);
+                                       inode->i_state|=I_FREEING;
+                                       spin_unlock(&inode_lock);
+                                       clear_inode(inode);
+                                       destroy = 1;
+                                       spin_lock(&inode_lock);
                                }
-                               inodes_stat.nr_unused++;
                        }
 #ifdef INODE_PARANOIA
 if (inode->i_flock)
index 4160bf2e32b5537eec9f381fad435268c567f1ba..517456326048f613e68401b05b3f058041cb972f 100644 (file)
@@ -69,7 +69,7 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
        call->a_args.lock    = *lock;
        call->a_args.lock.caller = system_utsname.nodename;
 
-       init_waitqueue_head(&lock->fl.fl_wait);
+       init_waitqueue_head(&call->a_args.lock.fl.fl_wait);
        /* set default data area */
        call->a_args.lock.oh.data = call->a_owner;
 
index bd02a11d539ccdedbee7a68f5384045c98e7e30c..c0797a16faa8f5e70b138e2a85c87c181bd67b89 100644 (file)
@@ -596,11 +596,18 @@ static struct rpc_version nlm_version3 = {
        3, 24, nlm_procedures,
 };
 
+#ifdef         CONFIG_LOCKD_V4
+extern struct rpc_version nlm_version4;
+#endif
+
 static struct rpc_version *    nlm_versions[] = {
        NULL,
        &nlm_version1,
        NULL,
        &nlm_version3,
+#ifdef         CONFIG_LOCKD_V4
+       &nlm_version4,
+#endif
 };
 
 static struct rpc_stat         nlm_stats;
index e33fe9787799d19550e12e32aeedc040df4cb5a0..9620870ad2fe8e1c23d1ae383488a22d76631ba8 100644 (file)
@@ -35,9 +35,13 @@ static int minix_remount (struct super_block * sb, int * flags, char * data);
 
 static void minix_delete_inode(struct inode *inode)
 {
+       lock_kernel();
+
        inode->i_size = 0;
        minix_truncate(inode);
        minix_free_inode(inode);
+
+       unlock_kernel();
 }
 
 static void minix_commit_super(struct super_block * sb)
@@ -1243,7 +1247,9 @@ static void minix_write_inode(struct inode * inode)
 {
        struct buffer_head *bh;
 
+       lock_kernel();
        bh = minix_update_inode(inode);
+       unlock_kernel();
        brelse(bh);
 }
 
index 33a4293c4ab4efd18757f149620e893379272d07..3f36db262086d41dafa903f9b90ce5b5149ed981 100644 (file)
@@ -203,7 +203,8 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size,
                                }
                                n = 0;
                                timeout = init_timeout;
-                               init_timeout <<= 1;
+                               if (init_timeout < max_timeout)
+                                       init_timeout <<= 1;
                                if (!major_timeout_seen) {
                                        printk(KERN_WARNING "NCP server not responding\n");
                                }
index 84e166610a3653412c0a99ca24a4961ce1e32863..16b3624c1862463f45c520c138acc8eaef6baa9b 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sunrpc/stats.h>
 #include <linux/nfs_fs.h>
 #include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -102,6 +103,7 @@ nfs_delete_inode(struct inode * inode)
 
        dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
+       lock_kernel();
        if (S_ISDIR(inode->i_mode)) {
                nfs_free_dircache(inode);
        } else {
@@ -129,6 +131,8 @@ printk("nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
        if (failed)
                printk("NFS: inode %ld had %d failed requests\n",
                        inode->i_ino, failed);
+       unlock_kernel();
+
        clear_inode(inode);
 }
 
index f7b441ab1c0b49f1eab9a7b8f97b5e0306b6b545..63c8fec9344bf0b42364eb82555e7845d87e7a49 100644 (file)
@@ -150,7 +150,7 @@ static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32
         */
        for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
                result = list_entry(lp,struct dentry, d_alias);
-               if (! IS_ROOT(result) || inode->i_sb->s_root == result) {
+               if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
                        dget(result);
                        iput(inode);
                        return result;
@@ -161,6 +161,7 @@ static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32
                iput(inode);
                return ERR_PTR(-ENOMEM);
        }
+       result->d_flags |= DCACHE_NFSD_DISCONNECTED;
        d_rehash(result); /* so a dput won't loose it */
        return result;
 }
@@ -175,6 +176,8 @@ int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
 #ifdef NFSD_PARANOIA
        if (!IS_ROOT(target))
                printk("nfsd: d_splice with no-root target: %s/%s\n", parent->d_name.name, name->name);
+       if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
+               printk("nfsd: d_splice with non-DISCONNECTED target: %s/%s\n", parent->d_name.name, name->name);
 #endif
        name->hash = full_name_hash(name->name, name->len);
        tdentry = d_alloc(parent, name);
@@ -189,6 +192,29 @@ int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
        tdentry->d_parent = tdentry;
        d_rehash(target);
        dput(tdentry);
+
+       /* if parent is properly connected, then we can assert that
+        * the children are connected, but it must be a singluar (non-forking)
+        * branch
+        */
+       if (!(parent->d_flags & DCACHE_NFSD_DISCONNECTED)) {
+               while (target) {
+                       target->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+                       parent = target;
+                       if (list_empty(&parent->d_subdirs))
+                               target = NULL;
+                       else {
+                               target = list_entry(parent->d_subdirs.next, struct dentry, d_child);
+#ifdef NFSD_PARANOIA
+                               /* must be only child */
+                               if (target->d_child.next != &parent->d_subdirs
+                                   || target->d_child.prev != &parent->d_subdirs)
+                                       printk("nfsd: d_splice found non-singular disconnected branch: %s/%s\n",
+                                              parent->d_name.name, target->d_name.name);
+#endif
+                       }
+               }
+       }
        return 0;
 }
 
@@ -227,7 +253,10 @@ struct dentry *nfsd_findparent(struct dentry *child)
                }
                if (pdentry == NULL) {
                        pdentry = d_alloc_root(igrab(tdentry->d_inode));
-                       if (pdentry) d_rehash(pdentry);
+                       if (pdentry) {
+                               pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
+                               d_rehash(pdentry);
+                       }
                }
                if (pdentry == NULL)
                        pdentry = ERR_PTR(-ENOMEM);
@@ -302,13 +331,13 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
        struct dentry *tmp;
        int  found =0;
        int err;
-       /* This semaphore is needed to make sure that only one unconnected (free)
+       /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free)
         * dcache path ever exists, as otherwise two partial paths might get
         * joined together, which would be very confusing.
         * If there is ever an unconnected non-root directory, then this lock
-        * must be held.  This could sensibly be per-filesystem.
+        * must be held.
         */
-       static DECLARE_MUTEX(free_path_sem);
+
 
        nfsdstats.fh_lookup++;
        /*
@@ -324,7 +353,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
                dprintk("find_fh_dentry: No inode found.\n");
                goto err_out;
        }
-       if (!IS_ROOT(result) || result->d_inode->i_sb->s_root ==result)
+       if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED))
                return result;
 
        /* result is now an anonymous dentry, which may be adequate as it stands, or else
@@ -339,7 +368,15 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
         * location in the tree.
         */
        dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
-       down(&free_path_sem);
+       down(&sb->s_nfsd_free_path_sem);
+
+       /* claiming the semaphore might have allow things to get fixed up */
+       if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
+               up(&sb->s_nfsd_free_path_sem);
+               return result;
+       }
+
+
        found = 0;
        if (!S_ISDIR(result->d_inode->i_mode)) {
                nfsdstats.fh_nocache_nondir++;
@@ -356,7 +393,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
                            || !S_ISDIR(dentry->d_inode->i_mode)) {
                                goto err_dentry;
                        }
-                       if (!IS_ROOT(dentry) || dentry->d_inode->i_sb->s_root ==dentry)
+                       if ((!dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
                                found = 1;
                        tmp = splice(result, dentry);
                        err = PTR_ERR(tmp);
@@ -393,10 +430,8 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
                        dput(pdentry);
                        goto err_dentry;
                }
-               /* I'm not sure that this is the best test for
-                *  "is it not a floating dentry?"
-                */
-               if (!IS_ROOT(pdentry) || parent->i_sb->s_root == pdentry)
+
+               if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
                        found = 1;
 
                tmp = splice(dentry, pdentry);
@@ -419,21 +454,21 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
                        dput(tmp);
                        dput(dentry);
                        dput(result);   /* this will discard the whole free path, so we can up the semaphore */
-                       up(&free_path_sem);
+                       up(&sb->s_nfsd_free_path_sem);
                        goto retry;
                }
                dput(dentry);
                dentry = pdentry;
        }
        dput(dentry);
-       up(&free_path_sem);
+       up(&sb->s_nfsd_free_path_sem);
        return result;
 
 err_dentry:
        dput(dentry);
 err_result:
        dput(result);
-       up(&free_path_sem);
+       up(&sb->s_nfsd_free_path_sem);
 err_out:
        if (err == -ESTALE)
                nfsdstats.fh_stale++;
@@ -515,6 +550,13 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                        error = nfserrno(-PTR_ERR(dentry));
                        goto out;
                }
+#ifdef NFSD_PARANOIA
+               if (S_ISDIR(dentry->d_inode->i_mode) &&
+                   (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
+                       printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+                              dentry->d_parent->d_name.name, dentry->d_name.name);
+               }
+#endif
 
                fhp->fh_dentry = dentry;
                fhp->fh_export = exp;
index 607a7d7e9920d0acd294fb765e3b4fbc4a8522d2..ffe846e5c75345aacf1dbd7983e839f3702b4770 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/limits.h>
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/smp_lock.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -34,6 +35,7 @@ struct proc_dir_entry * de_get(struct proc_dir_entry *de)
 void de_put(struct proc_dir_entry *de)
 {
        if (de) {
+               lock_kernel(); /* FIXME: count should be atomic_t */
                if (!de->count) {
                        printk("de_put: entry %s already free!\n", de->name);
                        return;
@@ -46,6 +48,7 @@ void de_put(struct proc_dir_entry *de)
                                free_proc_entry(de);
                        }
                }
+               unlock_kernel();
        }
 }
 
@@ -66,6 +69,8 @@ static void proc_delete_inode(struct inode *inode)
 {
        struct proc_dir_entry *de = inode->u.generic_ip;
 
+       inode->i_state = I_CLEAR;
+
        if (PROC_INODE_PROPER(inode)) {
                proc_pid_delete_inode(inode);
                return;
index 8f9d6ddac44e18ae6724281ee3809abcb80c3615..344ef8f6fdef41c9f491c59bce032400981d55db 100644 (file)
@@ -565,6 +565,7 @@ static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
        s->s_flags = flags;
        s->s_dirt = 0;
        sema_init(&s->s_vfs_rename_sem,1);
+       sema_init(&s->s_nfsd_free_path_sem,1);
        /* N.B. Should lock superblock now ... */
        if (!type->read_super(s, data, silent))
                goto out_fail;
@@ -1142,6 +1143,7 @@ void __init mount_root(void)
                        sb->s_bdev = NULL;
                        sb->s_flags = root_mountflags;
                        sema_init(&sb->s_vfs_rename_sem,1);
+                       sema_init(&s->s_nfsd_free_path_sem,1);
                        vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
                        if (vfsmnt) {
                                if (nfs_root_mount(sb) >= 0) {
index 074cad84f4636590d2373c57d6437c2a2203feb2..69ea9cf48686046f0c73a841104ca6c6528cc8e5 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
  * Include file for the interface to an APM BIOS
- * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.com)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -90,32 +90,6 @@ struct apm_bios_info {
 #define        APM_FUNC_TIMER_ENABLE   1
 #define        APM_FUNC_TIMER_GET      2
 
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS         20
-
-/*
- * The per-file APM data
- */
-struct apm_bios_struct {
-       int             magic;
-       struct apm_bios_struct *        next;
-       int             suser;
-       int             suspends_pending;
-       int             standbys_pending;
-       int             suspends_read;
-       int             standbys_read;
-       int             event_head;
-       int             event_tail;
-       apm_event_t     events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_bios_struct
- */
-#define APM_BIOS_MAGIC         0x4101
-
 /*
  * in init/main.c
  */
index 3dfa8f67dd1994a73f83e514756d40973a427c52..3dcad335743a3c72364bc2fd40fedaf3cd345ae5 100644 (file)
@@ -98,6 +98,12 @@ struct dentry_operations {
                                         * renamed" and has to be
                                         * deleted on the last dput()
                                         */
+#define        DCACHE_NFSD_DISCONNECTED 0x0004 /* This dentry is not currently connected to the
+                                        * dcache tree. Its parent will either be itself,
+                                        * or will have this flag as well.
+                                        * If this dentry points to a directory, then
+                                        * s_nfsd_free_path semaphore will be down
+                                        */
 
 /*
  * d_drop() unhashes the entry from the parent
index dc35928e7aa7db538c18bf17f26de99646b6d264..a64c6f9c763c400f9e405bb7e3fb8e83a7888686 100644 (file)
@@ -435,6 +435,7 @@ struct inode {
 #define I_DIRTY                1
 #define I_LOCK         2
 #define I_FREEING      4
+#define I_CLEAR                8
 
 extern void __mark_inode_dirty(struct inode *);
 static inline void mark_inode_dirty(struct inode *inode)
@@ -614,6 +615,15 @@ struct super_block {
         * even looking at it. You had been warned.
         */
        struct semaphore s_vfs_rename_sem;      /* Kludge */
+
+       /* The next field is used by knfsd when converting a (inode number based)
+        * file handle into a dentry. As it builds a path in the dcache tree from
+        * the bottom up, there may for a time be a subpath of dentrys which is not
+        * connected to the main tree.  This semaphore ensure that there is only ever
+        * one such free path per filesystem.  Note that unconnected files (or other
+        * non-directories) are allowed, but not unconnected diretories.
+        */
+       struct semaphore s_nfsd_free_path_sem;
 };
 
 /*
@@ -676,6 +686,10 @@ struct inode_operations {
        int (*revalidate) (struct dentry *);
 };
 
+/*
+ * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called
+ * without the big kernel lock held in all filesystems.
+ */
 struct super_operations {
        void (*read_inode) (struct inode *);
        void (*write_inode) (struct inode *);
index 957d024684b3b9b690f15b8ffde724b6865b1137..62325a43e5ad5cd316b8acc0d2b8dab33a0e1d95 100644 (file)
@@ -157,11 +157,11 @@ typedef unsigned char     byte;   /* used everywhere */
  * Timeouts for various operations:
  */
 #define WAIT_DRQ       (5*HZ/100)      /* 50msec - spec allows up to 20ms */
-#ifdef CONFIG_APM
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
 #define WAIT_READY     (5*HZ)          /* 5sec - some laptops are very slow */
 #else
 #define WAIT_READY     (3*HZ/100)      /* 30msec - should be instantaneous */
-#endif /* CONFIG_APM */
+#endif /* CONFIG_APM || CONFIG_APM_MODULE */
 #define WAIT_PIDENTIFY (10*HZ) /* 10sec  - should be less than 3ms (?)
                                            if all ATAPI CD is closed at boot */
 #define WAIT_WORSTCASE (30*HZ) /* 30sec  - worst case when spinning up */
index 6a2240a2059e44815b5addd04e0b361a730eaeca..e1163acdeece217264c8b78c55957a47f8830c9f 100644 (file)
@@ -48,7 +48,7 @@
 
 #define QUEUE_FIRST(head, listnam) (head)->DLIST_NEXT(listnam)
 #define QUEUE_LAST(head, listnam) (head)->DLIST_PREV(listnam)
-#define QUEUE_EMPTY(head, listnam) \
+#define QUEUE_IS_EMPTY(head, listnam) \
        ((QUEUE_FIRST(head, listnam) == QUEUE_LAST(head, listnam)) && \
         ((u_long)QUEUE_FIRST(head, listnam) == (u_long)head)) 
 
index 41a3c31904fdcc423f2f168c134145fc3dcdd6c0..eda945b6c1ae46d3de882df0bd06ae291c398df0 100644 (file)
@@ -574,7 +574,39 @@ unsigned int ss_vendor, unsigned int ss_device, const struct pci_dev *from)
 { return NULL; }
 
 extern inline void pci_set_master(struct pci_dev *dev) { }
-extern inline int pci_enable_device(struct pci_dev *dev) { return 0; }
+extern inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
+extern inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; }
+
+#else
+
+/*
+ * a helper function which helps ensure correct pci_driver
+ * setup and cleanup for commonly-encountered hotplug/modular cases
+ *
+ * This MUST stay in a header, as it checks for -DMODULE
+ */
+extern inline int pci_module_init(struct pci_driver *drv)
+{
+       int rc = pci_register_driver (drv);
+
+       if (rc > 0)
+               return 0;
+
+       /* iff CONFIG_HOTPLUG and built into kernel, we should
+        * leave the driver around for future hotplug events.
+        * For the module case, a hotplug daemon of some sort
+        * should load a module in response to an insert event. */
+#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
+       if (rc == 0)
+               return 0;
+#endif
+
+       /* if we get here, we need to clean up pci driver instance
+        * and return some sort of error */
+       pci_unregister_driver (drv);
+       
+       return -ENODEV;
+}
 
 #endif /* !CONFIG_PCI */
 
index aaafe127ff3d627bf5507c05752a5bba6c245ec9..3f73f489f848f12436f6437c7d3377ade49d67d8 100644 (file)
@@ -105,7 +105,7 @@ struct pm_dev
        struct list_head entry;
 };
 
-#if defined(CONFIG_ACPI) || defined(CONFIG_APM)
+#if defined(CONFIG_ACPI) || defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
 
 extern int pm_active;
 
@@ -141,7 +141,7 @@ struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
 extern inline void pm_access(struct pm_dev *dev) {}
 extern inline void pm_dev_idle(struct pm_dev *dev) {}
 
-#else // CONFIG_ACPI || CONFIG_APM
+#else /* CONFIG_ACPI || CONFIG_APM || CONFIG_APM_MODULE */
 
 #define PM_IS_ACTIVE() 0
 
@@ -169,11 +169,11 @@ extern inline struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
 extern inline void pm_access(struct pm_dev *dev) {}
 extern inline void pm_dev_idle(struct pm_dev *dev) {}
 
-#endif // CONFIG_ACPI || CONFIG_APM
+#endif /* CONFIG_ACPI || CONFIG_APM || CONFIG_APM_MODULE */
 
 extern void (*pm_idle)(void);
 extern void (*pm_power_off)(void);
 
-#endif // __KERNEL__
+#endif /* __KERNEL__ */
 
 #endif /* _LINUX_PM_H */
index f9460b91aa6317417da55512d8704e3561504ac9..2089faac1bcb6cfff637e945c6544d325cf642f2 100644 (file)
@@ -7,9 +7,14 @@
 
 #define PSCHED_CLOCK_SOURCE    PSCHED_JIFFIES
 
+#include <linux/config.h>
 #include <linux/pkt_sched.h>
 #include <net/pkt_cls.h>
 
+#ifdef CONFIG_X86_TSC
+#include <asm/msr.h>
+#endif
+
 struct rtattr;
 struct Qdisc;
 
@@ -247,11 +252,11 @@ extern int psched_clock_scale;
 
 #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
 
-#if CPU == 586 || CPU == 686
+#ifdef CONFIG_X86_TSC
 
 #define PSCHED_GET_TIME(stamp) \
 ({ u64 __cur; \
-   __asm__ __volatile__ (".byte 0x0f,0x31" :"=A" (__cur)); \
+   rdtscll(__cur); \
    (stamp) = __cur>>psched_clock_scale; \
 })
 
index 82fad0a3704d4719301285953200acac6bf7e553..ebba04ae9e4580b7ac7a3064d1f1d463d55da799 100644 (file)
@@ -9,6 +9,10 @@
 #include <linux/kernel.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_X86_TSC
+#include <asm/msr.h>
+#endif
+
 struct net_profile_slot
 {
        char   id[16];
@@ -25,14 +29,11 @@ extern atomic_t net_profile_active;
 extern struct timeval net_profile_adjust;
 extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved);
 
-#if CPU == 586 || CPU == 686
-
+#ifdef CONFIG_X86_TSC
 
 extern __inline__ void  net_profile_stamp(struct timeval *pstamp)
 {
-       __asm__ __volatile__ (".byte 0x0f,0x31"
-               :"=a" (pstamp->tv_usec),
-               "=d" (pstamp->tv_sec));
+       rdtsc(pstamp->tv_usec, pstamp->tv_sec);
 }
 
 extern __inline__ void  net_profile_accumulate(struct timeval *entered,
index 88f5fd63f111d25237744199a81905a80f833474..43ee74a791c2809fc3ebe142e50f2e4f738e977a 100644 (file)
@@ -376,6 +376,7 @@ EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(loops_per_sec);
 #endif
 EXPORT_SYMBOL(kstat);
+EXPORT_SYMBOL(nr_running);
 
 /* misc */
 EXPORT_SYMBOL(panic);
@@ -461,6 +462,7 @@ EXPORT_SYMBOL(get_fast_time);
 
 /* library functions */
 EXPORT_SYMBOL(strnicmp);
+EXPORT_SYMBOL(strspn);
 
 /* software interrupts */
 EXPORT_SYMBOL(tasklet_hi_vec);
@@ -468,6 +470,8 @@ EXPORT_SYMBOL(tasklet_vec);
 EXPORT_SYMBOL(bh_task_vec);
 EXPORT_SYMBOL(init_bh);
 EXPORT_SYMBOL(remove_bh);
+EXPORT_SYMBOL(tasklet_init);
+EXPORT_SYMBOL(tasklet_kill);
 
 /* init task, for moving kthread roots - ought to export a function ?? */
 
index 26811bff290803f0f180d8bfe5bab87848fe4aed..c35620402cdc0b4deeeb91cbdc9959330dba2299 100644 (file)
@@ -168,3 +168,4 @@ EXPORT_SYMBOL(pm_unregister);
 EXPORT_SYMBOL(pm_unregister_all);
 EXPORT_SYMBOL(pm_send_request);
 EXPORT_SYMBOL(pm_find);
+EXPORT_SYMBOL(pm_active);
index 03c05e7c36a207a95cbdaf7e05cedbe95ccbb7b4..1ccc6826cad516203db2a251bd2c5c851e749ed8 100644 (file)
@@ -141,7 +141,7 @@ static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struc
 #endif
 
        /* .. and a slight advantage to the current MM */
-       if (p->mm == this_mm)
+       if (p->mm == this_mm || !p->mm)
                weight += 1;
        weight += p->priority;
 
@@ -173,7 +173,7 @@ static inline int prev_goodness(struct task_struct * p, int this_cpu, struct mm_
  */
 static inline int preemption_goodness(struct task_struct * prev, struct task_struct * p, int cpu)
 {
-       return goodness(p, cpu, prev->mm) - goodness(prev, cpu, prev->mm);
+       return goodness(p, cpu, prev->active_mm) - goodness(prev, cpu, prev->active_mm);
 }
 
 /*
index 6ea05dd76d5b9bd199c33fe869cd1959a6ffcec8..5721fc5d51f66dcfb10497bb9e919448260428bf 100644 (file)
@@ -275,7 +275,7 @@ unsigned long do_mremap(unsigned long addr,
        ret = -ENOMEM;
        if (flags & MREMAP_MAYMOVE) {
                if (!(flags & MREMAP_FIXED)) {
-                       new_addr = get_unmapped_area(addr, new_len);
+                       new_addr = get_unmapped_area(0, new_len);
                        if (!new_addr)
                                goto out;
                }
index 7803095ef7db696be2d097a174e1ca1941f5b223..efdbb98f1c82507a422e143408fbc15cd29c7962 100644 (file)
@@ -258,7 +258,9 @@ struct page * __alloc_pages (zonelist_t *zonelist, unsigned long order)
                 */
                if (!(current->flags & PF_MEMALLOC))
                {
-                       if (classfree(z) > z->pages_high)
+                       unsigned long free = classfree(z);
+
+                       if (free > z->pages_high)
                        {
                                if (z->low_on_memory)
                                        z->low_on_memory = 0;
@@ -270,11 +272,11 @@ struct page * __alloc_pages (zonelist_t *zonelist, unsigned long order)
                                if (z->low_on_memory)
                                        goto balance;
 
-                               if (classfree(z) <= z->pages_low)
+                               if (free <= z->pages_low)
                                {
                                        wake_up_interruptible(&kswapd_wait);
 
-                                       if (classfree(z) <= z->pages_min)
+                                       if (free <= z->pages_min)
                                        {
                                                z->low_on_memory = 1;
                                                goto balance;
@@ -298,16 +300,6 @@ ready:
                }
        }
 
-       /*
-        * If we can schedule, do so, and make sure to yield.
-        * We may be a real-time process, and if kswapd is
-        * waiting for us we need to allow it to run a bit.
-        */
-       if (gfp_mask & __GFP_WAIT) {
-               current->policy |= SCHED_YIELD;
-               schedule();
-       }
-
 nopage:
        return NULL;
 
index 34a818721cea8d65fea179ca48cbe9e2a39ae761..d2ed4f5231ceeeeae4a6bc036a64af9e3b0e9721 100644 (file)
@@ -2143,9 +2143,5 @@ int __init net_dev_init(void)
         
        net_device_init();
 
-#ifdef CONFIG_IP_PNP
-       ip_auto_config();
-#endif
-
        return 0;
 }
index 8b2616c5022c7b12a4d1dd61df5e68b0699f8113..0408447cbb110b4a355365c28fe5e0a2fa35819e 100644 (file)
@@ -271,12 +271,6 @@ int __init net_profile_init(void)
        register_netdevice(&whitehole_dev);
 
        printk("Evaluating net profiler cost ...");
-#if CPU == 586 || CPU == 686
-       if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC)) {
-               printk(KERN_ERR "Sorry, your CPU does not support TSC. Net profiler disabled.\n");
-               return -1;
-       }
-#endif
 #ifdef __alpha__
        alpha_tick(0);
 #endif
index 82e443d4d95436ec72f947477fd1aae34065f18b..bcdd71354fbedfe4c08c2e64bd057f94f1903c44 100644 (file)
@@ -821,7 +821,7 @@ static int __init ic_dynamic(void)
  *     IP Autoconfig dispatcher.
  */
 
-int __init ip_auto_config(void)
+static int __init ip_auto_config(void)
 {
        if (!ic_enable)
                return 0;
@@ -879,6 +879,9 @@ int __init ip_auto_config(void)
        return 0;
 }
 
+module_init(ip_auto_config);
+
+
 /*
  *  Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
  *  command line parameter. It consists of option fields separated by colons in
index f3f1d0bcf82298ea48eab4d4d7505f7a8dca7328..37ab925bffa3729add84a51f00655f86a87a990a 100644 (file)
@@ -857,11 +857,15 @@ void tcp_send_fin(struct sock *sk)
                }
        } else {
                /* Socket is locked, keep trying until memory is available. */
-               do {
+               for (;;) {
                        skb = sock_wmalloc(sk,
                                           MAX_TCP_HEADER + 15,
                                           1, GFP_KERNEL);
-               } while (skb == NULL);
+                       if (skb)
+                               break;
+                       current->policy |= SCHED_YIELD;
+                       schedule();
+               }
 
                /* Reserve space for headers and prepare control bits. */
                skb_reserve(skb, MAX_TCP_HEADER);
index 1d57af985591f65462a980d298ec7aaac7185882..9da8dcdcd7370ac230c7b7c0bcad4ff06608701f 100644 (file)
@@ -1139,11 +1139,6 @@ int __init psched_calibrate_clock(void)
        long rdelay;
        unsigned long stop;
 
-#if CPU == 586 || CPU == 686
-       if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC))
-               return -1;
-#endif
-
 #ifdef PSCHED_WATCHER
        psched_tick(0);
 #endif
index d993f6bf8d018b3e624d5595c8c072106d07d9b0..4916dc51d85a0c2fa574ac3504c5ef79e336402f 100644 (file)
@@ -311,6 +311,26 @@ function dep_bool () {
        bool "$ques" "$var"
 }
 
+function dep_mbool () {
+       ques=$1
+       var=$2
+       shift 2
+       while [ $# -gt 0 ]; do
+         case "$1" in
+           n)
+             define_bool "$var" "n"
+             return
+             ;;
+           m)
+             eval "$var=y"
+             ;;
+         esac
+         shift
+       done
+
+       bool "$ques" "$var"
+}
+
 #
 # define_int sets the value of a integer argument
 #
index 824d440144005dfd70bbefeefa43ca9829ec7cb2..d43739a679f082e916d282a9df276c06a629dcdb 100644 (file)
@@ -258,6 +258,26 @@ function dep_bool () {
        fi
 }
 
+function dep_mbool () {
+       ques="$1"
+       var="$2"
+       dep=y
+       shift 2
+       while [ $# -gt 0 ]; do
+               if [ "$1" = y -o "$1" = m ]; then
+                       shift
+               else
+                       dep=n
+                       shift $#
+               fi
+       done
+       if [ "$dep" = y ]; then
+           bool "$ques" "$var"
+       else 
+           define_bool "$var" n
+       fi
+}
+
 #
 # Add a menu item which will call our local int function.
 # 
@@ -1083,6 +1103,20 @@ save_configuration () {
                define_bool "$var" "$x"
        }
 
+       function dep_mbool () {
+               set_x_info "$2" "n"
+               var="$2"
+               shift 2
+               while [ $# -gt 0 ]; do
+                       if   [ "$1" = y -o "$1" = m ]; then
+                               shift
+                       else 
+                               x=n; shift $#
+                       fi
+               done
+               define_bool "$var" "$x"
+       }
+
        function int () {
                set_x_info "$2" "$3"
                echo "$2=$x"            >>$CONFIG
index adb5e0d41c130df0448098191591b92a35cfb303..6a88f68810628f198d1622ad953545e9fe0e74fd 100644 (file)
@@ -249,17 +249,19 @@ proc sync_tristate { var dep } {
        return $var
 }
 
-proc sync_bool { var dep } {
+proc sync_bool { var dep modset } {
        set var [sync_tristate $var $dep]
-       if {$dep == 2} then {
-               set var 0
+       if {$dep == 2 && $var == 2} then {
+               set var $modset
        }
        return $var
 }
 
-proc write_tristate { file1 file2 varname variable deplist } {
+proc write_tristate { file1 file2 varname variable deplist modset } {
        set variable [sync_tristate $variable [effective_dep $deplist]]
-       if { $variable == 1 }\
+       if { $variable == 2 } \
+               then { set variable $modset }
+       if { $variable == 1 } \
                then { puts $file1 "$varname=y"; \
                       puts $file2 "#define $varname 1" } \
        elseif { $variable == 2 } \
index ab0f74832f5ad9424793b39564b6636d1ece318f..34c923fe9e5f7921a47584268a4c7824fb0555d2 100644 (file)
@@ -53,6 +53,7 @@ static void mark_variables( struct kconfig * scfg )
        ||   cfg->token == token_define_string
        ||   cfg->token == token_define_tristate
        ||   cfg->token == token_dep_bool
+       ||   cfg->token == token_dep_mbool
        ||   cfg->token == token_dep_tristate
        ||   cfg->token == token_hex
        ||   cfg->token == token_int
@@ -517,6 +518,7 @@ void fix_conditionals( struct kconfig * scfg )
                break;
 
            case token_dep_bool:
+           case token_dep_mbool:
            case token_dep_tristate:
                /*
                 * Same as the other simple statements, plus an additional
index 4a50a82a44f67599a41ca176b72a3f240962ce56..e016218d728e595a0481838457a69c0bcfc08ee6 100644 (file)
@@ -343,12 +343,16 @@ void generate_if( struct kconfig * cfg, struct condition * ocond,
      */
     if ( line_num >= -1 )
     {
+       int modtoyes = 0;
+
        switch ( cfg->token )
        {
        default:
            printf( " }\n" );
            break;
 
+       case token_dep_mbool:
+           modtoyes = 1;
        case token_dep_bool:
            printf( "\n" );
            for ( tmp = cfg->depend; tmp; tmp = tmp->next )
@@ -359,10 +363,13 @@ void generate_if( struct kconfig * cfg, struct condition * ocond,
            printf( "\tset tmpvar_dep [effective_dep [list" );
            for ( tmp = cfg->depend; tmp; tmp = tmp->next )
                printf( " $%s", tmp->name );
-           printf( "]];set %s [sync_bool $%s $tmpvar_dep];",
-               vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
-           printf( "if {$tmpvar_dep != 1} then {" );
-           printf( "configure_entry .menu%d.config.f.x%d disabled {y};",
+           printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
+               vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
+               modtoyes );
+           printf( "if {$tmpvar_dep != 1" );
+           if (modtoyes)
+               printf( " && $tmpvar_dep != 2" );
+           printf( "} then {configure_entry .menu%d.config.f.x%d disabled {y};",
                menu_num, line_num );
            printf( "} else {" );
            printf( "configure_entry .menu%d.config.f.x%d normal {y};",
@@ -474,12 +481,16 @@ void generate_if( struct kconfig * cfg, struct condition * ocond,
     }
     else
     {
+       int modtoyes = 0;
+
        switch ( cfg->token )
        {
        default:
            printf( " }\n" );
            break;
 
+       case token_dep_mbool:
+           modtoyes = 1;
        case token_dep_bool:
            printf( "\n" );
            for ( tmp = cfg->depend; tmp; tmp = tmp->next )
@@ -490,8 +501,9 @@ void generate_if( struct kconfig * cfg, struct condition * ocond,
            printf( "\tset tmpvar_dep [effective_dep [list" );
            for ( tmp = cfg->depend; tmp; tmp = tmp->next )
                printf( " $%s", tmp->name );
-           printf( "]];set %s [sync_bool $%s $tmpvar_dep];",
-               vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+           printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
+               vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
+               modtoyes );
        case token_bool:
            if ( cfg->token == token_bool )
                printf( "\n\t" );
@@ -604,6 +616,7 @@ void generate_writeconfig( struct kconfig * cfg )
 {
     struct condition * cond;
     struct dependency * tmp;
+    int depmod = 2;
     
     /*
      * Generate global declaration for this symbol.
@@ -705,7 +718,7 @@ void generate_writeconfig( struct kconfig * cfg )
 
     case token_bool:
     case token_tristate:
-       printf( "write_tristate $cfg $autocfg %s $%s [list $notmod]", 
+       printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2", 
            vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
        if ( cfg->cond != NULL )
            printf( " }" );
@@ -724,7 +737,7 @@ void generate_writeconfig( struct kconfig * cfg )
                  cfg1 != NULL && cfg1->token == token_choice_item;
                  cfg1  = cfg1->next )
            {
-               printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] } else { write_tristate $cfg $autocfg %s 0 [list $notmod] }",
+               printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] 2 } else { write_tristate $cfg $autocfg %s 0 [list $notmod] 2 }",
                    -(cfg->nameindex), cfg1->label,
                    vartable[cfg1->nameindex].name,
                    vartable[cfg1->nameindex].name );
@@ -751,23 +764,25 @@ void generate_writeconfig( struct kconfig * cfg )
     case token_define_tristate:
        if ( cfg->cond == NULL )
        {
-           printf( "write_tristate $cfg $autocfg %s $%s [list $notmod]\n",
+           printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2\n",
                vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
        }
        else
        {
-           printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] }\n",
+           printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] }\n",
                vartable[cfg->nameindex].name, cfg->value );
        }
        break;
 
+    case token_dep_mbool:
+       depmod = 1;
     case token_dep_bool:
     case token_dep_tristate:
        printf( "write_tristate $cfg $autocfg %s $%s [list",
            vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
        for ( tmp = cfg->depend; tmp; tmp = tmp->next )
            printf( " $%s", tmp->name );
-       printf( "]" );
+       printf( "] %d", depmod );
        if ( cfg->cond != NULL )
            printf( " }" );
        printf( "\n" );
@@ -887,6 +902,7 @@ static void generate_update_var( struct kconfig * scfg, int menu_num )
            case token_define_string:
            case token_dep_bool:
            case token_dep_tristate:
+           case token_dep_mbool:
            case token_int:
            case token_hex:
            case token_mainmenu_option:
@@ -1121,6 +1137,7 @@ void dump_tk_script( struct kconfig * scfg )
        case token_choice_item:
        case token_dep_bool:
        case token_dep_tristate:
+       case token_dep_mbool:
        case token_hex:
        case token_int:
        case token_string:
@@ -1222,6 +1239,7 @@ void dump_tk_script( struct kconfig * scfg )
                break;
 
            case token_dep_bool:
+           case token_dep_mbool:
                cfg->menu_line = menu_line++;
                printf( "\tdep_bool $w.config.f %d %d \"%s\" %s\n",
                    cfg->menu_number, cfg->menu_line, cfg->label,
@@ -1300,6 +1318,7 @@ void dump_tk_script( struct kconfig * scfg )
        case token_choice_item:
        case token_dep_bool:
        case token_dep_tristate:
+       case token_dep_mbool:
        case token_tristate:
            if ( ! vartable[cfg->nameindex].global_written )
            {
@@ -1376,6 +1395,7 @@ void dump_tk_script( struct kconfig * scfg )
        case token_define_tristate:
        case token_dep_bool:
        case token_dep_tristate:
+       case token_dep_mbool:
        case token_hex:
        case token_int:
        case token_string:
index 86924a08d82aa019480e411bb126a73642565618..bf27a3a8b4c9bc900ecc5b2f2b1936baf402b2d5 100644 (file)
@@ -386,6 +386,7 @@ static void tokenize_line( const char * pnt )
        match_token( token_define_string, "define_string" );
        match_token( token_define_tristate, "define_tristate" );
        match_token( token_dep_bool, "dep_bool" );
+       match_token( token_dep_mbool, "dep_mbool" );
        match_token( token_dep_tristate, "dep_tristate" );
        break;
 
@@ -549,6 +550,7 @@ static void tokenize_line( const char * pnt )
        break;
 
     case token_dep_bool:
+    case token_dep_mbool:
     case token_dep_tristate:
        pnt = get_qstring ( pnt, &cfg->label );
        pnt = get_string  ( pnt, &buffer );
@@ -585,7 +587,7 @@ static void tokenize_line( const char * pnt )
            }
            else
            {
-               syntax_error( "can't handle dep_bool/dep_tristate condition" );
+               syntax_error( "can't handle dep_bool/dep_mbool/dep_tristate condition" );
            }
            dep_ptr = &(*dep_ptr)->next;
            while ( *pnt == ' ' || *pnt == '\t' )
@@ -623,12 +625,12 @@ static void tokenize_line( const char * pnt )
                *cond_ptr = malloc( sizeof(struct condition) );
                memset( *cond_ptr, 0, sizeof(struct condition) );
                (*cond_ptr)->op = op_lparen;
-               if ( token == token_dep_tristate )
-                   sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then",
-                       dep->name, dep->name, dep->name );
-               else
+               if ( token == token_dep_bool )
                    sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then",
                        dep->name, dep->name );
+               else
+                   sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then",
+                       dep->name, dep->name, dep->name );
                (*cond_ptr)->next = tokenize_if( fake_if );
                while ( *cond_ptr )
                    cond_ptr = &(*cond_ptr)->next;
index ecb31b6548920bac921d58ad7bac17b99e62713d..1ca16b1852e73e692fe2091c1572737245314da4 100644 (file)
@@ -19,6 +19,7 @@ enum e_token
     token_define_string,
     token_define_tristate,
     token_dep_bool,
+    token_dep_mbool,
     token_dep_tristate,
     token_else, 
     token_endmenu,
@@ -77,7 +78,7 @@ struct condition
 };
 
 /*
- * Dependency list for dep_bool, dep_tristate
+ * Dependency list for dep_bool, dep_mbool, dep_tristate
  */
 
 struct dependency