]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.1.93 2.1.93
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:06 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:06 +0000 (15:15 -0500)
2.1.93 is out there. It is broken on other platforms than x86, because I
had to move some initialization code around, but this shoul dbe very easy
to fix (moving the device init code later makes a _lot_ of things easier:
the system is essentially up and running, and "kmalloc()" etc actually
works).

Now the PCI init code actually has the full SMP knowledge, which it needs
in order to get the interrupt mapping stuff right (for example - it might
eventually need it for other reasons too).

The PCI code has generally been cleaned up - thanks to Martin Mares (the
PCI cleanup is what forced me to do the other changes - anything else
would simply have been too ugly).

2.1.93 should also fix the stupid things in 92 (modules don't load due to
missing symbols, and NULL pointer dereferences in /proc under certain
circumstances etc).

The kernel should also be better at detecting the really low memory
circumstances, and eventually return NULL instead of just looping forever
trying to find a page that it won't ever find.

                        Linus

[tytso on ext2fs changes:]
These patches provide the following enhancements to ext2.
        * Fixed a bug where we weren't byte-swapping the feature set
                flags before checking EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
        * Added Stephen Tweedie's patches to allow the number of file
                blocks which will be preallocated to be tuned (instead
                of being fixed at 8 blocks).
        * Added Stephen Tweedie's patches to allow directory blocks to
                be preallocated.  This change is only activated if the
                EXT2_FEATURE_COMPAT_DIR_PREALLOC is enabled.  (There
                will soon be a new release of e2fsprogs that will
                allow you to turn this on.)  The change is compatible
                with older kernels (that's why it's a COMPAT feature),
                but we need to flag it in the feature set because the
                e2fsck needs a few changes to support this.
        * Added future support for B-trees in directories.  I have a
                design in mind which is fully read/only compatible
                with the existing ext2 directories, which will make
                its debut in the 2.3 kernel series.  This patch will
                allow 2.2 kernels to mount filesystems with B-tree
                directories read-write; if a 2.2 kernel tries to
                modify a B-tree directory, the B-tree valid bit will
                be turned off, since the B-tree structures won't be
                updated by 2.2 kernels.  2.0 kernels will be able to
                mount filesystems with B-tree directories read-only.
                This defines a new feature, EXT2_FEATURE_RO_COMPAT_BTREE_DIR.
        * Added Jakub Jelinek's support for large files on 64-bit
                platforms.  On a 64-bit platform, the first time you
                expand a file past the 32-bit boundary, the
                EXT2_FEATURE_RO_COMPAT_LARGE_FILE is turned on.
                2.0 machines will be able to mount such filesystems
                read-only.  2.2 kernels on 32-bit platforms will be
                able such filesystems read-write, but they will only
                be able to see the first 2**32 bytes of the file, and
                any attempt to open a large file for read/write access
                will cause an EBIGF error.
        * Added support for storing the file type in the directory
                entry.  This optimization was added to BSD 4.4 and
                makes a very big difference for a number of
                operations, since application programs can avoid doing
                a stat in a number of situations.  Support for this is
                in the GNU user-land utilities, and is in glibc
                already.  Beyond this patch, we also need to implement
                a new getdents system call that will return the
                information all the way to libc.
                The reason why it's important to get this change into
                2.2 is that it requires "stealing" 8-bits from the
                name_len field of the directory entry.  Ext2fs limits
                you to 255 characters in a file name, so the high-byte
                of name_len is always zero.  However, older kernels
                look at both bytes of name_len, and will get confused
                if we try to store something there.  So we can only
                update the file type field if the feature
                EXT2_FEATURE_INCOMPAT_FILETYPE is enabled.
                I want to get this support into the 2.2 kernel, since
                even if it isn't used much (because people will want
                their filesystems to be compatible with 2.0 kernels),
                we will be able to migrate smoothly to using this
                feature by default in the future.

161 files changed:
Documentation/Configure.help
Documentation/networking/ip_dynaddr.txt [new file with mode: 0644]
Documentation/networking/ppp.txt
Documentation/networking/routing.txt
Documentation/pci.txt [new file with mode: 0644]
Documentation/sysrq.txt [new file with mode: 0644]
Makefile
arch/alpha/kernel/bios32.c
arch/alpha/kernel/cia.c
arch/alpha/kernel/lca.c
arch/alpha/kernel/mcpcia.c
arch/alpha/kernel/pyxis.c
arch/alpha/kernel/smc37c669.c
arch/alpha/kernel/smc37c93x.c
arch/alpha/kernel/t2.c
arch/alpha/kernel/tsunami.c
arch/i386/kernel/bios32.c
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/smp.c
arch/i386/mm/init.c
arch/mips/kernel/pci.c
arch/mips/sni/pci.c
drivers/block/Config.in
drivers/block/Makefile
drivers/block/cmd646.c [new file with mode: 0644]
drivers/block/ide-dma.c
drivers/block/ide-pci.c
drivers/block/ide-proc.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/ll_rw_blk.c
drivers/block/ns87415.c
drivers/block/opti621.c
drivers/block/rz1000.c
drivers/block/sl82c105.c [new file with mode: 0644]
drivers/block/trm290.c
drivers/block/xd.c
drivers/char/Makefile
drivers/char/cyclades.c
drivers/char/epca.c
drivers/char/pc_keyb.c
drivers/char/pty.c
drivers/char/rocket.c
drivers/char/stallion.c
drivers/char/tga.c
drivers/char/tty_io.c
drivers/misc/parport_pc.c
drivers/net/3c59x.c
drivers/net/de4x5.c
drivers/net/defxx.c
drivers/net/defxx.h
drivers/net/dgrs.c
drivers/net/eepro100.c
drivers/net/hp100.c
drivers/net/lance.c
drivers/net/ne.c
drivers/net/pcnet32.c
drivers/net/sunhme.c
drivers/net/tlan.c
drivers/net/tulip.c
drivers/pci/Makefile
drivers/pci/compat.c [new file with mode: 0644]
drivers/pci/oldproc.c
drivers/pci/pci.c
drivers/pci/pcisyms.c [new file with mode: 0644]
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/scsi/53c7,8xx.c
drivers/scsi/53c7xx.c
drivers/scsi/53c7xx.h
drivers/scsi/AM53C974.c
drivers/scsi/README.in2000
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx.h
drivers/scsi/aic7xxx_proc.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/eata_dma.c
drivers/scsi/eata_pio.c
drivers/scsi/fdomain.c
drivers/scsi/gdth.c
drivers/scsi/in2000.c
drivers/scsi/in2000.h
drivers/scsi/ncr53c8xx.c
drivers/scsi/ncr53c8xx.h
drivers/scsi/pci2000.c
drivers/scsi/pci2220i.c
drivers/scsi/qlogicisp.c
drivers/scsi/scsi.c
drivers/scsi/scsi_obsolete.c
drivers/scsi/tmscsim.c
drivers/scsi/tmscsim.h
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
fs/Config.in
fs/Makefile
fs/adfs/super.c
fs/affs/super.c
fs/autofs/inode.c
fs/autofs/root.c
fs/coda/inode.c
fs/dcache.c
fs/devpts/Makefile [new file with mode: 0644]
fs/devpts/devpts_i.h [new file with mode: 0644]
fs/devpts/inode.c [new file with mode: 0644]
fs/devpts/root.c [new file with mode: 0644]
fs/exec.c
fs/ext2/balloc.c
fs/ext2/dir.c
fs/ext2/file.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/ext2/super.c
fs/fat/inode.c
fs/filesystems.c
fs/hfs/super.c
fs/hpfs/hpfs_fs.c
fs/isofs/inode.c
fs/minix/inode.c
fs/ncpfs/inode.c
fs/nfs/inode.c
fs/ntfs/fs.c
fs/proc/inode.c
fs/proc/link.c
fs/romfs/inode.c
fs/smbfs/inode.c
fs/super.c
fs/sysv/inode.c
fs/ufs/ufs_super.c
include/asm-i386/smp.h
include/asm-i386/string.h
include/linux/bios32.h
include/linux/devpts_fs.h [new file with mode: 0644]
include/linux/ext2_fs.h
include/linux/ext2_fs_i.h
include/linux/pci.h
include/linux/proc_fs.h
include/linux/skbuff.h
include/net/br.h
include/net/ip.h
include/net/snmp.h
include/net/sock.h
include/net/tcp.h
init/main.c
kernel/ksyms.c
mm/page_alloc.c
net/core/dev.c
net/ipv4/af_inet.c
net/ipv4/ip_input.c
net/ipv4/proc.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/tcp_ipv6.c

index 64cb0570272850d564d8e4d961b7e6d94c2deb71..9b762c0139bcbb323ae310f5855c26ac515bea4e 100644 (file)
@@ -974,8 +974,7 @@ CONFIG_TGA_CONSOLE
   that implements the TGA interface (much like the VGA standard, but
   older TGA adapters are *not* VGA compatible).  On such systems, you
   should say Y here so that the TGA driver rather than the standard
-  VGA driver is used.  Note that, at this time, there is no X server
-  for these systems. If unsure, try N.
+  VGA driver is used.
 
 PCI support
 CONFIG_PCI
@@ -1019,9 +1018,13 @@ CONFIG_PCI_OPTIMIZE
 
 Backward-compatible /proc/pci
 CONFIG_PCI_OLD_PROC
-  If you say Y here and to the "/proc filesystem support" below, you
-  will get a directory /proc/pci with information about your PCI
-  hardware. If unsure, say Y.
+  Older kernels supported a /proc/pci file containing brief textual
+  description of all PCI devices in the system. Several programs tried
+  to parse this file, so it became almost impossible to add new
+  fields without breaking compatibility. So a new /proc interface to
+  PCI (/proc/bus/pci) has been implemented and the old one is supported
+  for compatibility reasons only (you can disable it here, gaining
+  some memory).  If unsure, say Y.
 
 MCA support
 CONFIG_MCA
@@ -5343,7 +5346,7 @@ CONFIG_ROMFS_FS
   M here and read Documentation/modules.txt. If you don't know whether
   you need it, then you don't need it: say N.
 
-Kernel automounter support (experimental)
+Kernel automounter support
 CONFIG_AUTOFS_FS
   The automounter is a tool to automatically mount remote filesystems
   on demand.  This implementation is partially kernel-based to reduce
@@ -5422,6 +5425,13 @@ CONFIG_ADFS_FS
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
+/dev/pts filesystem
+CONFIG_DEVPTS_FS
+  A filesystem which when mounted on /dev/pts and used in conjunction
+  with the /dev/ptmx multiplexing pty device, should allow full
+  support for Unix98 pty's without requiring setuid or daemons.  glibc
+  2.1 contains the requisite support for this mode of operation.
+
 Macintosh partition map support
 CONFIG_MAC_PARTITION
   Say Y here if you want your Linux system to be able to read the
diff --git a/Documentation/networking/ip_dynaddr.txt b/Documentation/networking/ip_dynaddr.txt
new file mode 100644 (file)
index 0000000..45f3c12
--- /dev/null
@@ -0,0 +1,29 @@
+IP dynamic address hack-port v0.03
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This stuff allows diald ONESHOT connections to get established by
+dynamically changing packet source address (and socket's if local procs).
+It is implemented for TCP diald-box connections(1) and IP_MASQuerading(2).
+
+If enabled[*] and forwarding interface has changed:
+  1)  Socket (and packet) source address is rewritten ON RETRANSMISSIONS
+      while in SYN_SENT state (diald-box processes).
+  2)  Out-bounded MASQueraded source address changes ON OUTPUT (when
+      internal host does retransmission) until a packet from outside is
+      received by the tunnel.
+
+This is specially helpful for auto dialup links (diald), where the
+``actual'' outgoing address is unknown at the moment the link is
+going up. So, the *same* (local AND masqueraded) connections requests that
+bring the link up will be able to get established.
+
+[*] At boot, by default no address rewriting is attempted. 
+  To enable:
+     # echo 1 > /proc/sys/net/ipv4/ip_dynaddr
+  To enable verbose mode:
+     # echo 2 > /proc/sys/net/ipv4/ip_dynaddr
+  To disable (default)
+     # echo 0 > /proc/sys/net/ipv4/ip_dynaddr
+
+Enjoy!
+
+-- Juanjo  <jjciarla@raiz.uncu.edu.ar>
index d34f3986bc5c15f335c02404afdd37b59f182db0..55c036251c4e363905b46b0b14c9400d4777119f 100644 (file)
@@ -1,11 +1,7 @@
 *NEWSFLASH*
 This kernel release needs a minor bug fix for pppd to run properly with
 the new routing code.  When your pppd doesn't work apply the following 
-patch to pppd-2.2.0f or install updated RPMs.
-
-Updated RPMs for libc5 machines (build on RedHat 4.0):
-ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.src.rpm
-ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.i386.rpm
+patch to pppd-2.2.0f or update to the newest pppd version.
 
 Patch:
 
index 99f571763641e92cae0e6aa36140b9263fe12a3e..42d4218ca13ca35561ace264b2ea9423212df4f1 100644 (file)
@@ -35,10 +35,10 @@ NEWS for user.
 
 NEWS for hacker.
 
-- New destination cache. Flexible, robust and just beatiful.
+- New destination cache. Flexible, robust and just beautiful.
 - Network stack is reordered, simplified, optimized, a lot of bugs fixed.
-  (well, and new bugs are intoduced, but I've yet not seen them 8))
-  It is difficult to descibe all the changes, look into source.
+  (well, and new bugs are introduced, but I haven't seen them yet 8))
+  It is difficult to describe all the changes, look into source.
 
 If you see this file, then this patch works 8)
 
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
new file mode 100644 (file)
index 0000000..b5d8632
--- /dev/null
@@ -0,0 +1,60 @@
+                      Few Notes About The PCI Subsystem
+
+                                      or
+
+               "What should you avoid when writing PCI drivers"
+
+         by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on 13-Feb-1998
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. How to find PCI devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+   In case your driver wants to search for all devices with given vendor/device
+ID, it should use:
+
+               struct pci_dev *dev = NULL;
+               while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
+                       configure_device(dev);
+
+   For class-based search, use pci_find_class(CLASS_ID, dev).
+
+   In case you want to do some complex matching, look at pci_devices -- it's
+a linked list of pci_dev structures for all PCI devices in the system.
+
+   All these methods return pointer to a pci_dev structure which is used as a
+parameter for many other PCI functions. The rest of them accept bus and
+device/function numbers which can be found in pci_dev->bus->number and
+pci_dev->devfn. Feel free to use all other fields of the pci_dev structure, but
+don't modify them.
+
+   The pci_present() function can be used to test presence of PCI in the
+machine.
+
+2. How to access PCI config space
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   You can use pci_(read|write)_config_(byte|word|dword) to access the config
+space of device represented by pci_dev. All these functions return 0 when
+successfull or an error code (PCIBIOS_...) which can be translated to text
+string by pcibios_strerror. Most drivers expect that accesses to valid PCI
+devices don't fail.
+
+   In case you want to address the devices by bus/device/function numbers,
+use pcibios_(read_write)_config_(byte|word|dword).
+
+   If you access fields in the standard portion of the config header, please
+use symbolic names of locations and bits declared in <linux/pci.h>.
+
+3. Addresses and interrupts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   Memory and port addresses and interrupt numbers should NOT be read from the
+config space. You should use the values in the pci_dev structure as they might
+have been remapped by the kernel.
+
+4. Obsolete functions
+~~~~~~~~~~~~~~~~~~~~~
+
+<linux/bios32.h> is obsolete and should not be included in new code.
+
+pcibios_find_(device|class) are also obsolete and should be replaced by
+pci_find_(device|class).
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
new file mode 100644 (file)
index 0000000..f9d282b
--- /dev/null
@@ -0,0 +1,89 @@
+                      MAGIC SYSRQ KEY DOCUMENTATION v1.0
+                     ------------------------------------
+                        [Fri Apr  3 08:27:12 EST 1998]
+
+1. What is the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It is a 'magical' key combo you can hit, and the kernel will respond to
+regardless of anything else, unless it is hard-locked.
+
+2. How do I enable the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. This option is only available it 2.1.x or later
+kernels.
+
+3. How do I use the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You press the key combo 'ALT-SysRQ-<command key>'.
+
+4. What are the 'command' keys?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+'r'     - Turns off keyboard raw mode and sets it to XLATE.
+
+'k'     - Kills all programs on the current virtual console.
+
+'b'     - Will immediately reboot the system without syncing or unmounting
+          your disks.
+
+'o'     - Will shut your system off via APM (if configured and supported).
+
+'s'     - Will attempt to sync all mounted filesystems.
+
+'u'     - Will attempt to remount all mounted file systems readonly.
+
+'p'     - Will dump the current registers and flags to your console.
+
+'t'     - Will dump a list of current tasks and their information to your
+          console.
+
+'m'     - Will dump current memory info to your console.
+
+'0'-'8' - Sets the console log level, controlling which kernel messages
+          will be printed to your console. ('0', for example would make
+          it so that only emergency messages like PANICs or OOPSes would
+          make it to your console.)
+
+'e'     - Send a SIGTERM to all processes, except for init.
+
+'i'     - Send a SIGKILL to all processes, except for init.
+
+'l'     - Send a SIGKILL to all processes, INCLUDING init. (Your system
+          will be non-functional after this.)
+
+5. Okay, so what can I use them for?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Well, un'R'aw is very handy when your X server or a svgalib program crashes.
+
+sa'K' (system attention key) is useful when you want to exit a program
+that will not let you switch consoles. (For example, X or a svgalib program.)
+
+re'B'oot is good when you're unable to shut down. But you should also 'S'ync
+and 'U'mount first.
+
+'S'ync is great when your system is locked up, it allows you to sync your
+disks and will certainly lessen the chance of data loss and fscking.
+
+'U'mount is basically useful in the same ways as 'S'ync. I generally 'S'ync,
+'U'mount, then re'B'oot when my system locks. It's saved me many a fsck.
+
+The loglevel'0'-'8' is useful when your console is being flooded with
+kernel messages you do not want to see. Setting '0' will prevent all but
+the most urgent kernel messages from reaching your console. (They will
+still be logged if syslogd/klogd are alive, though.)
+
+t'E'rm and k'I'll are useful if you have some sort of runaway process you
+are unable to kill any other way, especially if it's spawning other
+processes.
+
+6. Sometimes SysRQ seems to get 'stuck' after using it, what can I do?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+That happens to me, also. I've found that tapping shift, alt, and control
+on both sides of the keyboard, and hitting an invalid sysrq sequence again
+will fix the problem. (ie, something like alt-sysrq-z).
+
+7. I have more questions, who can I ask?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You may feel free to send email to myrdraal@deathsdoor.com, and I will
+respond as soon as possible.
+ -Myrdraal
index 8e39a665fb9587115b784fa865fc178e0da078f3..774ac07cda406dd0e3e51fc409c31d802a26d474 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 92
+SUBLEVEL = 93
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index 89e57e44e6f932cf66532f89ca86f59e6083fa41..b7dfd3135da0bd110cec81352f30cb59cb47ad3c 100644 (file)
@@ -56,7 +56,6 @@ asmlinkage int sys_pciconfig_write()
 
 #else /* CONFIG_PCI */
 
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
@@ -555,55 +554,6 @@ static int layout_bus(struct pci_bus *bus)
 #endif /* !PCI_MODIFY */
 
 
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-                        unsigned short index, unsigned char *bus,
-                        unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next) {
-               if (dev->vendor == vendor && dev->device == device_id) {
-                       if (curr == index) {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-                       unsigned char *bus, unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next) {
-               if (dev->class == class_code) {
-                       if (curr == index) {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-
 int pcibios_present(void)
 {
        return 1;
@@ -2248,6 +2198,11 @@ es1888_init(void)
 }
 #endif /* CONFIG_ALPHA_MIATA */
 
+__initfunc(char *pcibios_setup(char *str))
+{
+       return str;
+}
+
 #ifdef CONFIG_ALPHA_SRM_SETUP
 void reset_for_srm(void)
 {
index c89536143f1683fbd49b2d55bcfdad3e38e97ef8..57fae7d8726a9167e945c055b62ffbfdc9825566 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
index 4307a191e443879171b46d9624b0fd7dce25854d..a0b8aea8de08946a55df78feeb3969ebcf5030be 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 
 #include <asm/ptrace.h>
index 3c3736b151270105c811f629d9efd2df9150dd70..8d61cfe7e76d0f04e4ea93ec76d7a477b0dec647 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
index c776414ce31ab24a21e5b6feb98e7563e3bfd91d..de3814b66a9978574685bdad876ba75f893964e3 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/config.h> /* CONFIG_ALPHA_RUFFIAN. */
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
index 6724372feeb51805a07cda9ea3c813a4a1f30d7f..052a6f1a76f4a75d55a8c7e12ec321d63ac0b06b 100644 (file)
@@ -3,8 +3,6 @@
  */
 #include <linux/kernel.h>
 
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
index a75998d7e939129ab19d05db826934eba62a98cb..b0284b032a7563b08bfcc494bdc2bc2066e7f7b0 100644 (file)
@@ -5,8 +5,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
index ffa16657201f86fb9bdd74ec768a39f3102a07c9..69ca71404f567e463841a3c26c8fc8e522a1aa40 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
index 5c4d34e74dc7a519427cd1ea1e52c9f7161cd48b..3d0fdde8910f432956101b0fb4651b17dad90326 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
index 578a2b4d647e8ff57a9dfff7cf0991cd48649a26..3e89085e344d7cafadf0cf4987b546c097a2380f 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * bios32.c - BIOS32, PCI BIOS functions.
+ * bios32.c - Low-Level PCI Access
  *
- * $Id: bios32.c,v 1.17 1997/11/16 11:03:41 mj Exp $
+ * $Id: bios32.c,v 1.26 1998/02/18 15:21:09 mj Exp $
  *
  * Sponsored by
  *     iX Multiuser Multitasking Magazine
  *
  * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
  *     and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 
@@ -91,8 +92,6 @@
 
 struct pci_access {
     int pci_present;
-    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
-    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
     int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
     int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
     int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
@@ -108,8 +107,6 @@ static int pci_stub(void)
 
 static struct pci_access pci_access_none = {
        0,                              /* No PCI present */
-       (void *) pci_stub,              /* No functions implemented */
-       (void *) pci_stub,
        (void *) pci_stub,
        (void *) pci_stub,
        (void *) pci_stub,
@@ -125,18 +122,6 @@ int pcibios_present(void)
        return access_pci->pci_present;
 }
 
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-       unsigned char *bus, unsigned char *device_fn)
-{
-       return access_pci->find_class(class_code, index, bus, device_fn);
-}
-
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-       unsigned short index, unsigned char *bus, unsigned char *device_fn)
-{
-       return access_pci->find_device(vendor, device_id, index, bus, device_fn);
-}
-
 int pcibios_read_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
 {
@@ -147,6 +132,9 @@ int pcibios_read_config_byte (unsigned char bus,
 #ifdef __SMP__
 /*
  * IOAPICs can take PCI IRQs directly, lets first check the mptable:
+ *
+ * This can go away once nobody probes the irq this way,
+ * but uses the PCI tables instead.
  */
        if (where == PCI_INTERRUPT_LINE) {
                int irq;
@@ -205,60 +193,17 @@ int pcibios_write_config_dword (unsigned char bus,
        return access_pci->write_config_dword(bus, device_fn, where, value);
 }
 
-/*
- * Direct access to PCI hardware...
- */
-
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-
-#ifdef CONFIG_PCI_DIRECT
+static unsigned int pci_probe = ~0;
 
-static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
-                          unsigned short index, unsigned char *bus,
-                          unsigned char *devfn)
-{
-    unsigned int curr = 0;
-    struct pci_dev *dev;
-
-    for (dev = pci_devices; dev; dev = dev->next) {
-       if (dev->vendor == vendor && dev->device == device_id) {
-           if (curr == index) {
-               *devfn = dev->devfn;
-               *bus = dev->bus->number;
-               return PCIBIOS_SUCCESSFUL;
-           }
-           ++curr;
-       }
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
 
 /*
- * Given the class, find the n'th instance of that device
- * in the system.
+ * Direct access to PCI hardware...
  */
 
-static int pci_direct_find_class (unsigned int class_code, unsigned short index,
-                         unsigned char *bus, unsigned char *devfn)
-{
-    unsigned int curr = 0;
-    struct pci_dev *dev;
-
-    for (dev = pci_devices; dev; dev = dev->next) {
-       if (dev->class == class_code) {
-           if (curr == index) {
-               *devfn = dev->devfn;
-               *bus = dev->bus->number;
-               return PCIBIOS_SUCCESSFUL;
-           }
-           ++curr;
-       }
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#ifdef CONFIG_PCI_DIRECT
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
@@ -346,8 +291,6 @@ static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device
 
 static struct pci_access pci_direct_conf1 = {
       1,
-      pci_direct_find_device,
-      pci_direct_find_class,
       pci_conf1_read_config_byte,
       pci_conf1_read_config_word,
       pci_conf1_read_config_dword,
@@ -458,8 +401,6 @@ static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device
 
 static struct pci_access pci_direct_conf2 = {
       1,
-      pci_direct_find_device,
-      pci_direct_find_class,
       pci_conf2_read_config_byte,
       pci_conf2_read_config_word,
       pci_conf2_read_config_dword,
@@ -470,39 +411,43 @@ static struct pci_access pci_direct_conf2 = {
 
 __initfunc(static struct pci_access *pci_check_direct(void))
 {
-    unsigned int tmp;
-    unsigned long flags;
+       unsigned int tmp;
+       unsigned long flags;
 
-    save_flags(flags); cli();
+       save_flags(flags); cli();
+
+       /*
+        * Check if configuration type 1 works.
+        */
+       if (pci_probe & PCI_PROBE_CONF1) {
+               outb (0x01, 0xCFB);
+               tmp = inl (0xCF8);
+               outl (0x80000000, 0xCF8);
+               if (inl (0xCF8) == 0x80000000) {
+                       outl (tmp, 0xCF8);
+                       restore_flags(flags);
+                       printk("PCI: Using configuration type 1\n");
+                       return &pci_direct_conf1;
+               }
+               outl (tmp, 0xCF8);
+       }
+
+       /*
+        * Check if configuration type 2 works.
+        */
+       if (pci_probe & PCI_PROBE_CONF2) {
+               outb (0x00, 0xCFB);
+               outb (0x00, 0xCF8);
+               outb (0x00, 0xCFA);
+               if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
+                       restore_flags(flags);
+                       printk("PCI: Using configuration type 2\n");
+                       return &pci_direct_conf2;
+               }
+       }
 
-    /*
-     * Check if configuration type 1 works.
-     */
-    outb (0x01, 0xCFB);
-    tmp = inl (0xCF8);
-    outl (0x80000000, 0xCF8);
-    if (inl (0xCF8) == 0x80000000) {
-       outl (tmp, 0xCF8);
-       restore_flags(flags);
-       printk("PCI: Using configuration type 1\n");
-       return &pci_direct_conf1;
-    }
-    outl (tmp, 0xCF8);
-
-    /*
-     * Check if configuration type 2 works.
-     */
-    outb (0x00, 0xCFB);
-    outb (0x00, 0xCF8);
-    outb (0x00, 0xCFA);
-    if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
        restore_flags(flags);
-       printk("PCI: Using configuration type 2\n");
-       return &pci_direct_conf2;
-    }
-    restore_flags(flags);
-    printk("PCI: PCI hardware not found (i.e., not present or not supported).\n");
-    return NULL;
+       return NULL;
 }
 
 #endif
@@ -599,7 +544,7 @@ static unsigned long bios32_service(unsigned long service)
                        printk("bios32_service(0x%lx): not present\n", service);
                        return 0;
                default: /* Shouldn't happen */
-                       printk("bios32_service(0x%lx): returned 0x%x, mail drew@colorado.edu\n",
+                       printk("bios32_service(0x%lx): returned 0x%x, report to <mj@ucw.cz>.\n",
                                service, return_code);
                        return 0;
        }
@@ -642,7 +587,7 @@ __initfunc(static int check_pcibios(void))
                if (present_status || (signature != PCI_SIGNATURE)) {
                        printk ("PCI: %s: BIOS32 Service Directory says PCI BIOS is present,\n"
                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
-                               "       and signature of 0x%08lx (%c%c%c%c).  Mail drew@Colorado.EDU\n",
+                               "       and signature of 0x%08lx (%c%c%c%c).  Report to <mj@ucw.cz>.\n",
                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
                                present_status, signature,
                                (char) (signature >>  0), (char) (signature >>  8),
@@ -660,6 +605,8 @@ __initfunc(static int check_pcibios(void))
        return 0;
 }
 
+#if 0  /* Not used */
+
 static int pci_bios_find_class (unsigned int class_code, unsigned short index,
        unsigned char *bus, unsigned char *device_fn)
 {
@@ -709,6 +656,8 @@ static int pci_bios_find_device (unsigned short vendor, unsigned short device_id
        return (int) (ret & 0xff00) >> 8;
 }
 
+#endif
+
 static int pci_bios_read_config_byte(unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
 {
@@ -847,8 +796,6 @@ static int pci_bios_write_config_dword (unsigned char bus,
 
 static struct pci_access pci_bios_access = {
       1,
-      pci_bios_find_device,
-      pci_bios_find_class,
       pci_bios_read_config_byte,
       pci_bios_read_config_word,
       pci_bios_read_config_dword,
@@ -887,18 +834,14 @@ __initfunc(static struct pci_access *pci_find_bios(void))
                if (sum != 0)
                        continue;
                if (check->fields.revision != 0) {
-                       printk("PCI: unsupported BIOS32 revision %d at 0x%p, mail drew@colorado.edu\n",
+                       printk("PCI: unsupported BIOS32 revision %d at 0x%p, report to <mj@ucw.cz>\n",
                                check->fields.revision, check);
                        continue;
                }
                printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
                if (check->fields.entry >= 0x100000) {
-#ifdef CONFIG_PCI_DIRECT
-                       printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n");
-                       return pci_check_direct();
-#else
                        printk("PCI: BIOS32 entry in high memory, cannot use.\n");
-#endif
+                       return NULL;
                } else {
                        bios32_entry = check->fields.entry;
                        printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
@@ -909,39 +852,128 @@ __initfunc(static struct pci_access *pci_find_bios(void))
                break;  /* Hopefully more than one BIOS32 cannot happen... */
        }
 
+       /*
+        * If we were told to use the PCI BIOS and it's not present, avoid
+        * touching the hardware.
+        */
+       pci_probe = 0;
        return NULL;
 }
 
 #endif
 
 /*
- * No fixup function used.
+ * Arch-dependent fixups.
  */
 
-__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
+__initfunc(void pcibios_fixup(void))
 {
-    return mem_start;
+       struct pci_dev *dev;
+       int i, has_io;
+
+       for(dev = pci_devices; dev; dev=dev->next) {
+               /*
+                * There are probably some buggy BIOSes that forget to assign I/O port
+                * addresses to several devices. We probably should assign new addresses
+                * to such devices, but we need to gather some information first. [mj]
+                */
+               has_io = 0;
+               for(i=0; i<6; i++) {
+                       unsigned long a = dev->base_address[i];
+                       if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+                               has_io = 1;
+                               a &= PCI_BASE_ADDRESS_IO_MASK;
+                               if (!a || a == PCI_BASE_ADDRESS_IO_MASK)
+                                       printk(KERN_WARNING "PCI: BIOS forgot to assign address #%d to device %02x:%02x,"
+                                               " please report to <mj@ucw.cz>\n", i, dev->bus->number, dev->devfn);
+                       }
+               }
+               /*
+                * Check if the I/O space access is allowed. If not, moan loudly. [mj]
+                */
+               if (has_io) {
+                       unsigned short cmd;
+                       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+                       if (!(cmd & PCI_COMMAND_IO))
+                               printk(KERN_WARNING "PCI: BIOS forgot to enable I/O for device %02x:%02x,"
+                                       " please report to <mj@ucw.cz>\n", dev->bus->number, dev->devfn);
+               }
+#ifdef __SMP__
+               /*
+                * Recalculate IRQ numbers if we use the I/O APIC
+                */
+               {
+               unsigned char pin;
+               int irq;
+
+               pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+               if (pin) {
+                       pin--;          /* interrupt pins are numbered starting from 1 */
+                       irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
+                       if (irq >= 0) {
+                               printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+                                       dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+                               dev->irq = irq;
+                               }
+               }
+               }
+#endif
+               /*
+                * Fix out-of-range IRQ numbers.
+                */
+               if (dev->irq >= NR_IRQS)
+                       dev->irq = 0;
+       }
 }
 
 /*
  * Initialization. Try all known PCI access methods.
  */
 
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_init(void))
 {
        struct pci_access *a = NULL;
 
 #ifdef CONFIG_PCI_BIOS
-       a = pci_find_bios();
-#else
-#ifdef CONFIG_PCI_DIRECT
-       a = pci_check_direct();
-#else
-#error "You need to set CONFIG_PCI_BIOS or CONFIG_PCI_DIRECT if you want PCI support."
+       if (pci_probe & PCI_PROBE_BIOS)
+               a = pci_find_bios();
 #endif
+#ifdef CONFIG_PCI_DIRECT
+       if (!a && (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)))
+               a = pci_check_direct();
 #endif
        if (a)
                access_pci = a;
+}
+
+#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT)
+#error PCI configured with neither PCI BIOS or PCI direct access support.
+#endif
 
-       return memory_start;
+__initfunc(char *pcibios_setup(char *str))
+{
+       if (!strncmp(str, "off", 3)) {
+               pci_probe = 0;
+               return str+3;
+       }
+#ifdef CONFIG_PCI_BIOS
+       else if (!strncmp(str, "bios", 4)) {
+               pci_probe = PCI_PROBE_BIOS;
+               return str+4;
+       } else if (!strncmp(str, "nobios", 6)) {
+               pci_probe &= ~PCI_PROBE_BIOS;
+               return str+6;
+       }
+#endif
+#ifdef CONFIG_PCI_DIRECT
+       else if (!strncmp(str, "conf1", 5)) {
+               pci_probe = PCI_PROBE_CONF1;
+               return str+5;
+       }
+       else if (!strncmp(str, "conf2", 5)) {
+               pci_probe = PCI_PROBE_CONF2;
+               return str+5;
+       }
+#endif
+       return str;
 }
index d2837d648e3cfad9020863fa32a2242e8fe4e518..a5ec92210f2a36d2d55951147ec32dd829bbd42f 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/in6.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
-#include <linux/pci.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -64,13 +63,14 @@ EXPORT_SYMBOL(__generic_copy_to_user);
 EXPORT_SYMBOL(strlen_user);
 
 #ifdef __SMP__
-EXPORT_SYMBOL(apic_reg);       /* Needed internally for the I386 inlines */
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL_NOVERS(kernel_flag);
 EXPORT_SYMBOL_NOVERS(active_kernel_processor);
 EXPORT_SYMBOL(smp_invalidate_needed);
 EXPORT_SYMBOL_NOVERS(__lock_kernel);
 EXPORT_SYMBOL(lk_lockmsg);
+EXPORT_SYMBOL(__cpu_logical_map);
+EXPORT_SYMBOL(smp_num_cpus);
 
 /* Global SMP irq stuff */
 EXPORT_SYMBOL(synchronize_irq);
@@ -97,7 +97,3 @@ EXPORT_SYMBOL(mca_set_adapter_procfn);
 EXPORT_SYMBOL(mca_isenabled);
 EXPORT_SYMBOL(mca_isadapter);
 #endif
-
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
-#endif
index 219e7f853e05d2bf1fc9378c26b88d2b17ff568d..6e422614e7efb5aecf85eff1b5ad1fb4c2f3f9d1 100644 (file)
 
 #include "irq.h"
 
-#define IO_APIC_BASE 0xfec00000
-
 /*
  * volatile is justified in this case, it might change
  * spontaneously, GCC should not cache it
  */
-volatile unsigned int * io_apic_reg = NULL;
+#define IO_APIC_BASE ((volatile int *)0xfec00000)
 
 /*
  * The structure of the IO-APIC:
@@ -96,17 +94,19 @@ int nr_ioapic_registers = 0;                        /* # of IRQ routing registers */
 int mp_irq_entries = 0;                                /* # of MP IRQ source entries */
 struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
                                                /* MP IRQ source entries */
+int mpc_default_type = 0;                      /* non-0 if default (table-less)
+                                                  MP configuration */
 
 unsigned int io_apic_read (unsigned int reg)
 {
-       *io_apic_reg = reg;
-       return *(io_apic_reg+4);
+       *IO_APIC_BASE = reg;
+       return *(IO_APIC_BASE+4);
 }
 
 void io_apic_write (unsigned int reg, unsigned int value)
 {
-       *io_apic_reg = reg;
-       *(io_apic_reg+4) = value;
+       *IO_APIC_BASE = reg;
+       *(IO_APIC_BASE+4) = value;
 }
 
 void enable_IO_APIC_irq (unsigned int irq)
@@ -256,7 +256,7 @@ void setup_IO_APIC_irqs (void)
                /*
                 * PCI IRQ redirection. Yes, limits are hardcoded.
                 */
-               if ((i>=16) && (i<=19)) {
+               if ((i>=16) && (i<=23)) {
                        if (pirq_entries[i-16] != -1) {
                                if (!pirq_entries[i-16]) {
                                        printk("disabling PIRQ%d\n", i-16);
@@ -516,16 +516,16 @@ void print_IO_APIC (void)
 static void init_sym_mode (void)
 {
        printk("enabling Symmetric IO mode ... ");
-               outb (0x70, 0x22);
-               outb (0x01, 0x23);
+               outb_p (0x70, 0x22);
+               outb_p (0x01, 0x23);
        printk("...done.\n");
 }
 
 void init_pic_mode (void)
 {
        printk("disabling Symmetric IO mode ... ");
-               outb (0x70, 0x22);
-               outb (0x00, 0x23);
+               outb_p (0x70, 0x22);
+               outb_p (0x00, 0x23);
        printk("...done.\n");
 }
 
@@ -579,17 +579,85 @@ static int ioapic_blacklisted (void)
        return in_ioapic_list(ioapic_blacklist);
 }
 
+static void setup_ioapic_id (void)
+{
+       struct IO_APIC_reg_00 reg_00;
 
-void setup_IO_APIC (void)
+       /*
+        * 'default' mptable configurations mean a hardwired setup,
+        * 2 CPUs, 16 APIC registers. IO-APIC ID is usually set to 0,
+        * setting it to ID 2 should be fine.
+        */
+
+       /*
+        * Sanity check, is ID 2 really free? Every APIC in the
+        * system must have a unique ID or we get lots of nice
+        * 'stuck on smp_invalidate_needed IPI wait' messages.
+        */
+       if (cpu_present_map & (1<<0x2))
+               panic("APIC ID 2 already used");
+
+       /*
+        * set the ID
+        */
+       *(int *)&reg_00 = io_apic_read(0);
+       printk("... changing IO-APIC physical APIC ID to 2 ...\n");
+       reg_00.ID = 0x2;
+       io_apic_write(0, *(int *)&reg_00);
+
+       /*
+        * Sanity check
+        */
+       *(int *)&reg_00 = io_apic_read(0);
+       if (reg_00.ID != 0x2)
+               panic("could not set ID");
+}
+
+static void construct_default_ISA_mptable (void)
 {
-       int i;
+       int i, pos=0;
+
+       for (i=0; i<16; i++) {
+               if (!IO_APIC_IRQ(i))
+                       continue;
+
+               mp_irqs[pos].mpc_irqtype = 0;
+               mp_irqs[pos].mpc_irqflag = 0;
+               mp_irqs[pos].mpc_srcbus = 0;
+               mp_irqs[pos].mpc_srcbusirq = i;
+               mp_irqs[pos].mpc_dstapic = 0;
+               mp_irqs[pos].mpc_dstirq = i;
+               pos++;
+       }
+       mp_irq_entries = pos;
+       mp_bus_id_to_type[0] = MP_BUS_ISA;
+
        /*
-        *      Map the IO APIC into kernel space
+        * MP specification 1.4 defines some extra rules for default
+        * configurations, fix them up here:
         */
+       
+       switch (mpc_default_type)
+       {
+               case 2:
+                       break;
+               default:
+               /*
+                * pin 2 is IRQ0:
+                */
+                       mp_irqs[0].mpc_dstirq = 2;
+       }
 
-       printk("mapping IO APIC from standard address.\n");
-       io_apic_reg = ioremap_nocache(IO_APIC_BASE,4096);
-       printk("new virtual address: %p.\n",io_apic_reg);
+       setup_ioapic_id();
+}
+                       
+void setup_IO_APIC (void)
+{
+       int i;
+
+       if (!pirqs_enabled)
+               for (i=0; i<MAX_PIRQS; i++)
+                       pirq_entries[i]=-1;
 
        init_sym_mode();
        {
@@ -605,12 +673,6 @@ void setup_IO_APIC (void)
        for (i=0; i<nr_ioapic_registers; i++)
                clear_IO_APIC_irq (i);
 
-#if DEBUG_1
-       for (i=0; i<16; i++)
-               if (IO_APIC_IRQ(i))
-                       setup_IO_APIC_irq_ISA_default (i);
-#endif
-
        /*
         * the following IO-APIC's can be enabled:
         *
@@ -634,7 +696,18 @@ void setup_IO_APIC (void)
                io_apic_irqs = 0;
        }
 
+       /*
+        * If there are no explicit mp irq entries: it's either one of the
+        * default configuration types or we are broken. In both cases it's
+        * fine to set up most of the low 16 IOAPIC pins to ISA defaults.
+        */
+       if (!mp_irq_entries) {
+               printk("no explicit IRQ entries, using default mptable\n");
+               construct_default_ISA_mptable();
+       }
+
        init_IO_APIC_traps();
+
        setup_IO_APIC_irqs ();
 
        if (!timer_irq_works ()) {
@@ -644,9 +717,9 @@ void setup_IO_APIC (void)
                printk("..MP-BIOS bug: i8254 timer not connected to IO-APIC\n");
                printk("..falling back to 8259A-based timer interrupt\n");
        }
-
-       printk("nr of MP irq sources: %d.\n", mp_irq_entries);
-       printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
+       printk("nr of MP irq sources: %d.\n", mp_irq_entries);
+       printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
        print_IO_APIC();
 }
 
index 9ca377128c89de41b943b7c15fbd7f919a38602f..7a7a6caa549880de1939f35deb72be0f0ad36cca 100644 (file)
@@ -128,9 +128,6 @@ unsigned char boot_cpu_id = 0;                              /* Processor that is doing the boot up                  */
 static int smp_activated = 0;                          /* Tripped once we need to start cross invalidating     */
 int apic_version[NR_CPUS];                             /* APIC version number                                  */
 static volatile int smp_commenced=0;                   /* Tripped when we start scheduling                     */
-unsigned long apic_addr = 0xFEE00000;                  /* Address of APIC (defaults to 0xFEE00000)             */
-unsigned long nlong = 0;                               /* dummy used for apic_reg address + 0x20               */
-unsigned char *apic_reg=((unsigned char *)(&nlong))-0x20;/* Later set to the ioremap() of the APIC             */
 unsigned long apic_retval;                             /* Just debugging the assembler..                       */
 
 static volatile unsigned char smp_cpu_in_msg[NR_CPUS]; /* True if this processor is sending an IPI             */
@@ -150,6 +147,7 @@ const char lk_lockmsg[] = "lock from interrupt context at %p\n";
 int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
 extern int mp_irq_entries;
 extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+extern int mpc_default_type;
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
 int mp_current_pci_id = 0;
 
@@ -272,8 +270,9 @@ __initfunc(static int smp_read_mpc(struct mp_config_table *mpc))
 
        printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
 
-       /* set the local APIC address */
-       apic_addr = (unsigned long)phys_to_virt((unsigned long)mpc->mpc_lapic);
+       /* check the local APIC address */
+       if ((char *)phys_to_virt((unsigned long)mpc->mpc_lapic) != APIC_BASE)
+               panic("unexpected APIC address");
 
        /*
         *      Now process the configuration blocks.
@@ -454,7 +453,7 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length))
                                         */
                        
                                        cfg=pg0[0];
-                                       pg0[0] = (apic_addr | 7);
+                                       pg0[0] = ((unsigned long)APIC_BASE | 7);
                                        local_flush_tlb();
 
                                        boot_cpu_id = GET_APIC_ID(*((volatile unsigned long *) APIC_ID));
@@ -477,6 +476,14 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length))
                                        cpu_present_map=3;
                                        num_processors=2;
                                        printk("I/O APIC at 0xFEC00000.\n");
+
+                                       /*
+                                        * Save the default type number, we
+                                        * need it later to set the IO-APIC
+                                        * up properly:
+                                        */
+                                       mpc_default_type = mpf->mpf_feature1;
+
                                        printk("Bus #0 is ");
                                }
                                switch(mpf->mpf_feature1)
@@ -525,11 +532,6 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length))
                                if(mpf->mpf_physptr)
                                        smp_read_mpc((void *)mpf->mpf_physptr);
 
-                               /*
-                                *      Now that the boot CPU id is known,
-                                *      set some other information about it.
-                                */
-                               nlong = boot_cpu_id<<24;        /* Dummy 'self' for bootup */
                                __cpu_logical_map[0] = boot_cpu_id;
                                global_irq_holder = boot_cpu_id;
                                current->processor = boot_cpu_id;
@@ -951,15 +953,6 @@ __initfunc(void smp_boot_cpus(void))
                printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
        }
 
-       /*
-        *      Map the local APIC into kernel space
-        */
-
-       apic_reg = ioremap(apic_addr,4096);
-
-       if(apic_reg == NULL)
-               panic("Unable to map local apic.");
-
 #ifdef SMP_DEBUG
        {
                int reg;
@@ -1497,7 +1490,7 @@ asmlinkage void smp_stop_cpu_interrupt(void)
 /*
  * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
  * per second. We assume that the caller has already set up the local
- * APIC at apic_addr.
+ * APIC.
  *
  * The APIC timer is not exactly sync with the external timer chip, it
  * closely follows bus clocks.
index ef3ac57f4d052b6459580eb4df4e3bfeea171d0b..4b5f7bf19adcb25732e6bf5100171509755c040a 100644 (file)
@@ -174,29 +174,29 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
  * It may also hold the MP configuration table when we are booting SMP.
  */
 #ifdef __SMP__
-       if (!smp_scan_config(0x0,0x400))        /* Scan the bottom 1K for a signature */
-       {
+       /*
+        * FIXME: Linux assumes you have 640K of base ram..
+        * this continues the error...
+        *
+        * 1) Scan the bottom 1K for a signature
+        * 2) Scan the top 1K of base RAM
+        * 3) Scan the 64K of bios
+        */
+       if (!smp_scan_config(0x0,0x400) &&
+           !smp_scan_config(639*0x400,0x400) &&
+           !smp_scan_config(0xF0000,0x10000)) {
                /*
-                *      FIXME: Linux assumes you have 640K of base ram.. this continues
-                *      the error...
+                * If it is an SMP machine we should know now, unless the
+                * configuration is in an EISA/MCA bus machine with an
+                * extended bios data area. 
+                *
+                * there is a real-mode segmented pointer pointing to the
+                * 4K EBDA area at 0x40E, calculate and scan it here:
                 */
-               if (!smp_scan_config(639*0x400,0x400))  /* Scan the top 1K of base RAM */
-               {
-                       if(!smp_scan_config(0xF0000,0x10000))   /* Scan the 64K of bios */
-                       {
-                               /*
-                                *      If it is an SMP machine we should know now, unless the configuration
-                                *      is in an EISA/MCA bus machine with an extended bios data area. 
-                                */
-                
-                               address = *(unsigned short *)phys_to_virt(0x40E); /* EBDA */
-                               address<<=4;    /* Real mode segments to physical */
-                               smp_scan_config(address, 0x1000);       /* Scan the EBDA */
-                       }
-               }
+               address = *(unsigned short *)phys_to_virt(0x40E);
+               address<<=4;
+               smp_scan_config(address, 0x1000);
        }
-                       
-/*     smp_alloc_memory(8192); */
 #endif
        start_mem = PAGE_ALIGN(start_mem);
        address = PAGE_OFFSET;
@@ -255,7 +255,50 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
                        address += PAGE_SIZE;
                }
        }
+#ifdef __SMP__
+{
+       pte_t pte;
+       unsigned long apic_area = (unsigned long)APIC_BASE;
+
+       pg_dir = swapper_pg_dir + ((apic_area) >> PGDIR_SHIFT);
+       memset((void *)start_mem, 0, PAGE_SIZE);
+       pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
+       start_mem += PAGE_SIZE;
+
+       if (smp_found_config) {
+               /*
+                * Map the local APIC to FEE00000.
+                */
+               pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+               pte = mk_pte(__va(apic_area), PAGE_KERNEL);
+               set_pte(pg_table, pte);
+
+               /*
+                * Map the IO-APIC to FEC00000.
+                */
+               apic_area = 0xFEC00000; /*(unsigned long)IO_APIC_BASE;*/
+               pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+               pte = mk_pte(__va(apic_area), PAGE_KERNEL);
+               set_pte(pg_table, pte);
+       } else {
+               /*
+                * No local APIC but we are compiled SMP ... set up a
+                * fake all zeroes page to simulate the local APIC.
+                */
+               pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+               pte = mk_pte(start_mem, PAGE_KERNEL);
+               memset((void *)start_mem, 0, PAGE_SIZE);
+               start_mem += PAGE_SIZE;
+               set_pte(pg_table, pte);
+       }
+
+       local_flush_tlb();
+       printk("IO APIC ID: %d\n", *(int *)0xFEC00000);
+       printk("APIC ID: %d\n", *(int *)0xFEE00000);
+}
+#endif
        local_flush_tlb();
+
        return free_area_init(start_mem, end_mem);
 }
 
index 6f7374fd27d6f55487a84bf81b9559ce1fc138eb..71a57b73ec8612c0118106bca8db8fc565170b40 100644 (file)
@@ -5,7 +5,6 @@
  *
  * MIPS implementation of PCI BIOS services for PCI support.
  */
-#include <linux/bios32.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -35,53 +34,6 @@ int pcibios_present (void)
        return pci_ops != NULL;
 }
 
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-                        unsigned short index, unsigned char *bus,
-                        unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next) {
-               if (dev->vendor == vendor && dev->device == device_id) {
-                       if (curr == index) {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-                       unsigned char *bus, unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next) {
-               if (dev->class == class_code) {
-                       if (curr == index) {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
 /*
  * The functions below are machine specific and must be reimplented for
  * each PCI chipset configuration.  We just run the hook to the machine
@@ -129,4 +81,9 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
        return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
 }
 
+__initfunc(char *pcibios_setup(char *str))
+{
+       return str;
+}
+
 #endif /* defined(CONFIG_PCI) */
index 8a8016e706bcee90cc3e98d2ede5397f0154a6c7..4fe83bed0e28097325d4217b6d7dd9c80e85baa3 100644 (file)
@@ -6,7 +6,6 @@
  * SNI specific PCI support for RM200/RM300.
  */
 #include <linux/config.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/types.h>
index 99226e40a5e65974df6c41601a71694bddf2e0d7..dffd31d917a14e50922e90e51c5e2d7ddc01dbce 100644 (file)
@@ -34,6 +34,9 @@ else
           fi
         fi
       fi
+      if [ "$CONFIG_CHRP" = "y" ]; then
+          bool '   WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
+      fi
     fi
     bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
     if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
index 39786eb97dc7b18278a197779e45ed744e1ffecb..3fd1526e4acfecdb6e12cbc8aed6ec59aa9d84a8 100644 (file)
@@ -155,6 +155,14 @@ ifeq ($(CONFIG_BLK_DEV_NS87415),y)
 L_OBJS += ns87415.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CMD646),y)
+L_OBJS += cmd646.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
+L_OBJS += sl82c105.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDEDISK),y)
 L_OBJS += ide-disk.o
 else
diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c
new file mode 100644 (file)
index 0000000..aa9248c
--- /dev/null
@@ -0,0 +1,20 @@
+/* $Id: cmd646.c,v 1.1 1998/03/15 13:29:10 ecd Exp $
+ * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines
+ *
+ * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#include <linux/pci.h>
+#include "ide.h"
+
+__initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
+{
+#ifdef __sparc_v9__
+       struct pci_dev *dev = hwif->pci_dev;
+       unsigned char mrdmode;
+
+       (void) pci_read_config_byte(dev, 0x71, &mrdmode);
+       mrdmode &= ~(0x30);
+       (void) pci_write_config_byte(dev, 0x71, mrdmode);
+#endif
+}
index faf6ceaf793946c18ecf76c306566c2a22a13907..ff711db0194dc7c67ab6966389b411cf3aab3763 100644 (file)
@@ -70,7 +70,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -84,6 +84,7 @@
  */
 const char *good_dma_drives[] = {"Micropolis 2112A",
                                 "CONNER CTMA 4000",
+                                "ST34342A",
                                 NULL};
 
 /*
@@ -140,7 +141,7 @@ int ide_build_dmatable (ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        struct buffer_head *bh = rq->bh;
-       unsigned long size, addr, *table = HWIF(drive)->dmatable;
+       unsigned int size, addr, *table = (unsigned int *)HWIF(drive)->dmatable;
 #ifdef CONFIG_BLK_DEV_TRM290
        unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
 #else
@@ -183,7 +184,7 @@ int ide_build_dmatable (ide_drive_t *drive)
                                printk("%s: DMA table too small\n", drive->name);
                                return 0; /* revert to PIO for this request */
                        } else {
-                               unsigned long xcount, bcount = 0x10000 - (addr & 0xffff);
+                               unsigned int xcount, bcount = 0x10000 - (addr & 0xffff);
                                if (bcount > size)
                                        bcount = size;
                                *table++ = cpu_to_le32(addr);
@@ -288,7 +289,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
        }
 }
 
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) /* __init */
+__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
 {
        static unsigned long dmatable = 0;
        static unsigned leftover = 0;
@@ -320,74 +321,39 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
                if (hwif->chipset != ide_trm290) {
                        byte dma_stat = inb(dma_base+2);
                        printk(", BIOS settings: %s:%s, %s:%s",
-                        hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
-                        hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
+                              hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
+                              hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
                }
                printk("\n");
        }
 }
 
-/* The next two functions were stolen from cmd640.c, with a few modifications  */
-
-__initfunc(static void write_pcicfg_dword (byte fn, unsigned short reg, long val))
-{
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-  outl_p((reg & 0xfc) | ((fn * 0x100) + 0x80000000), 0xcf8);
-  outl_p(val, (reg & 3) | 0xcfc);
-  restore_flags(flags);
-}
-
-__initfunc(static long read_pcicfg_dword (byte fn, unsigned short reg))
-{
-  long b;
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-  outl_p((reg & 0xfc) | ((fn * 0x100) + 0x80000000), 0xcf8);
-  b = inl_p((reg & 3) | 0xcfc);
-  restore_flags(flags);
-  return b;
-}
-
 /*
  * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  */
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) /* __init */
+__initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name))
 {
        unsigned long new, dma_base = 0;
-       byte bus = hwif->pci_bus, fn = hwif->pci_fn;
 
        if (hwif->mate && hwif->mate->dma_base) {
                dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
-       } else if (pcibios_read_config_dword(bus, fn, 0x20, (unsigned int *)&dma_base)) {
-               printk("%s: failed to read dma_base\n", name);
-               dma_base = 0;
-       } else if ((dma_base &= ~0xf) == 0 || dma_base == ~0xf) {
-               printk("%s: dma_base is invalid (0x%04lx, BIOS problem)\n", name, dma_base);
-               new = ide_find_free_region(16 + extra);
-               hwif->no_autodma = 1;   /* default DMA off if we had to configure it here */
-               if (new) {
-                       printk("%s: setting dma_base to 0x%04lx\n", name, new);
-                       new |= 1;
-                       (void) pcibios_write_config_dword(bus, fn, 0x20, new);
-                       dma_base = 0;
-                       (void) pcibios_read_config_dword(bus, fn, 0x20, (unsigned int *)&dma_base);
-                       if (dma_base != new) {
-                               if (bus == 0) {
-                                       printk("%s: operation failed, bypassing BIOS to try again\n", name);
-                                       write_pcicfg_dword(fn, 0x20, new);
-                                       dma_base = read_pcicfg_dword(fn, 0x20);
-                               }
+       } else {
+               dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+               if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) {
+                       printk("%s: dma_base is invalid (0x%04lx, BIOS problem), please report to <mj@ucw.cz>\n", name, dma_base);
+                       new = ide_find_free_region(16 + extra);
+                       hwif->no_autodma = 1;   /* default DMA off if we had to configure it here */
+                       if (new) {
+                               printk("%s: setting dma_base to 0x%04lx\n", name, new);
+                               new |= PCI_BASE_ADDRESS_SPACE_IO;
+                               (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, new);
+                               dma_base = 0;
+                               (void) pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, (unsigned int *) &dma_base);
                                if (dma_base != new) {
-                                       printk("%s: operation failed, DMA disabled\n", name);
+                                       printk("%s: Operation failed, DMA disabled\n", name);
                                        dma_base = 0;
                                }
                        }
-                       dma_base &= ~0xf;
                }
        }
        if (dma_base) {
@@ -401,4 +367,3 @@ unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *
        }
        return dma_base;
 }
-
index 6353c80207dcb85d2b52bfacd7ef08ee36df437d..01d59a5cc8df693b1a8736490431f1b1be01cde7 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -67,6 +67,13 @@ extern void ide_init_ns87415(ide_hwif_t *);
 #define INIT_NS87415   IDE_IGNORE
 #endif
 
+#ifdef CONFIG_BLK_DEV_CMD646
+extern void ide_init_cmd646(ide_hwif_t *);
+#define INIT_CMD646    &ide_init_cmd646
+#else
+#define INIT_CMD646    IDE_IGNORE
+#endif
+
 #ifdef CONFIG_BLK_DEV_RZ1000
 extern void ide_init_rz1000(ide_hwif_t *);
 #define INIT_RZ1000    &ide_init_rz1000
@@ -99,7 +106,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_CMD640,  "CMD640",       IDE_IGNORE,     {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
        {DEVID_NS87410, "NS87410",      NULL,           {{0x43,0x08,0x08}, {0x47,0x08,0x08}} },
        {DEVID_SIS5513, "SIS5513",      NULL,           {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} },
-       {DEVID_CMD646,  "CMD646",       NULL,           {{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
+       {DEVID_CMD646,  "CMD646",       INIT_CMD646,    {{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
        {DEVID_HT6565,  "HT6565",       NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
        {DEVID_OPTI621, "OPTI621",      INIT_OPTI621,   {{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
        {DEVID_OPTI621X,"OPTI621X",     INIT_OPTI621,   {{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
@@ -137,7 +144,7 @@ unsigned long ide_find_free_region (unsigned short size) /* __init */
  * Match a PCI IDE port against an entry in ide_hwifs[],
  * based on io_base port if possible.
  */
-__initfunc(static ide_hwif_t *ide_match_hwif (unsigned int io_base, const char *name))
+__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char *name))
 {
        int h;
        ide_hwif_t *hwif;
@@ -163,7 +170,7 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned int io_base, const char *
                if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
                        if (hwif->chipset == ide_unknown)
                                return hwif; /* match */
-                       printk("%s: port 0x%04x already claimed by %s\n", name, io_base, hwif->name);
+                       printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name);
                        return NULL;    /* already claimed */
                }
        }
@@ -188,7 +195,7 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned int io_base, const char *
        return NULL;
 }
 
-__initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *name))
+__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name))
 {
        unsigned int base, readback;
        byte reg, progif = 0;
@@ -196,14 +203,14 @@ __initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *nam
        /*
         * Place both IDE interfaces into PCI "native" mode:
         */
-       if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) {
+       if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
                if ((progif & 0xa) != 0xa) {
                        printk("%s: device not capable of full native PCI mode\n", name);
                        return 1;
                }
                printk("%s: placing both ports into native PCI mode\n", name);
-               (void) pcibios_write_config_byte(bus, fn, 0x09, progif|5);
-               if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) {
+               (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
+               if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
                        printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif);
                        return 1;
                }
@@ -213,9 +220,10 @@ __initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *nam
         */
        if (!(base = ide_find_free_region(32)))
                return 1;
-       for (reg = 0x10; reg <= 0x1c; reg += 4, base += 8) {
-               (void) pcibios_write_config_dword(bus, fn, reg, base|1);
-               if (pcibios_read_config_dword(bus, fn, reg, &readback) || (readback &= ~1) != base) {
+       for (reg = 0; reg < 4; reg++, base += 8) {
+               (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, base | PCI_BASE_ADDRESS_SPACE_IO);
+               if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, &readback) ||
+                   readback != (base | PCI_BASE_ADDRESS_SPACE_IO)) {
                        printk("%s: readback failed for basereg 0x%02x: wrote 0x%04x, read 0x%x04\n", name, reg, base, readback);
                        return 1;
                }
@@ -233,22 +241,19 @@ __initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *nam
  * we "know" about, this information is in the ide_pci_device_t struct;
  * for all other chipsets, we just assume both interfaces are enabled.
  */
-__initfunc(static void ide_setup_pci_device (byte bus, byte fn, unsigned int ccode, ide_pci_device_t *d))
+__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d))
 {
-       unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0;
+       unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0, pciirq = 0;
        unsigned short pcicmd = 0, tried_config = 0;
-       byte tmp = 0, progif = 0, pciirq = 0;
+       byte tmp = 0;
        ide_hwif_t *hwif, *mate = NULL;
 
 check_if_enabled:
-       if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd)
-        || pcibios_read_config_byte(bus, fn, 0x09, &progif)
-        || pcibios_read_config_byte(bus, fn, 0x3c, &pciirq))
-       {
+       if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
                printk("%s: error accessing PCI regs\n", d->name);
                return;
        }
-       if (!(pcicmd & 1)) {    /* is device disabled? */
+       if (!(pcicmd & PCI_COMMAND_IO)) {       /* is device disabled? */
                /*
                 * PnP BIOS was *supposed* to have set this device up for us,
                 * but we can do it ourselves, so long as the BIOS has assigned an IRQ
@@ -257,9 +262,8 @@ check_if_enabled:
                 * but we'll eventually ignore it again if no drives respond.
                 */
                if (tried_config++
-                || ide_setup_pci_baseregs(bus, fn, d->name)
-                || pcibios_write_config_word(bus, fn, 0x04, pcicmd|1))
-               {
+                || ide_setup_pci_baseregs(dev, d->name)
+                || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
                        printk("%s: device disabled (BIOS)\n", d->name);
                        return;
                }
@@ -271,39 +275,47 @@ check_if_enabled:
        /*
         * Can we trust the reported IRQ?
         */
-       if ((ccode >> 16) != PCI_CLASS_STORAGE_IDE || (progif & 5) != 5) {
+       pciirq = dev->irq;
+       if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
                printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
                pciirq = 0;
        } else if (tried_config) {
                printk("%s: will probe irqs later\n", d->name);
                pciirq = 0;
-       } else if (!pciirq || pciirq >= NR_IRQS) {
-               printk("%s: bad irq from BIOS (%d): will probe later\n", d->name, pciirq);
+       } else if (!pciirq) {
+               printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
                pciirq = 0;
        } else {
+#ifdef __sparc_v9__
+               printk("%s: 100%% native mode on irq %08x\n", d->name, pciirq);
+#else
                printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
+#endif
        }
        /*
         * Set up the IDE ports
         */
        for (port = 0; port <= 1; ++port) {
-               unsigned int base = 0, ctl = 0;
+               unsigned long base = 0, ctl = 0;
                ide_pci_enablebit_t *e = &(d->enablebits[port]);
-               if (e->reg && (pcibios_read_config_byte(bus, fn, e->reg, &tmp) || (tmp & e->mask) != e->val))
+               if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
                        continue;       /* port not enabled */
-               if (pcibios_read_config_dword(bus, fn, 0x14+(port*8), &ctl) || (ctl &= ~3) == 0)
+               ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK;
+               if (!ctl)
                        ctl = port ? 0x374 : 0x3f4;     /* use default value */
-               if (pcibios_read_config_dword(bus, fn, 0x10+(port*8), &base) || (base &= ~7) == 0)
+               base = dev->base_address[2*port] & ~7;
+
+               if (!base)
                        base = port ? 0x170 : 0x1f0;    /* use default value */
                if ((hwif = ide_match_hwif(base, d->name)) == NULL)
                        continue;       /* no room in ide_hwifs[] */
                if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
                        ide_init_hwif_ports(hwif->io_ports, base, NULL);
                        hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2;
+                       hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
                }
                hwif->chipset = ide_pci;
-               hwif->pci_bus = bus;
-               hwif->pci_fn = fn;
+               hwif->pci_dev = dev;
                hwif->pci_devid = d->devid;
                hwif->channel = port;
                if (!hwif->irq)
@@ -315,16 +327,18 @@ check_if_enabled:
                if (no_autodma)
                        hwif->no_autodma = 1;
 #ifdef CONFIG_BLK_DEV_IDEDMA
-               if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || ((ccode >> 16) == PCI_CLASS_STORAGE_IDE && (ccode & 0x8000))) {
+               if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+                   ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
                        unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
-                       unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
-                       if (dma_base && !(pcicmd & 4)) {
+                       unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name);
+                       if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
                                /*
                                 * Set up BM-DMA capability (PnP BIOS should have done this)
                                 */
+printk("%s: %s enabling Bus-Master DMA\n", hwif->name, d->name);
                                hwif->no_autodma = 1;   /* default DMA off if we had to configure it here */
-                               (void) pcibios_write_config_word(bus, fn, 0x04, (pcicmd|4));
-                               if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd) || !(pcicmd & 4)) {
+                               (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
+                               if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
                                        printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
                                        dma_base = 0;
                                }
@@ -332,8 +346,7 @@ check_if_enabled:
                        if (dma_base)
                                ide_setup_dma(hwif, dma_base, 8);
                        else
-                               printk("%s: %s Bus-Master DMA disabled (BIOS), pcicmd=0x%04x, ccode=0x%04x, dma_base=0x%04lx\n",
-                                hwif->name, d->name, pcicmd, ccode, dma_base);
+                               printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
                }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
                if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
@@ -346,66 +359,32 @@ check_if_enabled:
 }
 
 /*
- * ide_scan_pci_device() examines all functions of a PCI device,
- * looking for IDE interfaces and/or devices in ide_pci_chipsets[].
- * We cannot use pcibios_find_class() cuz it doesn't work in all systems.
+ * ide_scan_pcibus() gets invoked at boot time from ide.c.
+ * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
  */
-static inline void ide_scan_pci_device (unsigned int bus, unsigned int fn)
+__initfunc(void ide_scan_pcibus (void))
 {
-       unsigned int            ccode;
+       struct pci_dev          *dev;
        ide_pci_devid_t         devid;
        ide_pci_device_t        *d;
-       byte                    hedt;
-
-       if (pcibios_read_config_byte(bus, fn, 0x0e, &hedt))
-               hedt = 0;
-       do {
-               if (pcibios_read_config_word(bus, fn, 0x00, &devid.vid)
-                || devid.vid == 0xffff
-                || pcibios_read_config_word(bus, fn, 0x02, &devid.did)
-                || IDE_PCI_DEVID_EQ(devid, IDE_PCI_DEVID_NULL)
-                || pcibios_read_config_dword(bus, fn, 0x08, &ccode))
-                       return;
-               /* 
-                * workaround Intel Advanced/ZP with bios <= 1.04;
-                * these appear in some Dell Dimension XPS's 
-                */
-               if (!hedt && IDE_PCI_DEVID_EQ(devid, DEVID_PIIXa)) {
-                       printk("ide: implementing workaround for PIIX detection\n");
-                       hedt = 0x80;
-               }
 
+       if (!pci_present())
+               return;
+       for(dev = pci_devices; dev; dev=dev->next) {
+               devid.vid = dev->vendor;
+               devid.did = dev->device;
                for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
                if (d->init_hwif == IDE_IGNORE)
                        printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
-               else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(fn & 1))
+               else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
                        continue;       /* OPTI Viper-M uses same devid for functions 0 and 1 */
-               else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (ccode >> 16) == PCI_CLASS_STORAGE_IDE) {
+               else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
                        if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
-                               printk("%s: unknown IDE controller on PCI bus %d function %d, VID=%04x, DID=%04x\n",
-                                       d->name, bus, fn, devid.vid, devid.did);
+                               printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
+                                       d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
                        else
-                               printk("%s: IDE controller on PCI bus %d function %d\n", d->name, bus, fn);
-                       ide_setup_pci_device(bus, fn, ccode, d);
-               }
-       } while ((hedt & 0x80) && (++fn & 7));
-}
-
-/*
- * ide_scan_pcibus() gets invoked at boot time from ide.c
- *
- * Loops over all PCI devices on all PCI buses, invoking ide_scan_pci_device().
- * We cannot use pcibios_find_class() cuz it doesn't work in all systems.
- */
-void ide_scan_pcibus (void) /* __init */
-{
-       unsigned int bus, dev;
-
-       if (!pcibios_present())
-               return;
-       for (bus = 0; bus <= 255; ++bus) {
-               for (dev = 0; dev < 256; dev += 8) {
-                       ide_scan_pci_device(bus, dev);
+                               printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+                       ide_setup_pci_device(dev, d);
                }
        }
 }
index 1b4871d211aeeb1e412304f40f69293c430e57cc..b1663d5e32c4c9f38f2d86cc704a4f76d0a7678e 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/ctype.h>
 #include <asm/io.h>
 #include "ide.h"
@@ -211,21 +210,22 @@ static int proc_ide_write_config
                                if (is_pci) {
 #ifdef CONFIG_BLK_DEV_IDEPCI
                                        int rc = 0;
+                                       struct pci_dev *dev = hwif->pci_dev;
                                        switch (digits) {
                                                case 2: msg = "byte";
-                                                       rc = pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, reg, val);
+                                                       rc = pci_write_config_byte(dev, reg, val);
                                                        break;
                                                case 4: msg = "word";
-                                                       rc = pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, reg, val);
+                                                       rc = pci_write_config_word(dev, reg, val);
                                                        break;
                                                case 8: msg = "dword";
-                                                       rc = pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, reg, val);
+                                                       rc = pci_write_config_dword(dev, reg, val);
                                                        break;
                                        }
                                        if (rc) {
                                                restore_flags(flags);
-                                               printk("proc_ide_write_config: error writing %s at bus %d fn %d reg 0x%x value 0x%x\n",
-                                                       msg, hwif->pci_bus, hwif->pci_fn, reg, val);
+                                               printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
+                                                       msg, dev->bus->number, dev->devfn, reg, val);
                                                printk("proc_ide_write_config: %s\n", pcibios_strerror(rc));
                                                return -EIO;
                                        }
@@ -259,14 +259,16 @@ static int proc_ide_read_config
        int             len, reg = 0;
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
-       out += sprintf(out, "pci bus %d device %d vid %04x did %04x channel %d\n",
-               hwif->pci_bus, hwif->pci_fn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
+       struct pci_dev *dev = hwif->pci_dev;
+
+       out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
+               dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
        do {
                byte val;
-               int rc = pcibios_read_config_byte(hwif->pci_bus, hwif->pci_fn, reg, &val);
+               int rc = pci_read_config_byte(dev, reg, &val);
                if (rc) {
-                       printk("proc_ide_read_config: error reading bus %d fn %d reg 0x%02x\n",
-                               hwif->pci_bus, hwif->pci_fn, reg);
+                       printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
+                               dev->bus->number, dev->devfn, reg);
                        printk("proc_ide_read_config: %s\n", pcibios_strerror(rc));
                        return -EIO;
                        out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
index 2bf40ce538bab31e47a88c3c32d56cb73ab3a2c8..7750e944654284ef140806d89e4ed6ea472587a1 100644 (file)
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/malloc.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 
@@ -263,7 +262,7 @@ int ide_system_bus_speed (void)
                if (idebus_parameter)
                        system_bus_speed = idebus_parameter;    /* user supplied value */
 #ifdef CONFIG_PCI
-               else if (pcibios_present())
+               else if (pci_present())
                        system_bus_speed = 40;  /* safe default value for PCI */
 #endif /* CONFIG_PCI */
                else
@@ -1260,6 +1259,12 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
        } while ((hwif = hwif->next) != hwgroup->hwif);
 }
 
+#ifdef __sparc_v9__
+#define IDE_IRQ_EQUAL(irq1, irq2)      (1)
+#else
+#define IDE_IRQ_EQUAL(irq1, irq2)      ((irq1) == (irq2))
+#endif
+
 /*
  * entry point for all interrupts, caller does __cli() for us
  */
@@ -1270,25 +1275,28 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
        ide_hwif_t *hwif = hwgroup->hwif;
        ide_handler_t *handler;
 
-       if (!ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
+       if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
                return;
+
        do {
-               if (hwif->irq != irq) disable_irq(hwif->irq);
+               if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq))
+                       disable_irq(hwif->irq);
        } while ((hwif = hwif->next) != hwgroup->hwif);
-       if (irq == hwif->irq && (handler = hwgroup->handler) != NULL) {
+       if (IDE_IRQ_EQUAL(irq, hwif->irq)
+           && (handler = hwgroup->handler) != NULL) {
                ide_drive_t *drive = hwgroup->drive;
-#if 1  /* temporary, remove later -- FIXME */
+#if 1  /* temporary, remove later -- FIXME */
                {
                        struct request *rq = hwgroup->rq;
                        if (rq != NULL
-                        &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
-                        || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
+                           &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
+                           || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
                        {
                                printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n");
                                return;
                        }
                }
-#endif /* temporary */
+#endif /* temporary */
                hwgroup->handler = NULL;
                del_timer(&(hwgroup->timer));
                /* if (drive->unmask)
@@ -1308,7 +1316,8 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
        __cli();
        hwif = hwgroup->hwif;
        do {
-               if (hwif->irq != irq) enable_irq(hwif->irq);
+               if (!IDE_IRQ_EQUAL(hwif->irq, irq))
+                       enable_irq(hwif->irq);
        } while ((hwif = hwif->next) != hwgroup->hwif);
 }
 
@@ -2520,7 +2529,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
 __initfunc(static void probe_for_hwifs (void))
 {
 #ifdef CONFIG_PCI
-       if (pcibios_present())
+       if (pci_present())
        {
 #ifdef CONFIG_BLK_DEV_IDEPCI
                ide_scan_pcibus();
@@ -2530,23 +2539,29 @@ __initfunc(static void probe_for_hwifs (void))
                        extern void ide_probe_for_rz100x(void);
                        ide_probe_for_rz100x();
                }
-#endif /* CONFIG_BLK_DEV_RZ1000 */
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif /* CONFIG_BLK_DEV_RZ1000 */
+#ifdef CONFIG_BLK_DEV_SL82C105
+               {
+                       extern void ide_probe_for_sl82c105(void);
+                       ide_probe_for_sl82c105();
+               }
+#endif /* CONFIG_BLK_DEV_SL82C105 */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
        }
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI */
 
 #ifdef CONFIG_BLK_DEV_CMD640
        {
                extern void ide_probe_for_cmd640x(void);
                ide_probe_for_cmd640x();
        }
-#endif /* CONFIG_BLK_DEV_CMD640 */
+#endif /* CONFIG_BLK_DEV_CMD640 */
 #ifdef CONFIG_BLK_DEV_PDC4030
        {
                extern int init_pdc4030(void);
                (void) init_pdc4030();
        }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
 }
 
 __initfunc(void ide_init_builtin_drivers (void))
index 96fdf9422643b160f21f7cb0630a189fe59cb484..565ffea7dc0765f9d36ae6a1efc50dedd8d42a19 100644 (file)
@@ -340,8 +340,7 @@ typedef struct hwif_s {
        unsigned        reset      : 1; /* reset after probe */
        unsigned        no_autodma : 1; /* don't automatically enable DMA at boot */
        byte            channel;        /* for dual-port chips: 0=primary, 1=secondary */
-       byte            pci_bus;        /* for pci chipsets */
-       byte            pci_fn;         /* for pci chipsets */
+       struct          pci_dev *pci_dev; /* for pci chipsets */
        ide_pci_devid_t pci_devid;      /* for pci chipsets: {VID,DID} */
 #if (DISK_RECOVERY_TIME > 0)
        unsigned long   last_time;      /* time when previous rq was done */
@@ -723,7 +722,7 @@ int ide_build_dmatable (ide_drive_t *drive);
 void ide_dma_intr  (ide_drive_t *drive);
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
 void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
+unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name) __init;
 #endif
 
 #ifdef CONFIG_BLK_DEV_IDE
index b9b90c8eb5aef6c96d5727916f452137db2e4ce5..fded11f2cda91e686e7f7089bccf447ccefe8410 100644 (file)
@@ -38,6 +38,15 @@ DECLARE_TASK_QUEUE(tq_disk);
 
 /*
  * Protect the request list against multiple users..
+ *
+ * With this spinlock the Linux block IO subsystem is 100% SMP threaded
+ * from the IRQ event side, and almost 100% SMP threaded from the syscall
+ * side (we still have protect against block device array operations, and
+ * the do_request() side is casually still unsafe. The kernel lock protects
+ * this part currently.).
+ *
+ * there is a fair chance that things will work just OK if these functions
+ * are called with no global kernel lock held ...
  */
 spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED;
 
@@ -106,6 +115,11 @@ static inline int get_max_sectors(kdev_t dev)
        return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
+/*
+ * Is called with the request spinlock aquired.
+ * NOTE: the device-specific queue() functions
+ * have to be atomic!
+ */
 static inline struct request **get_queue(kdev_t dev)
 {
        int major = MAJOR(dev);
@@ -122,19 +136,27 @@ static inline struct request **get_queue(kdev_t dev)
 void unplug_device(void * data)
 {
        struct blk_dev_struct * dev = (struct blk_dev_struct *) data;
+       int queue_new_request=0;
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&io_request_lock,flags);
        if (dev->current_request == &dev->plug) {
                struct request * next = dev->plug.next;
                dev->current_request = next;
                if (next || dev->queue) {
                        dev->plug.next = NULL;
-                       (dev->request_fn)();
+                       queue_new_request = 1;
                }
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&io_request_lock,flags);
+
+       if (queue_new_request)
+               /*
+                * request functions are smart enough to notice a change
+                * in the request queue, calling them without the spinlock
+                * is OK, i think. <-- FIXME: [is this true? --mingo]
+                */
+               (dev->request_fn)();
 }
 
 /*
@@ -143,6 +165,7 @@ void unplug_device(void * data)
  * on the list.
  *
  * This is called with interrupts off and no requests on the queue.
+ * (and with the request spinlock aquired)
  */
 static inline void plug_device(struct blk_dev_struct * dev)
 {
@@ -154,8 +177,8 @@ static inline void plug_device(struct blk_dev_struct * dev)
 
 /*
  * look for a free request in the first N entries.
- * NOTE: interrupts must be disabled on the way in, and will still
- *       be disabled on the way out.
+ * NOTE: interrupts must be disabled on the way in (on SMP the request queue
+ * spinlock has to be aquired), and will still be disabled on the way out.
  */
 static inline struct request * get_request(int n, kdev_t dev)
 {
@@ -191,13 +214,14 @@ static struct request * __get_request_wait(int n, kdev_t dev)
 {
        register struct request *req;
        struct wait_queue wait = { current, NULL };
+       unsigned long flags;
 
        add_wait_queue(&wait_for_request, &wait);
        for (;;) {
                current->state = TASK_UNINTERRUPTIBLE;
-               cli();
+               spin_lock_irqsave(&io_request_lock,flags);
                req = get_request(n, dev);
-               sti();
+               spin_unlock_irqrestore(&io_request_lock,flags);
                if (req)
                        break;
                run_task_queue(&tq_disk);
@@ -211,10 +235,11 @@ static struct request * __get_request_wait(int n, kdev_t dev)
 static inline struct request * get_request_wait(int n, kdev_t dev)
 {
        register struct request *req;
+       unsigned long flags;
 
-       cli();
+       spin_lock_irqsave(&io_request_lock,flags);
        req = get_request(n, dev);
-       sti();
+       spin_unlock_irqrestore(&io_request_lock,flags);
        if (req)
                return req;
        return __get_request_wait(n, dev);
@@ -261,8 +286,9 @@ static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
 
 /*
  * add-request adds a request to the linked list.
- * It disables interrupts so that it can muck with the
- * request-lists in peace.
+ * It disables interrupts (aquires the request spinlock) so that it can muck
+ * with the request-lists in peace. Thus it should be called with no spinlocks
+ * held.
  *
  * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA,
  * which is important for drive_stat_acct() above.
@@ -272,6 +298,8 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
 {
        struct request * tmp, **current_request;
        short            disk_index;
+       unsigned long flags;
+       int queue_new_request = 0;
 
        switch (MAJOR(req->rq_dev)) {
                case SCSI_DISK_MAJOR:
@@ -292,16 +320,20 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
        }
 
        req->next = NULL;
+
+       /*
+        * We use the goto to reduce locking complexity
+        */
+       spin_lock_irqsave(&io_request_lock,flags);
        current_request = get_queue(req->rq_dev);
-       cli();
+
        if (req->bh)
                mark_buffer_clean(req->bh);
        if (!(tmp = *current_request)) {
                *current_request = req;
                if (dev->current_request != &dev->plug)
-                       (dev->request_fn)();
-               sti();
-               return;
+                       queue_new_request = 1;
+               goto out;
        }
        for ( ; tmp->next ; tmp = tmp->next) {
                if ((IN_ORDER(tmp,req) ||
@@ -314,11 +346,21 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
 
 /* for SCSI devices, call request_fn unconditionally */
        if (scsi_blk_major(MAJOR(req->rq_dev)))
-               (dev->request_fn)();
+               queue_new_request = 1;
+out:
+       spin_unlock_irqrestore(&io_request_lock,flags);
 
-       sti();
+       /*
+        * request_fn() is usually a quite complex and slow function,
+        * we want to call it with no spinlocks held
+        */
+       if (queue_new_request)
+               (dev->request_fn)();
 }
 
+/*
+ * Has to be called with the request spinlock aquired
+ */
 static inline void attempt_merge (struct request *req, int max_sectors)
 {
        struct request *next = req->next;
index 62ae86f6184f27287c3c4c0dc8b12f003bfafe61..f312b251c9c44f56e765317a75325c0bd2be02bf 100644 (file)
@@ -2,6 +2,7 @@
  * linux/drivers/block/ns87415.c       Version 1.00  December 7, 1997
  *
  * Copyright (C) 1997-1998  Mark Lord
+ * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
  *
  * Inspired by an earlier effort from David S. Miller (davem@caipfs.rutgers.edu)
  */
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include "ide.h"
 
 
-#undef INCLUDE_OBSOLETE_NS87514_STUFF  /* define this if you absolutely *need* the timings stuff */
-
-
-#ifdef INCLUDE_OBSOLETE_NS87514_STUFF
-/*
- * This part adapted from code from David S. Miller (davem@caipfs.rutgers.edu)
- * which was in turn adapted from code from Mark Lord.
- *
- * Here as a temporary measure only.  Will be removed once /proc/ide/ is working.
- */
-#include "ide_modes.h"
-
-static void ns87415_program_modes(ide_drive_t *drive, byte active_count, byte recovery_count)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       byte cfg_reg, regval;
-
-       cfg_reg = (0x44 + (8 * HWIF(drive)->channel) + (4 * drive->select.b.unit));
-
-       /* set identical PIO timings for read/write */
-       regval  = (17 - active_count) | ((16 - recovery_count) << 4);
-       pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg, regval);
-       pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg + 1, regval);
-}
-
-static void set_ide_modes(ide_drive_t *drive, ide_pio_data_t *d, int bus_speed)
-{
-       int setup_time, active_time, cycle_time = d->cycle_time;
-       byte setup_count, active_count, pio_mode = d->pio_mode;
-       byte recovery_count, recovery_count2, cycle_count;
-       int recovery_time, clock_time;
-
-       if(pio_mode > 5)
-               pio_mode = 5;
-
-       setup_time = ide_pio_timings[pio_mode].setup_time;
-       active_time = ide_pio_timings[pio_mode].active_time;
-
-       recovery_time = cycle_time - (setup_time + active_time);
-       clock_time = 1000 / bus_speed;
-
-       cycle_count  = (cycle_time  + clock_time - 1) / clock_time;
-       setup_count  = (setup_time  + clock_time - 1) / clock_time;
-       active_count = (active_time + clock_time - 1) / clock_time;
-
-       if(active_count < 2)
-               active_count = 2;
-
-       recovery_count  = (recovery_time + clock_time - 1) / clock_time;
-       recovery_count2 = cycle_count - (setup_count + active_count);
-
-       if(recovery_count2 > recovery_count)
-               recovery_count = recovery_count2;
-       if(recovery_count < 2)
-               recovery_count = 2;
-       if(recovery_count > 17) {
-               active_count += recovery_count - 17;
-               recovery_count = 17;
-       }
-
-       if(active_count > 16)
-               active_count = 16;
-       if(recovery_count > 16)
-               recovery_count = 16;
-
-       printk("active[%d CLKS] recovery[%d CLKS]\n", active_count, recovery_count);
-
-       ns87415_program_modes(drive, active_count, recovery_count);
-}
-
-/* Configure for best PIO mode. */
-static void ns87415_tuneproc (ide_drive_t *drive, byte mode_wanted)
-{
-       ide_pio_data_t d;
-       int bus_speed = ide_system_bus_speed();
-
-       switch(mode_wanted) {
-       case 6:
-       case 7:
-               /* Changes to Fast-devsel are unsupported. */
-               return;
-
-       case 8:
-       case 9:
-               mode_wanted &= 1;
-               /* XXX set_prefetch_mode(index, mode_wanted); */
-               printk("%s: %sbled NS87415 prefetching...\n", drive->name, mode_wanted ? "en" : "dis");
-               return;
-       };
-
-       (void) ide_get_best_pio_mode(drive, mode_wanted, 5, &d);
-
-       printk("%s: selected NS87415 PIO mode%d (%dns)%s ",
-              drive->name, d.pio_mode, d.cycle_time,
-              d.overridden ? " (overriding vendor mode)" : "");
-
-       set_ide_modes(drive, &d, bus_speed);
-}
-#endif /* INCLUDE_OBSOLETE_NS87514_STUFF */
-
-static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = {0};
+static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
 /*
  * This routine either enables/disables (according to drive->present)
@@ -131,24 +32,29 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
        ide_hwif_t *hwif = HWIF(drive);
        unsigned int bit, new, *old = (unsigned int *) hwif->select_data;
-       unsigned int flags;
-
-       save_flags(flags);
-       cli();
+       struct pci_dev *dev = hwif->pci_dev;
+       unsigned long flags;
 
+       save_flags(flags); cli();
        new = *old;
 
        /* adjust IRQ enable bit */
        bit = 1 << (8 + hwif->channel);
-       new = drive->present ? (new | bit) : (new & ~bit);
+       new = drive->present ? (new & ~bit) : (new | bit);
 
        /* select PIO or DMA */
        bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
        new = use_dma ? (new | bit) : (new & ~bit);
 
        if (new != *old) {
+               if (use_dma) {
+                       bit = (1 << (5 + drive->select.b.unit));
+                       outb((inb(hwif->dma_base+2) & 0x60) | bit,
+                            hwif->dma_base+2);
+               }
+
                *old = new;
-               (void) pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, new);
+               (void) pci_write_config_dword(dev, 0x40, new);
        }
        restore_flags(flags);
 }
@@ -167,25 +73,35 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
                {
                        byte dma_stat = inb(hwif->dma_base+2);
                        int rc = (dma_stat & 7) != 4;
-                       outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */
-                       outb(dma_stat|6, hwif->dma_base+2);     /* clear the INTR & ERROR bits */
-                       return rc;      /* verify good DMA status */
+                       /* from errata: stop DMA, clear INTR & ERROR */
+                       outb(7, hwif->dma_base);
+                       /* clear the INTR & ERROR bits */
+                       outb(dma_stat|6, hwif->dma_base+2);
+                       /* verify good DMA status */
+                       return rc;
                }
                case ide_dma_write:
                case ide_dma_read:
-                       ns87415_prepare_drive(drive, 1); /* select DMA xfer */
-                       if (!ide_dmaproc(func, drive))   /* use standard DMA stuff */
+                       /* select DMA xfer */
+                       ns87415_prepare_drive(drive, 1);
+                       /* use standard DMA stuff */
+                       if (!ide_dmaproc(func, drive))
                                return 0;
-                       ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
+                       /* DMA failed: select PIO xfer */
+                       ns87415_prepare_drive(drive, 0);
                        return 1;
                default:
-                       return ide_dmaproc(func, drive); /* use standard DMA stuff */
+                       /* use standard DMA stuff */
+                       return ide_dmaproc(func, drive);
        }
 }
 
 __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
 {
-       unsigned int ctrl, progif, using_inta;
+       struct pci_dev *dev = hwif->pci_dev;
+       unsigned int ctrl, using_inta;
+       byte progif, stat;
+       int timeout;
 
        /*
         * We cannot probe for IRQ: both ports share common IRQ on INTA.
@@ -194,35 +110,51 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
         *
         * IRQs get unmasked in selectproc when drive is first used.
         */
-       (void) pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, &ctrl);
-       (void) pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, &progif);
+       (void) pci_read_config_dword(dev, 0x40, &ctrl);
+       (void) pci_read_config_byte(dev, 0x09, &progif);
        /* is irq in "native" mode? */
        using_inta = progif & (1 << (hwif->channel << 1));
        if (!using_inta)
                using_inta = ctrl & (1 << (4 + hwif->channel));
-       (void) pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, ctrl);
        if (hwif->mate) {
                hwif->select_data = hwif->mate->select_data;
        } else {
-               hwif->select_data = (unsigned int) &ns87415_control[ns87415_count++];
-               ctrl |= (1 << 8) | (1 << 9);            /* mask both IRQs */
+               hwif->select_data = (unsigned long)
+                                       &ns87415_control[ns87415_count++];
+               ctrl |= (1 << 8) | (1 << 9);    /* mask both IRQs */
                if (using_inta)
-                       ctrl &= ~(1 << 6);              /* unmask INTA */
+                       ctrl &= ~(1 << 6);      /* unmask INTA */
                *((unsigned int *)hwif->select_data) = ctrl;
+               (void) pci_write_config_dword(dev, 0x40, ctrl);
+
                /*
                 * Set prefetch size to 512 bytes for both ports,
                 * but don't turn on/off prefetching here.
                 */
-               pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, 0x55, 0xee);
+               pci_write_config_byte(dev, 0x55, 0xee);
+
+#ifdef __sparc_v9__
+               /*
+                * XXX: Reset the device, if we don't it will not respond
+                *      to SELECT_DRIVE() properly during first probe_hwif().
+                */
+               timeout = 10000;
+               outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               udelay(10);
+               outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+               do {
+                       udelay(50);
+                       stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+                       if (stat == 0xff)
+                               break;
+               } while ((stat & BUSY_STAT) && --timeout);
+#endif
        }
        if (!using_inta)
                hwif->irq = hwif->channel ? 15 : 14;    /* legacy mode */
        else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-               hwif->irq = hwif->mate->irq;            /* share IRQ with mate */
+               hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
 
        hwif->dmaproc = &ns87415_dmaproc;
        hwif->selectproc = &ns87415_selectproc;
-#ifdef INCLUDE_OBSOLETE_NS87514_STUFF
-       hwif->tuneproc = &ns87415_tuneproc;
-#endif /* INCLUDE_OBSOLETE_NS87514_STUFF */
 }
index a4c94b0e66130fc8c5d5b65eeaf4759628f0ab20..a6be01938b9907b607921cd74955c8068426ef60 100644 (file)
@@ -73,8 +73,6 @@
 #include <asm/io.h>
 #include "ide.h"
 #include "ide_modes.h"
-#include <linux/pci.h>
-#include <linux/bios32.h>
 
 #define OPTI621_MAX_PIO 3
 /* In fact, I do not have any PIO 4 drive
index 4093427f08cce7e79dfbd9bfe615e4f16c625921..eecd46c2bd9bc964cc84aefffad75c604fc38370 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <asm/io.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include "ide.h"
 
 __initfunc(void ide_init_rz1000 (ide_hwif_t *hwif))    /* called from ide-pci.c */
 {
        unsigned short reg;
+       struct pci_dev *dev = hwif->pci_dev;
 
        hwif->chipset = ide_rz1000;
-       if (!pcibios_read_config_word (hwif->pci_bus, hwif->pci_fn, 0x40, &reg)
-        && !pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, 0x40, reg & 0xdfff))
+       if (!pci_read_config_word (dev, 0x40, &reg)
+        && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
        {
                printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name);
        } else {
@@ -50,16 +50,16 @@ __initfunc(void ide_init_rz1000 (ide_hwif_t *hwif)) /* called from ide-pci.c */
 
 #else
 
-__initfunc(static void init_rz1000 (byte bus, byte fn, const char *name))
+__initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
 {
        unsigned short reg, h;
 
-       if (!pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg) && !(reg & 1)) {
+       if (!pci_read_config_word (dev, PCI_COMMAND, &reg) && !(reg & PCI_COMMAND_IO)) {
                printk("%s: buggy IDE controller disabled (BIOS)\n", name);
                return;
        }
-       if (!pcibios_read_config_word (bus, fn, 0x40, &reg)
-        && !pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))
+       if (!pci_read_config_word (dev, 0x40, &reg)
+        && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
        {
                printk("IDE: disabled chipset read-ahead (buggy %s)\n", name);
        } else {
@@ -82,12 +82,12 @@ __initfunc(static void init_rz1000 (byte bus, byte fn, const char *name))
 
 __initfunc(void ide_probe_for_rz100x (void))   /* called from ide.c */
 {
-       byte index, bus, fn;
+       struct pci_dev *dev = NULL;
 
-       for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, index, &bus, &fn); ++index)
-               init_rz1000 (bus, fn, "RZ1000");
-       for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, index, &bus, &fn); ++index)
-               init_rz1000 (bus, fn, "RZ1001");
+       while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1000, dev))
+               init_rz1000 (dev, "RZ1000");
+       while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1001, dev))
+               init_rz1000 (dev, "RZ1001");
 }
 
 #endif CONFIG_BLK_DEV_IDEPCI
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
new file mode 100644 (file)
index 0000000..83426bc
--- /dev/null
@@ -0,0 +1,78 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "ide.h"
+#include "ide_modes.h"
+
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
+void ide_init_sl82c105(struct pci_dev *dev) {
+
+       unsigned short t16;
+       unsigned int t32;
+
+       pci_read_config_word(dev, PCI_COMMAND, &t16);
+       printk("SL82C105 command word: %x\n",t16);
+        t16 |= PCI_COMMAND_IO;
+        pci_write_config_word(dev, PCI_COMMAND, t16);
+       /* IDE timing */
+       pci_read_config_dword(dev, 0x44, &t32);
+       printk("IDE timing: %08x, resetting to PIO0 timing\n",t32);
+       pci_write_config_dword(dev, 0x44, 0x03e4);
+       pci_read_config_dword(dev, 0x40, &t32);
+       printk("IDE control/status register: %08x\n",t32);
+       pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+}
+
+
+void ide_probe_for_sl82c105(void)
+{
+       struct pci_dev *dev = NULL;
+
+        while ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev)))
+                ide_init_sl82c105(dev);
+}
+
+void chrp_ide_probe(void) {
+
+       struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+       chrp_ide_ports_known = 1;
+
+        if(pdev) {
+               chrp_ide_regbase[0]=pdev->base_address[0] &
+                       PCI_BASE_ADDRESS_IO_MASK;
+               chrp_ide_regbase[1]=pdev->base_address[2] &
+                       PCI_BASE_ADDRESS_IO_MASK;
+               chrp_idedma_regbase=pdev->base_address[4] &
+                       PCI_BASE_ADDRESS_IO_MASK;
+               chrp_ide_irq=pdev->irq;
+        }
+}
+
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+        ide_ioreg_t port = base;
+        int i = 8;
+
+        while (i--)
+                *p++ = port++;
+        *p++ = port;
+        if (irq != NULL)
+                *irq = chrp_ide_irq;
+}
+
index 5d3d3f37c474f46f76755c3eed29da43e5c6143a..474d434a2d308c1a2c6a6cac257d444439e9b5a7 100644 (file)
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 
 #include <asm/io.h>
@@ -213,13 +212,14 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
 {
        unsigned int cfgbase = 0;
        unsigned long flags;
-       byte reg, progif;
+       byte reg;
+       struct pci_dev *dev = hwif->pci_dev;
 
        hwif->chipset = ide_trm290;
-       if (!pcibios_read_config_byte(hwif->pci_bus, hwif->pci_fn, 0x09, &progif) && (progif & 5)
-        && !pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x20, &cfgbase) && cfgbase)
+       cfgbase = dev->base_address[4];
+       if ((dev->class & 5) && cfgbase)
        {
-               hwif->config_data = cfgbase & ~1;
+               hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK;
                printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data);
        } else {
                hwif->config_data = 0x3df0;
index c71d1f8e825a9cb4485468eb0d0e25d856e1d731..7a26e28ac33c38b243948012cfd8da68485e79e8 100644 (file)
@@ -208,6 +208,7 @@ __initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
                for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
                        if (check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
                                *controller = j;
+                               xd_type = j;
                                *address = xd_bases[i];
                                found++;
                        }
@@ -705,9 +706,10 @@ __initfunc(static void xd_dtc_init_controller (unsigned int address))
        switch (address) {
                case 0x00000:
                case 0xC8000:   break;                  /*initial: 0x320 */
-               case 0xCA000:   xd_iobase = 0x324; break;
+               case 0xCA000:   if (xd[3]<=0) xd_iobase = 0x324; 
+                               break;
                case 0xD0000:                           /*5150CX*/
-               case 0xD8000:   break;                  /*5150CX*/
+               case 0xD8000:   break;                  /*5150CX & 5150XL*/
                default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
                                break;
        }
index c3f72205b9bb9c06311a5ce727fcaec1eaa06583..76f21edfd32b658cdee3ea24bb815d8cf9ef3f9f 100644 (file)
@@ -20,7 +20,8 @@ FONTMAPFILE = cp437.uni
 
 L_TARGET := char.a
 M_OBJS   :=
-L_OBJS   := tty_io.o n_tty.o tty_ioctl.o pty.o mem.o random.o
+L_OBJS   := tty_io.o n_tty.o tty_ioctl.o mem.o random.o
+LX_OBJS  := pty.o
 
 ifdef CONFIG_VT
 L_OBJS += console.o vt.o vc_screen.o consolemap.o consolemap_deftbl.o
index 4535230ac8f1c2b96becce534faf9c4a0b798cea..775c8fe2a065340b9bab4e30f3f93a78355cb0d1 100644 (file)
@@ -525,7 +525,6 @@ static char rcsid[] =
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 
 #include <linux/version.h>
@@ -4391,7 +4390,7 @@ __initfunc(static int
 cy_detect_pci(void))
 {
 #ifdef CONFIG_PCI
-  unsigned char         cyy_bus, cyy_dev_fn, cyy_rev_id;
+  unsigned char         cyy_rev_id;
   unsigned long         pci_intr_ctrl;
   unsigned char         cy_pci_irq;
   uclong                cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
@@ -4399,20 +4398,17 @@ cy_detect_pci(void))
   unsigned short        device_id,dev_index = 0,board_index = 0;
   uclong               mailbox;
   uclong               Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
+  struct pci_dev       *pdev = NULL;
 
-        if(pcibios_present() == 0) {    /* PCI bus not present */
+        if(pci_present() == 0) {    /* PCI bus not present */
                 return(0);
         }
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
                 while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-                        if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES,
-                                        device_id,board_index,
-                                        &cyy_bus, &cyy_dev_fn) != 0)
-                        {
+                       if ((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, device_id, pdev)) == NULL)
                                 dev_index++;    /* try next device id */
-                                board_index = 0;
-                        } else {
+                        else {
                                 board_index++;
                                 break;          /* found a board */
                         }
@@ -4422,37 +4418,29 @@ cy_detect_pci(void))
                    break;
 
                 /* read PCI configuration area */
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                 PCI_INTERRUPT_LINE, &cy_pci_irq);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_0, 
-                                 (unsigned int *) &cy_pci_addr0);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_1, 
-                                 (unsigned int *) &cy_pci_addr1);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_2, 
-                                 (unsigned int *) &cy_pci_addr2);
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                  PCI_REVISION_ID, &cyy_rev_id);
+               cy_pci_irq = pdev->irq;
+               cy_pci_addr0 = pdev->base_address[0];
+               cy_pci_addr1 = pdev->base_address[1];
+               cy_pci_addr2 = pdev->base_address[2];
+               pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
 
     if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
           || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
 #ifdef CY_PCI_DEBUG
             printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-               cyy_bus, cyy_dev_fn);
+               pdev->bus->number, pdev->devfn);
             printk("rev_id=%d) IRQ%d\n",
                cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
                (ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
 #endif
-                cy_pci_addr1  &= 0xfffffffc;
-                cy_pci_addr2  &= 0xfffffff0;
+                cy_pci_addr1  &= PCI_BASE_ADDRESS_IO_MASK;
+                cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
 
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
                    printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-                       cyy_bus, cyy_dev_fn);
+                       pdev->bus->number, pdev->devfn);
                    printk("rev_id=%d) IRQ%d\n",
                        cyy_rev_id, (int)cy_pci_irq);
                     printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4537,7 +4525,7 @@ cy_detect_pci(void))
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
            /* print message */
                printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-                   cyy_bus, cyy_dev_fn);
+                   pdev->bus->number, pdev->devfn);
                printk("rev_id=%d) IRQ%d\n",
                    cyy_rev_id, (int)cy_pci_irq);
                printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -4547,13 +4535,13 @@ cy_detect_pci(void))
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
 #ifdef CY_PCI_DEBUG
             printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-               cyy_bus, cyy_dev_fn);
+               pdev->bus->number, pdev->devfn);
             printk("rev_id=%d) IRQ%d\n",
                cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
                 (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 #endif
-                cy_pci_addr0 &= 0xfffffff0;
+                cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
 #if !defined(__alpha__)
                 cy_pci_addr0 = (unsigned int) ioremap(
                                cy_pci_addr0 & PAGE_MASK,
@@ -4562,7 +4550,7 @@ cy_detect_pci(void))
 #endif
                mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
                           cy_pci_addr0)->mail_box_0);
-                cy_pci_addr2 &= 0xfffffff0;
+                cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
                if (mailbox == ZE_V1) {
 #if !defined(__alpha__)
                            cy_pci_addr2 = (unsigned int) ioremap(
index 0a6f0dd829e59c50aad89875ca7206256b54ba77..6fee9da6d7c7d0a13b0b4bb34c67950a37c0436a 100644 (file)
@@ -106,7 +106,6 @@ char kernel_version[]=UTS_RELEASE;
 
 
 #ifdef ENABLE_PCI
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/digiPCI.h>
 #endif /* ENABLE_PCI */
@@ -1747,7 +1746,7 @@ int pc_init(void)
        --------------------------------------------------------------------- */
   
        pci_boards_found = 0;
-       if (pcibios_present())
+       if (pci_present())
        {
                if(num_cards < MAXBOARDS)
                        pci_boards_found += init_PCI(num_cards);
@@ -4039,31 +4038,23 @@ void epca_setup(char *str, int *ints)
 #ifdef ENABLE_PCI
 /* --------------------- Begin get_PCI_configuration  ---------------------- */
 
-int get_PCI_configuration(char bus, char device_fn, 
+int get_PCI_configuration(char bus, char device_fn,
                           unsigned int *base_addr0, unsigned int *base_addr1,
                           unsigned int *base_addr2, unsigned int *base_addr3,
                           unsigned int *base_addr4, unsigned int *base_addr5)
 { /* Begin get_PCI_configuration */
 
-       int     error;
+       struct  pci_dev *dev = pci_find_slot(bus, device_fn);
 
-       error = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,
-                                         base_addr0);
-
-       error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1,
-                                      base_addr1);
-
-       error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2,
-                                      base_addr2);
-
-       error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_3,
-                                      base_addr3);
-
-       error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_4,
-                                      base_addr4);
+       if (!dev)
+               return(0);
 
-       error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_5,
-                                      base_addr5);
+       *base_addr0 = dev->base_address[0];
+       *base_addr1 = dev->base_address[1];
+       *base_addr2 = dev->base_address[2];
+       *base_addr3 = dev->base_address[3];
+       *base_addr4 = dev->base_address[4];
+       *base_addr5 = dev->base_address[5];
 
        /* ------------------------------------------------------------------------
                         NOTE - The code below mask out either the 2 or 4 bits dependent on the
@@ -4103,11 +4094,6 @@ int get_PCI_configuration(char bus, char device_fn,
        else
                (*base_addr5) &= PCI_BASE_ADDRESS_MEM_MASK;
 
-       if (error) 
-       {
-               printk(KERN_ERR "<Error> - DIGI PCI error: board not initializing due to error\n");
-               return(0);
-       }
        return(1);
 } /* End get_PCI_configuration */
 
@@ -4311,5 +4297,3 @@ int init_PCI(int boards_found)
 } /* End init_PCI */
 
 #endif /* ENABLE_PCI */
-
-
index 477151ce33c5247c49bcd214d0c78cb64a12dadd..bb7e9cf767a18cb0a671fd2e02bb6b13aec63eb4 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/irq.h>
 
 /* Some configuration switches are present in the include file... */
 
@@ -48,12 +49,17 @@ unsigned char pckbd_sysrq_xlate[128] =
  * them.
  */
 
-#ifndef __i386__
-#define INIT_KBD
+/*
+ * Some x86 BIOSes do not correctly initializes the keyboard, so the
+ * "kbd-reset" command line options can be given to force a reset.
+ * [Ranger]
+ */
+#ifdef __i386__
+ int kbd_startup_reset __initdata = 0;
+#else
+ int kbd_startup_reset __initdata = 1;
 #endif
 
-#ifdef INIT_KBD
-
 __initfunc(static int kbd_wait_for_input(void))
 {
        int     status, data;
@@ -202,7 +208,7 @@ __initfunc(static void initialize_kbd(void))
                printk(KERN_WARNING "initialize_kbd: %s\n", msg);
 }
 
-#endif /* INIT_KBD */
+
 
 unsigned char kbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */
 
@@ -602,7 +608,11 @@ __initfunc(void pckbd_init_hw(void))
 {
        request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
        request_region(0x60, 16, "keyboard");
-#ifdef INIT_KBD
-       initialize_kbd();
-#endif
+       if (kbd_startup_reset) initialize_kbd();
+}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void kbd_reset_setup(char *str, int *ints))
+{
+       kbd_startup_reset = 1;
 }
index 53c95d5fab850dd83e39b6f59fae5e23e0fd05dc..acef03f538cb4fefce5d3f767e085b4810748f84 100644 (file)
@@ -7,6 +7,9 @@
  *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
  */
 
+#include <linux/config.h>
+#include <linux/module.h>      /* For EXPORT_SYMBOL */
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -22,6 +25,9 @@
 #include <asm/system.h>
 #include <asm/bitops.h>
 
+#define BUILDING_PTY_C 1
+#include <linux/devpts_fs.h>
+
 struct pty_struct {
        int     magic;
        struct wait_queue * open_wait;
@@ -66,6 +72,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
        if (tty->driver.subtype == PTY_TYPE_MASTER) {
                tty_hangup(tty->link);
                set_bit(TTY_OTHER_CLOSED, &tty->flags);
+               devpts_pty_kill(MINOR(tty->device) - tty->driver.minor_start);
        }
 }
 
@@ -363,6 +370,5 @@ __initfunc(int pty_init(void))
                panic("Couldn't register compat pty driver");
        if (tty_register_driver(&old_pty_slave_driver))
                panic("Couldn't register compat pty slave driver");
-       
        return 0;
 }
index 3b6f95f6071731cbf76627624e311bcea8a111d4..901077455a45c306805e0bbbe9608b5223f4a4aa 100644 (file)
@@ -80,7 +80,6 @@
 #include <linux/major.h>
 #include <linux/ioport.h>
 #ifdef ENABLE_PCI
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #endif
 #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
@@ -1875,31 +1874,10 @@ __initfunc(int register_PCI(int i, char bus, char device_fn))
        unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
        char *str;
        CONTROLLER_t    *ctlp;
-       unsigned short  vendor_id, device_id;
-       int     ret, error;
-       unsigned int port;
-
-       error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
-               &vendor_id);
-       ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
-               &device_id);
-       if (error == 0)
-               error = ret;
-       ret = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,
-               &port);
-       rcktpt_io_addr[i] = (unsigned long) port;
-       if (error == 0)
-               error = ret;
-
-       if (error) {
-               printk("PCI RocketPort error: %s not initializing due to error"
-                      "reading configuration space\n",
-                      pcibios_strerror(error));
-               return(0);
-       }
+       struct pci_dev *dev = pci_find_slot(bus, device_fn);
 
-       --rcktpt_io_addr[i];
-       switch(device_id) {
+       rcktpt_io_addr[i] = dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+       switch(dev->device) {
        case PCI_DEVICE_ID_RP4QUAD:
                str = "Quadcable";
                max_num_aiops = 1;
@@ -1935,7 +1913,7 @@ __initfunc(int register_PCI(int i, char bus, char device_fn))
        num_aiops = sPCIInitController(ctlp, i,
                                        aiopio, max_num_aiops, 0,
                                        FREQ_DIS, 0);
-       printk("Rocketport controller #%d found at %d:%d, "
+       printk("Rocketport controller #%d found at %02x:%02x, "
               "%d AIOP(s) (PCI Rocketport %s)\n", i, bus, device_fn,
               num_aiops, str);
        if(num_aiops <= 0) {
@@ -2095,7 +2073,7 @@ __initfunc(int rp_init(void))
                        isa_boards_found++;
        }
 #ifdef ENABLE_PCI
-       if (pcibios_present()) {
+       if (pci_present()) {
                if(isa_boards_found < NUM_BOARDS)
                        pci_boards_found = init_PCI(isa_boards_found);
        } else {
index 67aeafc472b1f8ec065f808142dd1459a94849ab..31fa5ab50029bbc26ea3d7865ef450845aa6d560 100644 (file)
@@ -52,7 +52,6 @@
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #endif
 
 /*****************************************************************************/
@@ -466,7 +465,7 @@ static inline int   stl_initech(stlbrd_t *brdp);
 
 #ifdef CONFIG_PCI
 static inline int      stl_findpcibrds(void);
-static inline int      stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr);
+static inline int      stl_initpcibrd(int brdtype, struct pci_dev *dev);
 #endif
 
 /*
@@ -2530,16 +2529,16 @@ __initfunc(static int stl_brdinit(stlbrd_t *brdp))
  *     configuration space.
  */
 
-static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr)
+static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev)
 {
        unsigned int    bar[4];
        stlbrd_t        *brdp;
-       int             i, rc;
+       int             i;
        unsigned char   irq;
 
 #if DEBUG
        printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
-               brdtype, busnr, devnr);
+               brdtype, dev->bus->number, dev->devfn);
 #endif
 
        brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
@@ -2559,22 +2558,9 @@ static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char
  *     boards use these in different ways, so we just read in the whole
  *     lot and then figure out what is what later.
  */
-       for (i = 0; (i < 4); i++) {
-               rc = pcibios_read_config_dword(busnr, devnr,
-                       (PCI_BASE_ADDRESS_0 + (i * 0x4)), &bar[i]);
-               if (rc) {
-                       printk("STALLION: failed to read BAR register %d "
-                               "from PCI board, errno=%x\n", i, rc);
-                       return(0);
-               }
-       }
-
-       rc = pcibios_read_config_byte(busnr, devnr, PCI_INTERRUPT_LINE, &irq);
-       if (rc) {
-               printk("STALLION: failed to read INTERRUPT register "
-                       "from PCI board, errno=%x\n", rc);
-               return(0);
-       }
+       for (i = 0; (i < 4); i++)
+               bar[i] = dev->base_address[i];
+       irq = dev->irq;
 
 #if DEBUG
        printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
@@ -2620,24 +2606,18 @@ static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char
 
 static inline int stl_findpcibrds()
 {
-       unsigned char   busnr, devnr;
-       unsigned short  class;
-       int             i, rc, brdtypnr;
+       struct pci_dev  *dev = NULL;
+       int             i, rc;
 
 #if DEBUG
        printk("stl_findpcibrds()\n");
 #endif
 
-       if (! pcibios_present())
+       if (! pci_present())
                return(0);
 
-       for (i = 0; (i < stl_nrpcibrds); i++) {
-               for (brdtypnr = 0; ; brdtypnr++) {
-
-                       rc = pcibios_find_device(stl_pcibrds[i].vendid,
-                               stl_pcibrds[i].devid, brdtypnr, &busnr, &devnr);
-                       if (rc)
-                               break;
+       for (i = 0; (i < stl_nrpcibrds); i++)
+               while ((dev = pci_find_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) {
 
 /*
  *                     Check that we can handle more boards...
@@ -2653,22 +2633,13 @@ static inline int stl_findpcibrds()
  *                     Found a device on the PCI bus that has our vendor and
  *                     device ID. Need to check now that it is really us.
  */
-                       rc = pcibios_read_config_word(busnr, devnr,
-                               PCI_CLASS_DEVICE, &class);
-                       if (rc) {
-                               printk("STALLION: failed to read class type "
-                                       "from PCI board, errno=%x\n", rc);
-                               continue;
-                       }
-                       if (class == PCI_CLASS_STORAGE_IDE)
+                       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
                                continue;
 
-                       rc = stl_initpcibrd(stl_pcibrds[i].brdtype, busnr,
-                               devnr);
+                       rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
                        if (rc)
                                return(rc);
                }
-       }
 
        return(0);
 }
index 4fe1676f379a7244d859f6d067336e6197ab2147..6e041a550c77947500ca5f7fa7843b5855a0d6ea 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -137,7 +136,7 @@ extern struct console vt_console_driver;
 #define TGA_F_HEIGHT_PADDED 18
 
 int tga_type;
-unsigned int tga_mem_base;
+unsigned long tga_mem_base;
 unsigned long tga_fb_base;
 unsigned long tga_regs_base;
 unsigned int tga_bpp, tga_fb_width, tga_fb_height, tga_fb_stride;
@@ -472,15 +471,13 @@ __initfunc(int con_is_present(void))
 __initfunc(void
 tga_console_init(void))
 {
-       unsigned char pci_bus, pci_devfn;
+       struct pci_dev *dev;
        int status;
        
        /*
         * first, find the TGA among the PCI devices...
         */
-       status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
-                                     0, &pci_bus, &pci_devfn);
-       if (status == PCIBIOS_DEVICE_NOT_FOUND) {
+       if (! (dev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL)))
                /* PANIC!!! */
                printk("tga_console_init: TGA not found!!! :-(\n");
                return;
@@ -489,14 +486,12 @@ tga_console_init(void))
        /*
         * read BASE_REG_0 for memory address
         */
-       pcibios_read_config_dword(pci_bus, pci_devfn,
-                                 PCI_BASE_ADDRESS_0, &tga_mem_base);
-       tga_mem_base &= ~15;
+       tga_mem_base = dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
 #ifdef DEBUG
-       printk("tga_console_init: mem_base 0x%x\n", tga_mem_base);
+       printk("tga_console_init: mem_base 0x%lx\n", tga_mem_base);
 #endif /* DEBUG */
 
-       tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f;
+       tga_type = (readl(tga_mem_base) >> 12) & 0x0f;
        if (tga_type != 0 && tga_type != 1 && tga_type != 3) {
          printk("TGA type (0x%x) unrecognized!\n", tga_type);
          return;
@@ -561,9 +556,8 @@ tga_init_video(void))
        int i, j, temp;
        unsigned char *cbp;
 
-       tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET);
-       tga_fb_base =
-         ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]);
+       tga_regs_base = (tga_mem_base + TGA_REGS_OFFSET);
+       tga_fb_base = (tga_mem_base + fb_offset_presets[tga_type]);
 
        /* first, disable video timing */
        TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
index 1ae53be8ab064ab0c3c9118c6cd4138014a9a45b..35be2317763eafe2f7d76734c433b44368e4c284 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
 #include <linux/file.h>
 #include <linux/console.h>
 #include <linux/timer.h>
@@ -1209,7 +1210,7 @@ retry_open:
        if (device == PTMX_DEV) {
                /* find a free pty. */
                struct tty_driver *driver = tty_drivers;
-               int minor;
+               int minor, line;
 
                /* find the pty driver */
                for (driver=tty_drivers; driver; driver=driver->next)
@@ -1229,6 +1230,8 @@ retry_open:
                        return -EIO; /* no free ptys */
                
                set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+               line = minor - driver->minor_start;
+               devpts_pty_new(line, MKDEV(driver->other->major, line+driver->other->minor_start));
                noctty = 1;
                goto init_dev_done;
        }
index 012542b09446c23b47fad87f97487c6c3a8f68b8..b1fe56af6eddd048e4efa7fd1e14d8f78872e879 100644 (file)
@@ -458,6 +458,7 @@ static int epp_clear_timeout(struct parport *pb)
 static int parport_SPP_supported(struct parport *pb)
 {
        /* Do a simple read-write test to make sure the port exists. */
+       parport_pc_write_econtrol(pb, 0xc);
        parport_pc_write_control(pb, 0xc);
        parport_pc_write_data(pb, 0xaa);
        if (parport_pc_read_data(pb) != 0xaa) return 0;
@@ -894,6 +895,7 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
        p->flags |= PARPORT_FLAG_COMA;
 
        /* Done probing.  Now put the port into a sensible start-up state. */
+       parport_pc_write_econtrol(p, 0xc);
        parport_pc_write_control(p, 0xc);
        parport_pc_write_data(p, 0);
 
index 2694dbb6c9a368192d9e132690306672b3cd49f5..a9ddfa4752208d45bef89bd963ebf264c97ed5ec 100644 (file)
@@ -65,7 +65,6 @@ static int max_interrupt_work = 20;
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/timer.h>
 #include <asm/irq.h>                   /* For NR_IRQS only. */
 #include <asm/bitops.h>
@@ -113,6 +112,7 @@ static int max_interrupt_work = 20;
 
 #if LINUX_VERSION_CODE < 0x20115
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #elif defined(MODULE)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
@@ -532,12 +532,18 @@ static int vortex_scan(struct device *dev)
           be best done a central PCI probe dispatch, which wouldn't work
           well with the current structure.  So instead we detect 3Com cards
           in slot order. */
-       if (pcibios_present()) {
+       if (pci_present()) {
                static int pci_index = 0;
                unsigned char pci_bus, pci_device_fn;
 
                for (;pci_index < 0xff; pci_index++) {
-                       unsigned char pci_irq_line, pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+                       unsigned int pci_irq_line;
+                       struct pci_dev *pdev;
+#else
+                       unsigned char pci_irq_line;
+#endif
+                       unsigned char pci_latency;
                        unsigned short pci_command, new_command, vendor, device;
                        unsigned int pci_ioaddr;
                        int board_index = 0;
@@ -550,10 +556,16 @@ static int vortex_scan(struct device *dev)
                                                                         PCI_VENDOR_ID, &vendor);
                        pcibios_read_config_word(pci_bus, pci_device_fn,
                                                                         PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+                       pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       pci_irq_line = pdev->irq;
+                       pci_ioaddr = pdev->base_address[0];
+#else
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                                                         PCI_INTERRUPT_LINE, &pci_irq_line);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                                                          PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
                        pcibios_read_config_word(pci_bus, pci_device_fn,
                                                                         PCI_COMMAND, &pci_command);
                        /* Remove I/O space marker in bit 0. */
index 55424dc51d7a0e8954a05b73aa3570fef0f457c0..d8ad8c67b4aab6ace044b3711326a755518f73eb 100644 (file)
 
         insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
 
-    For a compiled in driver, at or above line 526, place e.g.
+    For a compiled in driver, somewhere in this file, place e.g.
        #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
 
     Yes,  I know full duplex  isn't permissible on BNC  or AUI; they're just
@@ -390,7 +390,6 @@ static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -929,7 +928,7 @@ static void    SetMulticastFilter(struct device *dev);
 static int     get_hw_addr(struct device *dev);
 static void    srom_repair(struct device *dev, int card);
 static int     test_bad_enet(struct device *dev, int status);
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 static void    eisa_probe(struct device *dev, u_long iobase);
 #endif
 static void    pci_probe(struct device *dev, u_long iobase);
@@ -978,12 +977,15 @@ static int loading_module = 0;
 #endif /* MODULE */
 
 static char name[DE4X5_NAME_LENGTH + 1];
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
 #endif
 static int num_de4x5s = 0;
 static int cfrv = 0, useSROM = 0;
-static int lastEISA = 0, lastPCI = -1;
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
+static int lastEISA = 0;
+#endif
+static int lastPCI = -1;
 static struct device *lastModule = NULL;
 
 /*
@@ -1048,7 +1050,7 @@ de4x5_probe(struct device *dev))
 {
     u_long iobase = dev->base_addr;
 
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
     eisa_probe(dev, iobase);
 #endif
     pci_probe(dev, iobase);
@@ -1094,14 +1096,14 @@ de4x5_hw_init(struct device *dev, u_long iobase))
     
     dev->base_addr = iobase;
     if (lp->bus == EISA) {
-       printk("%s: %s at 0x%04lx (EISA slot %ld),\n", 
+       printk("%s: %s at 0x%04lx (EISA slot %ld)", 
               dev->name, name, iobase, ((iobase>>12)&0x0f));
     } else {                                 /* PCI port address */
-       printk("%s: %s at 0x%04lx (PCI bus %d, device %d),\n", dev->name, name,
+       printk("%s: %s at 0x%04lx (PCI bus %d, device %d)", dev->name, name,
               iobase, lp->bus_num, lp->device);
     }
     
-    printk("      h/w address ");
+    printk(", h/w address ");
     status = get_hw_addr(dev);
     for (i = 0; i < ETH_ALEN - 1; i++) {     /* get the ethernet addr. */
        printk("%2.2x:", dev->dev_addr[i]);
@@ -1305,9 +1307,8 @@ de4x5_open(struct device *dev)
     
     lp->state = OPEN;
     de4x5_dbg_open(dev);
-    
     if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, 
-                                                    lp->adapter_name, dev)) {
+           lp->adapter_name, dev)) {
        printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
        if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
                                                     lp->adapter_name, dev)) {
@@ -1974,7 +1975,7 @@ SetMulticastFilter(struct device *dev)
     return;
 }
 
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 /*
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard. Upto 15 EISA devices are supported.
@@ -2063,15 +2064,14 @@ __initfunc(static void
 pci_probe(struct device *dev, u_long ioaddr))
 {
     u_char pb, pbus, dev_num, dnum, dev_fn, timer;
-    u_short vendor, index, status;
+    u_short dev_id, vendor, index, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     struct bus_type *lp = &bus;
-    struct pci_dev *pdev;
 
     if (lastPCI == NO_MORE_PCI) return;
 
-    if (!pcibios_present()) {
+    if (!pci_present()) {
        lastPCI = NO_MORE_PCI;
        return;          /* No PCI bus in this machine! */
     }
@@ -2091,75 +2091,92 @@ pci_probe(struct device *dev, u_long ioaddr))
         (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
         index++) {
        dev_num = PCI_SLOT(dev_fn);
-       if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue;
-       pdev = pci_find_dev(pb, dev_fn);
-
-       vendor = pdev->vendor;
-       device = pdev->device << 8;
-       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+       if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) {
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
+           struct pci_dev *pdev = pci_find_slot(pb, dev_fn);
+#else
+           u_char tirq;
+           u_int tmp;
+#endif
+           device = 0;
+           pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+           pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+           device = dev_id;
+           device <<= 8;
+           if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+               continue;
+           }
 
-       /* Search for an SROM on this bus */
-       if (lp->bus_num != pb) {
-           lp->bus_num = pb;
-           srom_search(index);
-       }
+           /* Search for an SROM on this bus */
+           if (lp->bus_num != pb) {
+               lp->bus_num = pb;
+               srom_search(index);
+           }
 
-       /* Get the chip configuration revision register */
-       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
+           /* Get the chip configuration revision register */
+           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
 
-       /* Set the device number information */
-       lp->device = dev_num;
-       lp->bus_num = pb;
+           /* Set the device number information */
+           lp->device = dev_num;
+           lp->bus_num = pb;
            
-       /* Set the chipset information */
-       if (is_DC2114x) device |= (cfrv & CFRV_RN);
-       lp->chipset = device;
+           /* Set the chipset information */
+           if (is_DC2114x) device |= (cfrv & CFRV_RN);
+           lp->chipset = device;
 
-       /* Get the board I/O address (64 bits on sparc64) */
-       iobase = pdev->base_address[0] & CBIO_MASK;
+           /* Get the board I/O address and IRQ */
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,85)
+           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+           iobase = tmp;
+           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+           irq = tirq;
+#else
+           iobase = pdev->base_address[0];
+           irq = pdev->irq;
+#endif
+           iobase &= CBIO_MASK;
 
-       /* Fetch the IRQ to be used */
-       irq = pdev->irq;
-       if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
-           
-       /* Check if I/O accesses and Bus Mastering are enabled */
-       pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-#ifdef __powerpc__
-       if (!(status & PCI_COMMAND_IO)) {
-           status |= PCI_COMMAND_IO;
-           pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+           if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
+
+           /* Check if I/O accesses and Bus Mastering are enabled */
            pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-       }
+#ifdef __powerpc__
+           if (!(status & PCI_COMMAND_IO)) {
+               status |= PCI_COMMAND_IO;
+               pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+               pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+           }
 #endif /* __powerpc__ */
-       if (!(status & PCI_COMMAND_IO)) continue;
+           if (!(status & PCI_COMMAND_IO)) continue;
 
-       if (!(status & PCI_COMMAND_MASTER)) {
-           status |= PCI_COMMAND_MASTER;
-           pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
-           pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-       }
-       if (!(status & PCI_COMMAND_MASTER)) continue;
+           if (!(status & PCI_COMMAND_MASTER)) {
+               status |= PCI_COMMAND_MASTER;
+               pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+               pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+           }
+           if (!(status & PCI_COMMAND_MASTER)) continue;
 
-       /* Check the latency timer for values >= 0x60 */
-       pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
-       if (timer < 0x60) {
-           pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
-       }
+           /* Check the latency timer for values >= 0x60 */
+           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
+           if (timer < 0x60) {
+               pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
+           }
 
-       DevicePresent(DE4X5_APROM);
-       if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
-           dev->irq = irq;
-           if ((status = de4x5_hw_init(dev, iobase)) == 0) {
-               num_de4x5s++;
-               if (loading_module) {
-                   link_modules(lastModule, dev);
-                   lastPCI = index;
+           DevicePresent(DE4X5_APROM);
+           if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
+               dev->irq = irq;
+               if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+                   num_de4x5s++;
+                   if (loading_module) {
+                       link_modules(lastModule, dev);
+                       lastPCI = index;
+                   }
+                   return;
                }
-               return;
+           } else if (ioaddr != 0) {
+               printk("%s: region already allocated at 0x%04lx.\n", dev->name,
+                      iobase);
            }
-       } else if (ioaddr != 0) {
-           printk("%s: region already allocated at 0x%04lx.\n", dev->name,
-                  iobase);
        }
     }
 
@@ -2178,24 +2195,35 @@ __initfunc(static void
 srom_search(int index))
 {
     u_char pb, dev_fn;
-    u_short dev_num, vendor, status;
+    u_short dev_id, dev_num, vendor, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j;
     struct bus_type *lp = &bus;
-    struct pci_dev *pdev;
+#ifndef __sparc_v9__
+    u_char tirq;
+    u_int tmp;
+#endif
 
     for (; 
         (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
         index++) {
-
+#ifdef __sparc_v9__
+       struct pci_dev *pdev;
+       for (pdev = pci_devices; pdev; pdev = pdev->next) {
+           if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break;
+       }
+#endif
        if (lp->bus_num != pb) return;
        dev_num = PCI_SLOT(dev_fn);
-       pdev = pci_find_dev(pb, dev_fn);
-
-       vendor = pdev->vendor;
-       device = pdev->device << 8;
-       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+       device = 0;
+       pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+       pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+       device = dev_id;
+       device <<= 8;
+       if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+           continue;
+       }
 
        /* Get the chip configuration revision register */
        pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
@@ -2209,10 +2237,21 @@ srom_search(int index))
        lp->chipset = device;
 
        /* Get the board I/O address (64 bits on sparc64) */
-       iobase = pdev->base_address[0] & CBIO_MASK;
+#ifndef __sparc_v9__
+       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+       iobase = tmp;
+#else
+       iobase = pdev->base_address[0];
+#endif
+       iobase &= CBIO_MASK;
 
        /* Fetch the IRQ to be used */
+#ifndef __sparc_v9__
+       pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+       irq = tirq;
+#else
        irq = pdev->irq;
+#endif
        if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
            
        /* Check if I/O accesses are enabled */
@@ -4053,6 +4092,19 @@ get_hw_addr(struct device *dev)
     /* If possible, try to fix a broken card - SMC only so far */
     srom_repair(dev, broken);
 
+#ifdef CONFIG_PMAC
+    /* If the address starts with 00 a0, we have to bit-reverse
+       each byte of the address. */
+    if (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0xa0) {
+       for (i = 0; i < ETH_ALEN; ++i) {
+           int x = dev->dev_addr[i];
+           x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
+           x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
+           dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
+       }
+    }
+#endif /* CONFIG_PMAC */
+
     /* Test for a bad enet address */
     status = test_bad_enet(dev, status);
 
@@ -5713,29 +5765,30 @@ unlink_modules(struct device *p)
 static int
 count_adapters(void)
 {
-    int i, j=0;
+    int i, j;
     char name[DE4X5_STRLEN];
-    u_char pb, dev_fn;
-    u_short vendor;
+    u_char pb, dev_fn, dev_num;
+    u_short dev_id, vendor;
     u_int class = DE4X5_CLASS_CODE;
     u_int device;
-    struct pci_dev *pdev;
-
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
     u_long iobase = 0x1000;
 
-    for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
+    for (j=0, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
        if (EISA_signature(name, EISA_ID)) j++;
     }
 #endif
-    if (!pcibios_present()) return j;
+    if (!pci_present()) return j;
 
     for (i=0; 
         (pcibios_find_class(class, i, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
         i++) {
-       pdev = pci_find_dev(pb, dev_fn);
-       vendor = pdev->vendor;
-       device = pdev->device << 8;
+       dev_num = PCI_SLOT(dev_fn);
+       device = 0;
+       pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+       pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+       device = dev_id;
+       device <<= 8;
        if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++;
     }
 
index 8c2cbd2780ab2ede3fcaba0c7cbacc053c899c0b..2faccc6fda66e1b9bae9747972a2c34711502473 100644 (file)
@@ -213,7 +213,6 @@ static const char *version = "defxx.c:v1.04 09/16/96  Lawrence V. Stefani (stefa
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <asm/byteorder.h>
@@ -455,9 +454,8 @@ __initfunc(int dfx_probe(
        int                             i;                              /* used in for loops */
        int                             version_disp;   /* was version info string already displayed? */
        int                             port_len;               /* length of port address range (in bytes) */
-       u8                              pci_bus;                /* PCI bus number (0-255) */
-       u8                              pci_dev_fun;    /* PCI device and function numbers (0-255) */
        u16                             port;                   /* temporary I/O (port) address */
+       struct pci_dev *                pdev = NULL;            /* PCI device record */
        u16                             command;                /* PCI Configuration space Command register val */
        u32                             slot_id;                /* EISA hardware (slot) ID read from adapter */
        DFX_board_t             *bp;                    /* board pointer */
@@ -530,61 +528,58 @@ __initfunc(int dfx_probe(
 
        /* Scan for FDDI PCI controllers */
 
-       if (pcibios_present())                                          /* is PCI BIOS even present? */
-               for (i=0; i < DFX_MAX_NUM_BOARDS; i++)  /* scan for up to 8 PCI cards */
-                       if (pcibios_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, i, &pci_bus, &pci_dev_fun) == 0)
+       if (pci_present())                                              /* is PCI even present? */
+               while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev)))
+                       {
+                       if (!version_disp)                                      /* display version info if adapter is found */
                                {
-                               if (!version_disp)                                      /* display version info if adapter is found */
-                                       {
-                                       version_disp = 1;                               /* set display flag to TRUE so that */
-                                       printk(version);                                /* we only display this string ONCE */
-                                       }
+                               version_disp = 1;                               /* set display flag to TRUE so that */
+                               printk(version);                                /* we only display this string ONCE */
+                               }
 
-                               /* Verify that I/O enable bit is set (PCI slot is enabled) */
+                       /* Verify that I/O enable bit is set (PCI slot is enabled) */
 
-                               pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, &command);
-                               if ((command & PCI_COMMAND_IO) == 0)
-                                       printk("I/O enable bit not set!  Verify that slot is enabled\n");
-                               else
-                                       {
-                                       /* Turn off memory mapped space and enable mastering */
+                       pci_read_config_word(pdev, PCI_COMMAND, &command);
+                       if ((command & PCI_COMMAND_IO) == 0)
+                               printk("I/O enable bit not set!  Verify that slot is enabled\n");
+                       else
+                               {
+                               /* Turn off memory mapped space and enable mastering */
 
-                                       command |= PCI_COMMAND_MASTER;
-                                       command &= ~PCI_COMMAND_MEMORY;
-                                       pcibios_write_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, command);
+                               command |= PCI_COMMAND_MASTER;
+                               command &= ~PCI_COMMAND_MEMORY;
+                               pci_write_config_word(pdev, PCI_COMMAND, command);
 
-                                       /* Read I/O base address from PCI Configuration Space */
-                               
-                                       pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_BASE_ADDRESS_1, &port);
-                                       port &= PCI_BASE_ADDRESS_IO_MASK;               /* clear I/O bit (bit 0) */
+                               /* Get I/O base address from PCI Configuration Space */
+
+                               port = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
 
-                                       /* Verify port address range is not already being used */
+                               /* Verify port address range is not already being used */
+
+                               port_len = PFI_K_CSR_IO_LEN;
+                               if (check_region(port, port_len) == 0)
+                                       {
+                                       /* Allocate a new device structure for this adapter */
 
-                                       port_len = PFI_K_CSR_IO_LEN;
-                                       if (check_region(port, port_len) == 0)
+                                       dev = dfx_alloc_device(dev, port);
+                                       if (dev != NULL)
                                                {
-                                               /* Allocate a new device structure for this adapter */
-
-                                               dev = dfx_alloc_device(dev, port);
-                                               if (dev != NULL)
-                                                       {
-                                                       /* Initialize board structure with bus-specific info */
-
-                                                       bp = (DFX_board_t *) dev->priv;
-                                                       bp->dev = dev;
-                                                       bp->bus_type = DFX_BUS_TYPE_PCI;
-                                                       bp->pci_bus = pci_bus;
-                                                       bp->pci_dev_fun = pci_dev_fun;
-                                                       if (dfx_driver_init(dev) == DFX_K_SUCCESS)
-                                                               num_boards++;           /* only increment global board count on success */
-                                                       else
-                                                               dev->base_addr = 0;     /* clear port address field in device structure on failure */
-                                                       }
+                                               /* Initialize board structure with bus-specific info */
+
+                                               bp = (DFX_board_t *) dev->priv;
+                                               bp->dev = dev;
+                                               bp->bus_type = DFX_BUS_TYPE_PCI;
+                                               bp->pci_dev = pdev;
+                                               if (dfx_driver_init(dev) == DFX_K_SUCCESS)
+                                                       num_boards++;           /* only increment global board count on success */
+                                               else
+                                                       dev->base_addr = 0;     /* clear port address field in device structure on failure */
                                                }
-                                       else
-                                               printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
                                        }
+                               else
+                                       printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
                                }
+                       }
 
        /*
         * If we're at this point we're going through dfx_probe() for the first
@@ -823,18 +818,19 @@ __initfunc(void dfx_bus_init(
                }
        else
                {
+               struct pci_dev *pdev = bp->pci_dev;
+
                /* Get the interrupt level from the PCI Configuration Table */
 
-               pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_INTERRUPT_LINE, &val);
-               dev->irq = val;                                 /* save IRQ value in device table */
+               dev->irq = pdev->irq;
 
                /* Check Latency Timer and set if less than minimal */
 
-               pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, &val);
+               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
                if (val < PFI_K_LAT_TIMER_MIN)  /* if less than min, override with default */
                        {
                        val = PFI_K_LAT_TIMER_DEF;
-                       pcibios_write_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, val);
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
                        }
 
                /* Enable interrupts at PCI bus interface chip (PFI) */
index 83d66456b7923e7f0f5b8ad3589cbf6e058e17e0..5707ad877cfb097ff243652777bb22dcc7a52c82 100644 (file)
@@ -1754,8 +1754,7 @@ typedef struct DFX_board_tag
        struct device                   *dev;                                                   /* pointer to device structure */
        u32                                             bus_type;                                               /* bus type (0 == PCI, 1 == EISA) */
        u16                                             base_addr;                                              /* base I/O address (same as dev->base_addr) */
-       u8                                              pci_bus;                                                /* PCI bus number */
-       u8                                              pci_dev_fun;                                    /* PCI device and function numbers */
+       struct pci_dev *                                pci_dev;
        u32                                             full_duplex_enb;                                /* FDDI Full Duplex enable (1 == on, 2 == off) */
        u32                                             req_ttrt;                                               /* requested TTRT value (in 80ns units) */
        u32                                             burst_size;                                             /* adapter burst size (enumerated) */
index e562446e829ae922137aaeff4c357e3812aea400..c379b3a4392af79a08f44a09c276fcc7870450f7 100644 (file)
@@ -87,7 +87,6 @@ static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -109,6 +108,7 @@ static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
        #define COPY_FROM_USER(DST,SRC,LEN)     copy_from_user(DST,SRC,LEN)
        #define COPY_TO_USER(DST,SRC,LEN)       copy_to_user(DST,SRC,LEN)
 #else
+       #include <linux/bios32.h>
        #define IOREMAP(ADDR, LEN)              vremap(ADDR, LEN)
        #define IOUNMAP(ADDR)                   vfree(ADDR)
        #define COPY_FROM_USER(DST,SRC,LEN)     memcpy_fromfs(DST,SRC,LEN)
@@ -1373,14 +1373,19 @@ dgrs_scan(struct device *dev))
        /*
         *      First, check for PCI boards
         */
-       if (pcibios_present())
+       if (pci_present())
        {
                int pci_index = 0;
 
                for (; pci_index < 8; pci_index++)
                {
                        uchar   pci_bus, pci_device_fn;
+#if LINUX_VERSION_CODE < 0x20100
                        uchar   pci_irq;
+#else
+                       uint    pci_irq;
+                       struct pci_dev *pdev;
+#endif
                        uchar   pci_latency;
                        ushort  pci_command;
 
@@ -1390,6 +1395,7 @@ dgrs_scan(struct device *dev))
                                                        &pci_device_fn))
                                        break;
 
+#if LINUX_VERSION_CODE < 0x20100
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                        PCI_INTERRUPT_LINE, &pci_irq);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
@@ -1398,6 +1404,13 @@ dgrs_scan(struct device *dev))
                                        PCI_BASE_ADDRESS_1, &io);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                        PCI_BASE_ADDRESS_2, &mem);
+#else
+                       pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       pci_irq = pdev->irq;
+                       plxreg = pdev->base_address[0];
+                       io = pdev->base_address[1];
+                       mem = pdev->base_address[2];
+#endif
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                        0x30, &plxdma);
                        irq = pci_irq;
index 156a07ba25b13f7210438f8eecfcd0323d671182..c896844b2e823a1de868fd4cbb54481deab3bf3c 100644 (file)
@@ -59,7 +59,6 @@ static int max_interrupt_work = 200;
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -120,6 +119,7 @@ struct device *init_etherdev(struct device *dev, int sizeof_priv,
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #endif
 
 /* The total I/O port extent of the board.  Nominally 0x18, but rounded up
@@ -473,10 +473,16 @@ int eepro100_init(struct device *dev)
 {
        int cards_found = 0;
 
-       if (pcibios_present()) {
+       if (pci_present()) {
                static int pci_index = 0;
                for (; pci_index < 8; pci_index++) {
-                       unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency;
+                       unsigned char pci_bus, pci_device_fn, pci_latency;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+                       unsigned int pci_irq_line;
+                       struct pci_dev *pdev;
+#else
+                       unsigned char pci_irq_line;
+#endif
 #if (LINUX_VERSION_CODE >= VERSION(1,3,44))
                        int pci_ioaddr;
 #else
@@ -489,11 +495,17 @@ int eepro100_init(struct device *dev)
                                                                        pci_index, &pci_bus,
                                                                        &pci_device_fn))
                          break;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+                       pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       pci_irq_line = pdev->irq;
+                       pci_ioaddr = pdev->base_address[1];
+#else
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                                                         PCI_INTERRUPT_LINE, &pci_irq_line);
                        /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                                                          PCI_BASE_ADDRESS_1, &pci_ioaddr);
+#endif
                        /* Remove I/O space marker in bit 0. */
                        pci_ioaddr &= ~3;
                        if (speedo_debug > 2)
index 0f1bdd3c72d542ce7699f1a6dc69583700dc5081..25f04ddead35e06906ee2e05e3ec956a1e22f2d5 100644 (file)
@@ -83,7 +83,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -331,6 +330,9 @@ __initfunc(int hp100_probe( struct device *dev ))
   int ioaddr = 0;
 #ifdef CONFIG_PCI
   int pci_start_index = 0;
+#ifdef LINUX_2_1
+  struct pci_dev *pdev;
+#endif
 #endif
 
 #ifdef HP100_DEBUG_B
@@ -363,7 +365,7 @@ __initfunc(int hp100_probe( struct device *dev ))
   /* at first - scan PCI bus(es) */
 
 #ifdef CONFIG_PCI
-  if ( pcibios_present() )
+  if ( pci_present() )
     {
       int pci_index;
 
@@ -384,8 +386,14 @@ __initfunc(int hp100_probe( struct device *dev ))
           break;
 
          __pci_found:
+
+#ifdef LINUX_2_1
+         pdev = pci_find_slot(pci_bus, pci_device_fn);
+         ioaddr = pdev->base_address[0];
+#else
           pcibios_read_config_dword( pci_bus, pci_device_fn,
                                      PCI_BASE_ADDRESS_0, &ioaddr );
+#endif
 
           ioaddr &= ~3;    /* remove I/O space marker in bit 0. */
 
index 423b4a7acbe2bfe1778bc049480503be3bba419e..367654ea3826053f95109677e2236716890270d3 100644 (file)
@@ -45,7 +45,6 @@ static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@c
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -285,7 +284,7 @@ static struct lance_chip_type {
 enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6};
 
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
 
 /* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers.
    Assume yes until we know the memory size. */
@@ -317,36 +316,26 @@ __initfunc(int lance_init(void))
                lance_need_isa_bounce_buffers = 0;
 
 #if defined(CONFIG_PCI) && !defined(CONFIG_PCNET32)
-    if (pcibios_present()) {
-           int pci_index;
+    if (pci_present()) {
+           struct pci_dev *pdev = NULL;
                if (lance_debug > 1)
-                       printk("lance.c: PCI bios is present, checking for devices...\n");
-               for (pci_index = 0; pci_index < 8; pci_index++) {
+                       printk("lance.c: PCI is present, checking for devices...\n");
+               while (pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev)) {
                        unsigned char pci_bus, pci_device_fn;
                        unsigned int pci_ioaddr;
                        unsigned short pci_command;
 
-                       if (pcibios_find_device (PCI_VENDOR_ID_AMD,
-                                                                        PCI_DEVICE_ID_AMD_LANCE, pci_index,
-                                                                        &pci_bus, &pci_device_fn) != 0)
-                               break;
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_0, &pci_ioaddr);
-                       /* Remove I/O space marker in bit 0. */
-                       pci_ioaddr &= ~3;
+                       pci_irq_line = pdev->irq;
+                       pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
                        /* PCI Spec 2.1 states that it is either the driver or PCI card's
                         * responsibility to set the PCI Master Enable Bit if needed.
                         *      (From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
                         */
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_COMMAND, &pci_command);
+                       pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
                        if ( ! (pci_command & PCI_COMMAND_MASTER)) {
                                printk("PCI Master Bit has not been set. Setting...\n");
                                pci_command |= PCI_COMMAND_MASTER;
-                               pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                                 PCI_COMMAND, pci_command);
+                               pci_write_config_word(pdev, PCI_COMMAND, pci_command);
                        }
                        printk("Found PCnet/PCI at %#x, irq %d.\n",
                                   pci_ioaddr, pci_irq_line);
index 87b80875404d9d3936fb9f8ba7f5f1cc1b0765d0..b36cee01b881614cd5a712968684ac548168ac42 100644 (file)
@@ -40,7 +40,6 @@ static const char *version =
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/system.h>
@@ -117,7 +116,7 @@ bad_clone_list[] __initdata = {
 #define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
 
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
 
 int ne_probe(struct device *dev);
 static int ne_probe1(struct device *dev, int ioaddr);
@@ -182,7 +181,7 @@ __initfunc(int ne_probe(struct device *dev))
 
 #ifdef CONFIG_PCI
     /* Then look for any installed PCI clones */
-    if (pcibios_present() && (ne_probe_pci(dev) == 0))
+    if (pci_present() && (ne_probe_pci(dev) == 0))
        return 0;
 #endif
 
@@ -207,27 +206,19 @@ __initfunc(static int ne_probe_pci(struct device *dev))
        int i;
 
        for (i = 0; pci_clone_list[i].vendor != 0; i++) {
-               unsigned char pci_bus, pci_device_fn;
+               struct pci_dev *pdev = NULL;
                unsigned int pci_ioaddr;
-               int pci_index;
-
-               for (pci_index = 0; pci_index < 8; pci_index++) {
-                       if (pcibios_find_device (pci_clone_list[i].vendor,
-                                       pci_clone_list[i].dev_id, pci_index,
-                                       &pci_bus, &pci_device_fn) != 0)
-                               break;  /* No more of these type of cards */
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                       PCI_BASE_ADDRESS_0, &pci_ioaddr);
-                       /* Strip the I/O address out of the returned value */
-                       pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+
+               while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) {
+                       pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
                        /* Avoid already found cards from previous calls */
                        if (check_region(pci_ioaddr, NE_IO_EXTENT))
                                continue;
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                       PCI_INTERRUPT_LINE, &pci_irq_line);
-                       break;  /* Beauty -- got a valid card. */
+                       pci_irq_line = pdev->irq;
+                       if (pci_irq_line == 0) continue;        /* Try next PCI ID */
                }
-               if (pci_irq_line == 0) continue;        /* Try next PCI ID */
+               if (!pdev)
+                       continue;
                printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
                                pci_clone_list[i].name,
                                pci_ioaddr, pci_irq_line);
index 313e4f5c63c1c6460f1ab5520a01a41dd6bc8c15..1bb492e8f3c51f0cfe4f237787841209e445e7e2 100644 (file)
@@ -25,7 +25,6 @@ static const char *version = "pcnet32.c:v0.23 8.2.97 tsbogend@alpha.franken.de\n
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -78,7 +77,7 @@ static int pcnet32_debug = 1;
  *        in arch/i386/bios32.c
  * v0.21:  added endian conversion for ppc, from work by cort@cs.nmt.edu
  * v0.22:  added printing of status to ring dump
- * v0.23:  changed enet_statistics to net_devive_stats
+ * v0.23:  changed enet_statistics to net_device_stats
  */
 
 
@@ -172,7 +171,7 @@ static void pcnet32_set_multicast_list(struct device *dev);
 __initfunc(int pcnet32_probe (struct device *dev))
 {
     unsigned int  ioaddr = dev ? dev->base_addr: 0;
-    unsigned char irq_line = dev ? dev->irq : 0;
+    unsigned int  irq_line = dev ? dev->irq : 0;
     int *port;
     
     if (ioaddr > 0x1ff)
@@ -181,30 +180,20 @@ __initfunc(int pcnet32_probe (struct device *dev))
       return ENXIO;
     
 #if defined(CONFIG_PCI)
-    if (pcibios_present()) {
-       int pci_index;
+    if (pci_present()) {
+       struct pci_dev *pdev = NULL;
        
        printk("pcnet32.c: PCI bios is present, checking for devices...\n");
-       for (pci_index = 0; pci_index < 8; pci_index++) {
-           unsigned char pci_bus, pci_device_fn;
+       while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) {
            unsigned short pci_command;
 
-           if (pcibios_find_device (PCI_VENDOR_ID_AMD,
-                                    PCI_DEVICE_ID_AMD_LANCE, pci_index,
-                                    &pci_bus, &pci_device_fn) != 0)
-             break;
-           pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                    PCI_INTERRUPT_LINE, &irq_line);
-           pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                     PCI_BASE_ADDRESS_0, &ioaddr);
-           /* Remove I/O space marker in bit 0. */
-           ioaddr &= ~3;
+           irq_line = pdev->irq;
+           ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
            /* PCI Spec 2.1 states that it is either the driver or PCI card's
             * responsibility to set the PCI Master Enable Bit if needed.
             *  (From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
             */
-           pcibios_read_config_word(pci_bus, pci_device_fn,
-                                    PCI_COMMAND, &pci_command);
+           pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
            
            /* Avoid already found cards from previous pcnet32_probe() calls */
            if (check_region(ioaddr, PCNET32_TOTAL_SIZE))
@@ -213,8 +202,7 @@ __initfunc(int pcnet32_probe (struct device *dev))
            if ( ! (pci_command & PCI_COMMAND_MASTER)) {
                printk("PCI Master Bit has not been set. Setting...\n");
                pci_command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-               pcibios_write_config_word(pci_bus, pci_device_fn,
-                                         PCI_COMMAND, pci_command);
+               pci_write_config_word(pdev, PCI_COMMAND, pci_command);
            }
 #ifdef __powerpc__
            irq_line = 15;
index 9ff5a4f110b8cab59cf3a48b2bf69a746faa1ab0..6c179167414a3d9dde04dcf7e03cfab0378f9aff 100644 (file)
@@ -45,7 +45,6 @@ static char *version =
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/pbm.h>
 #endif
 
@@ -55,7 +54,10 @@ static char *version =
 static struct happy_meal *root_happy_dev = NULL;
 #endif
 
-/* #define HMEDEBUG */
+#undef HMEDEBUG
+#undef SXDEBUG
+#undef RXDEBUG
+#undef TXDEBUG
 
 #ifdef HMEDEBUG
 #define HMD(x)  printk x
@@ -1584,8 +1586,11 @@ static inline void happy_meal_mif_interrupt(struct happy_meal *hp,
        happy_meal_poll_stop(hp, tregs);
 }
 
-/* #define TXD(x) printk x */
+#ifdef TXDEBUG
+#define TXD(x) printk x
+#else
 #define TXD(x)
+#endif
 
 static inline void happy_meal_tx(struct happy_meal *hp)
 {
@@ -1676,8 +1681,11 @@ static inline void sun4c_happy_meal_tx(struct happy_meal *hp)
        TXD((">"));
 }
 
-/* #define RXD(x) printk x */
+#ifdef RXDEBUG
+#define RXD(x) printk x
+#else
 #define RXD(x)
+#endif
 
 /* Originally I use to handle the allocation failure by just giving back just
  * that one ring buffer to the happy meal.  Problem is that usually when that
@@ -1705,7 +1713,7 @@ static inline void happy_meal_rx(struct happy_meal *hp, struct device *dev,
 
                /* Check for errors. */
                if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-                       RXD(("ERR(%08lx)]", flags));
+                       RXD(("ERR(%08x)]", flags));
                        hp->net_stats.rx_errors++;
                        if(len < ETH_ZLEN)
                                hp->net_stats.rx_length_errors++;
@@ -1724,11 +1732,8 @@ static inline void happy_meal_rx(struct happy_meal *hp, struct device *dev,
                }
                skb = hp->rx_skbs[elem];
 #ifdef NEED_DMA_SYNCHRONIZATION
-#ifdef CONFIG_PCI
-               if(!(hp->happy_flags & HFLAG_PCI))
-#endif
-                       mmu_sync_dma(kva_to_hva(hp, skb->data),
-                                    skb->len, hp->happy_sbus_dev->my_bus);
+               mmu_sync_dma(kva_to_hva(hp, skb->data),
+                            skb->len, hp->happy_sbus_dev->my_bus);
 #endif
                if(len > RX_COPY_THRESHOLD) {
                        struct sk_buff *new_skb;
@@ -1819,7 +1824,7 @@ static inline void pci_happy_meal_rx(struct happy_meal *hp, struct device *dev,
 
                /* Check for errors. */
                if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-                       RXD(("ERR(%08lx)]", flags));
+                       RXD(("ERR(%08x)]", flags));
                        hp->net_stats.rx_errors++;
                        if(len < ETH_ZLEN)
                                hp->net_stats.rx_length_errors++;
@@ -1926,7 +1931,7 @@ static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct device *dev
 
                /* Check for errors. */
                if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-                       RXD(("ERR(%08lx)]", flags));
+                       RXD(("ERR(%08x)]", flags));
                        hp->net_stats.rx_errors++;
                        if(len < ETH_ZLEN)
                                hp->net_stats.rx_length_errors++;
@@ -1975,7 +1980,7 @@ static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        struct hmeal_tcvregs *tregs   = hp->tcvregs;
        unsigned int happy_status    = hme_read32(hp, &gregs->stat);
 
-       HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+       HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
        dev->interrupt = 1;
 
@@ -2020,7 +2025,7 @@ static void pci_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs
        struct hmeal_tcvregs *tregs   = hp->tcvregs;
        unsigned int happy_status     = readl((unsigned long)&gregs->stat);
 
-       HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+       HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
        dev->interrupt = 1;
 
@@ -2065,7 +2070,7 @@ static void sun4c_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *re
        struct hmeal_tcvregs *tregs   = hp->tcvregs;
        unsigned int happy_status    = hme_read32(hp, &gregs->stat);
 
-       HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+       HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
        dev->interrupt = 1;
 
@@ -2181,8 +2186,11 @@ static int happy_meal_close(struct device *dev)
        return 0;
 }
 
-/* #define SXD(x) printk x */
+#ifdef SXDEBUG
+#define SXD(x) printk x
+#else
 #define SXD(x)
+#endif
 
 static int happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
 {
@@ -2700,19 +2708,20 @@ __initfunc(int happy_meal_probe(struct device *dev))
                }
        }
 #ifdef CONFIG_PCI
-       if(pcibios_present()) {
+       if(pci_present()) {
                struct pci_dev *pdev;
 
-               for(pdev = pci_devices; pdev; pdev = pdev->next) {
+               pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+                                      PCI_DEVICE_ID_SUN_HAPPYMEAL, 0);
+               while (pdev) {
                        if(cards)
                                dev = NULL;
-                       if((pdev->vendor == PCI_VENDOR_ID_SUN) &&
-                          (pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)) {
-                               cards++;
-                               if((v = happy_meal_pci_init(dev, pdev)))
-                                       return v;
-                       }
-
+                       cards++;
+                       if((v = happy_meal_pci_init(dev, pdev)))
+                               return v;
+                       pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+                                              PCI_DEVICE_ID_SUN_HAPPYMEAL,
+                                              pdev);
                }
        }
 #endif
index cef3f54a4e3ce5c9e4d193af3a7442d28bdfe1bd..92d4b9e694f391374bf040f024d3df33adc752ed 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "tlan.h"
 
-#include <linux/bios32.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
@@ -96,7 +95,7 @@ static        TLanPciId TLanDeviceList[] = {
 };
 
 
-static int     TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * );
+static int     TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * );
 static int     TLan_Init( struct device * );
 static int     TLan_Open(struct device *dev);
 static int     TLan_StartTx(struct sk_buff *, struct device *);
@@ -193,7 +192,7 @@ extern int init_module(void)
        int             failed;
        int             found;
        u32             io_base;
-       u8              irq;
+       int             irq;
        u8              rev;
 
        printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n",
@@ -319,7 +318,8 @@ extern int tlan_probe( struct device *dev )
        static int      pad_allocated = 0;
        int             found;
        TLanPrivateInfo *priv;
-       u8              bus, dfn, irq, rev;
+       u8              bus, dfn, rev;
+       int             irq;
        u32             io_base, dl_ix;
 
        found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix );
@@ -398,7 +398,7 @@ extern int tlan_probe( struct device *dev )
         *
         **************************************************************/
 
-int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
+int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
 {
        static int dl_index = 0;
        static int pci_index = 0;
@@ -409,7 +409,7 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
        int     reg;
 
 
-       if ( ! pcibios_present() ) {
+       if ( ! pci_present() ) {
                printk( "TLAN:   PCI Bios not present.\n" );
                return 0;
        }
@@ -425,6 +425,7 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
                );
 
                if ( ! not_found ) {
+                       struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn);
 
                        TLAN_DBG(
                                TLAN_DEBUG_GNRL,
@@ -433,19 +434,18 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
                                TLanDeviceList[dl_index].deviceId
                        );
 
-                       pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_REVISION_ID, pci_rev);
-                       pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_INTERRUPT_LINE, pci_irq);
-                       pcibios_read_config_word ( *pci_bus,  *pci_dfn, PCI_COMMAND, &pci_command);
-                       pcibios_read_config_dword( *pci_bus,  *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base);
-                       pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_LATENCY_TIMER, &pci_latency);
+                       pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev);
+                       *pci_irq = pdev->irq;
+                       pci_read_config_word ( pdev, PCI_COMMAND, &pci_command);
+                       pci_read_config_byte ( pdev, PCI_LATENCY_TIMER, &pci_latency);
 
                        if (pci_latency < 0x10) {
-                               pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff);
+                               pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 0xff);
                                TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    Setting latency timer to max.\n");
                        }
 
-                       for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) {
-                               pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base);
+                       for ( reg = 0; reg <= 5; reg ++ ) {
+                               *pci_io_base = pdev->base_address[reg];
                                if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
                                        *pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
                                        TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    IO mapping is available at %x.\n", *pci_io_base);
index 035c47a5cb3ffc63dea2436b01156f6693b2c1c0..0abf814e58d3e2248cbe5e064d9d1214a41fea5d 100644 (file)
@@ -82,7 +82,6 @@ static const rx_copybreak = 100;
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -125,8 +124,10 @@ char kernel_version[] = UTS_RELEASE;
 #include <linux/delay.h>
 #endif
 #if (LINUX_VERSION_CODE >= 0x20100)
+#ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 #endif
+#endif
 #ifdef SA_SHIRQ
 #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
 #else
@@ -135,6 +136,7 @@ char kernel_version[] = UTS_RELEASE;
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #endif
 
 /* This my implementation of shared IRQs, now only used for 1.2.13. */
@@ -453,11 +455,17 @@ int tulip_probe(struct device *dev)
           well with the current structure.  So instead we detect just the
           Tulip cards in slot order. */
 
-       if (pcibios_present()) {
+       if (pci_present()) {
                unsigned char pci_bus, pci_device_fn;
 
                for (;pci_index < 0xff; pci_index++) {
-                       unsigned char pci_irq_line, pci_latency;
+                       unsigned char pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+                       unsigned int pci_irq_line;
+                       struct pci_dev *pdev;
+#else
+                       unsigned char pci_irq_line;
+#endif
                        unsigned short pci_command, vendor, device;
                        unsigned int pci_ioaddr, chip_idx = 0;
 
@@ -473,10 +481,16 @@ int tulip_probe(struct device *dev)
                                                                         PCI_VENDOR_ID, &vendor);
                        pcibios_read_config_word(pci_bus, pci_device_fn,
                                                                         PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+                       pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       pci_irq_line = pdev->irq;
+                       pci_ioaddr = pdev->base_address[0];
+#else
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                                                         PCI_INTERRUPT_LINE, &pci_irq_line);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                                                          PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
                        /* Remove I/O space marker in bit 0. */
                        pci_ioaddr &= ~3;
 
index 9c4b53d13a4a7d86b49118c9126e98bf06700bf6..ba587264500e3e63ecf5d1910418b7f4fb50d5ec 100644 (file)
@@ -9,9 +9,18 @@
 # parent makefile.
 #
 
-L_OBJS   := pci.o
 L_TARGET := pci.a
 
+# Nasty trick as nobody references pcisyms.o, but we still want it linked.
+ifeq ($(CONFIG_MODULES),y)
+O_TARGET = pci_syms.o
+OX_OBJS  = pcisyms.o
+O_OBJS   = pci.o
+L_OBJS   := pci_syms.o
+else
+L_OBJS   := pci.o
+endif
+
 ifdef CONFIG_PROC_FS
 L_OBJS   += proc.o
 ifdef CONFIG_PCI_OLD_PROC
@@ -23,4 +32,6 @@ ifdef CONFIG_PCI_OPTIMIZE
 L_OBJS   += quirks.o
 endif
 
+L_OBJS   += compat.o
+
 include $(TOPDIR)/Rules.make
diff --git a/drivers/pci/compat.c b/drivers/pci/compat.c
new file mode 100644 (file)
index 0000000..cfc66ca
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *     $Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $
+ *
+ *     PCI Bus Services -- Function For Backward Compatibility
+ *
+ *     Copyright 1998 Martin Mares
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+int
+pcibios_find_class(unsigned int class, unsigned short index, unsigned char *bus, unsigned char *devfn)
+{
+       struct pci_dev *dev = NULL;
+       int cnt = 0;
+
+       while ((dev = pci_find_class(class, dev)))
+               if (index == cnt++) {
+                       *bus = dev->bus->number;
+                       *devfn = dev->devfn;
+                       return PCIBIOS_SUCCESSFUL;
+               }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+int
+pcibios_find_device(unsigned short vendor, unsigned short device, unsigned short index,
+                   unsigned char *bus, unsigned char *devfn)
+{
+       struct pci_dev *dev = NULL;
+       int cnt = 0;
+
+       while ((dev = pci_find_device(vendor, device, dev)))
+               if (index == cnt++) {
+                       *bus = dev->bus->number;
+                       *devfn = dev->devfn;
+                       return PCIBIOS_SUCCESSFUL;
+               }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
index c9fb9b28b9ce22b3f14c8b5bdc65384bd0bedadc..a505547221634131a0d08d4f60f9b7b4eb953393 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: oldproc.c,v 1.4 1998/01/05 14:16:18 mj Exp $
+ *     $Id: oldproc.c,v 1.10 1998/03/15 13:50:11 ecd Exp $
  *
  *     Backward-compatible procfs interface for PCI.
  *
@@ -10,7 +10,6 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/sched.h>
@@ -220,9 +219,11 @@ struct pci_dev_info dev_info[] = {
        DEVICE( OLICOM,         OLICOM_OC2183,  "OC-2183/2185"),
        DEVICE( OLICOM,         OLICOM_OC2326,  "OC-2326"),
        DEVICE( OLICOM,         OLICOM_OC6151,  "OC-6151/6152"),
-       DEVICE( SUN,            SUN_EBUS,       "EBUS"),
-       DEVICE( SUN,            SUN_HAPPYMEAL,  "Happy Meal"),
+       DEVICE( SUN,            SUN_EBUS,       "PCI-EBus Bridge"),
+       DEVICE( SUN,            SUN_HAPPYMEAL,  "Happy Meal Ethernet"),
+       DEVICE( SUN,            SUN_SIMBA,      "Advanced PCI Bridge"),
        DEVICE( SUN,            SUN_PBM,        "PCI Bus Module"),
+       DEVICE( SUN,            SUN_SABRE,      "Ultra IIi PCI"),
        DEVICE( CMD,            CMD_640,        "640 (buggy)"),
        DEVICE( CMD,            CMD_643,        "643"),
        DEVICE( CMD,            CMD_646,        "646"),
@@ -273,6 +274,8 @@ struct pci_dev_info dev_info[] = {
        DEVICE( ASP,            ASP_ABP940UW,   "ABP940UW"),
        DEVICE( CERN,           CERN_SPSB_PMC,  "STAR/RD24 SCI-PCI (PMC)"),
        DEVICE( CERN,           CERN_SPSB_PCI,  "STAR/RD24 SCI-PCI (PMC)"),
+       DEVICE( CERN,           CERN_HIPPI_DST, "HIPPI destination"),
+       DEVICE( CERN,           CERN_HIPPI_SRC, "HIPPI source"),
        DEVICE( IMS,            IMS_8849,       "8849"),
        DEVICE( TEKRAM2,        TEKRAM2_690c,   "DC690c"),
        DEVICE( TUNDRA,         TUNDRA_CA91C042,"CA91C042 Universe"),
@@ -378,6 +381,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
        DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
        DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
+       DEVICE( ESSENTIAL,      ROADRUNNER,     "RoadRunner serial HIPPI"),
        DEVICE( CYCLADES,       CYCLOM_Y_Lo,    "Cyclom-Y below 1Mbyte"),
        DEVICE( CYCLADES,       CYCLOM_Y_Hi,    "Cyclom-Y above 1Mbyte"),
        DEVICE( CYCLADES,       CYCLOM_Z_Lo,    "Cyclom-Z below 1Mbyte"),
index 199bb91884e669f38eb270f4f93c9e4c10233172..c8675207c9b0c506d2c63db9902a3d6df7046c54 100644 (file)
@@ -1,42 +1,28 @@
 /*
- *     $Id: pci.c,v 1.55 1997/12/27 12:17:54 mj Exp $
+ *     $Id: pci.c,v 1.71 1998/03/30 11:14:35 mj Exp $
  *
- *     PCI services that are built on top of the BIOS32 service.
+ *     PCI Bus Services
  *
- *     Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *     Copyright 1993 -- 1998 Drew Eckhardt, Frederic Potter,
  *     David Mosberger-Tang, Martin Mares
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 
 #include <asm/page.h>
 
 struct pci_bus pci_root;
-struct pci_dev *pci_devices = 0;
+struct pci_dev *pci_devices = NULL;
+static struct pci_dev **pci_last_dev_p = &pci_devices;
 
 #undef DEBUG
 
-/*
- * pci_malloc() returns initialized memory of size SIZE.  Can be
- * used only while pci_init() is active.
- */
-__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
-{
-       void *mem;
-
-       mem = (void*) *mem_startp;
-       *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-       memset(mem, 0, size);
-       return mem;
-}
-
-
 const char *pcibios_strerror(int error)
 {
        static char buf[32];
@@ -68,7 +54,45 @@ const char *pcibios_strerror(int error)
 }
 
 
-unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
+struct pci_dev *
+pci_find_slot(unsigned int bus, unsigned int devfn)
+{
+       struct pci_dev *dev;
+
+       for(dev=pci_devices; dev; dev=dev->next)
+               if (dev->bus->number == bus && dev->devfn == devfn)
+                       break;
+       return dev;
+}
+
+
+struct pci_dev *
+pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
+{
+       if (!from)
+               from = pci_devices;
+       else
+               from = from->next;
+       while (from && (from->vendor != vendor || from->device != device))
+               from = from->next;
+       return from;
+}
+
+
+struct pci_dev *
+pci_find_class(unsigned int class, struct pci_dev *from)
+{
+       if (!from)
+               from = pci_devices;
+       else
+               from = from->next;
+       while (from && from->class != class)
+               from = from->next;
+       return from;
+}
+
+
+__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
 {
        unsigned int devfn, l, max, class;
        unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
@@ -97,7 +121,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                        continue;
                }
 
-               dev = pci_malloc(sizeof(*dev), mem_startp);
+               dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+               memset(dev, 0, sizeof(*dev));
                dev->bus = bus;
                dev->devfn  = devfn;
                dev->vendor = l & 0xffff;
@@ -113,13 +138,19 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
                class >>= 8;                                /* upper 3 bytes */
                dev->class = class;
+               dev->hdr_type = hdr_type;
 
                switch (hdr_type & 0x7f) {                  /* header type */
-               case 0:                                     /* standard header */
+               case PCI_HEADER_TYPE_NORMAL:                /* standard header */
                        if (class >> 8 == PCI_CLASS_BRIDGE_PCI)
                                goto bad;
-                       /* read irq level (may be changed during pcibios_fixup()): */
-                       pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
+                       /*
+                        * If the card generates interrupts, read IRQ number
+                        * (some architectures change it during pcibios_fixup())
+                        */
+                       pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
+                       if (irq)
+                               pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
                        dev->irq = irq;
                        /*
                         * read base address registers, again pcibios_fixup() can
@@ -130,7 +161,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                                dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
                        }
                        break;
-               case 1:                                     /* bridge header */
+               case PCI_HEADER_TYPE_BRIDGE:                /* bridge header */
                        if (class >> 8 != PCI_CLASS_BRIDGE_PCI)
                                goto bad;
                        for (reg = 0; reg < 2; reg++) {
@@ -138,6 +169,14 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                                dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
                        }
                        break;
+               case PCI_HEADER_TYPE_CARDBUS:               /* CardBus bridge header */
+                       if (class >> 16 != PCI_BASE_CLASS_BRIDGE)
+                               goto bad;
+                       for (reg = 0; reg < 2; reg++) {
+                               pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l);
+                               dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
+                       }
+                       break;
                default:                                    /* unknown header */
                bad:
                        printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
@@ -154,8 +193,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                 * Put it into the global PCI device chain. It's used to
                 * find devices once everything is set up.
                 */
-               dev->next = pci_devices;
-               pci_devices = dev;
+               *pci_last_dev_p = dev;
+               pci_last_dev_p = &dev->next;
 
                /*
                 * Now insert it into the list of devices held
@@ -174,7 +213,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                        /*
                         * Insert it into the tree of buses.
                         */
-                       child = pci_malloc(sizeof(*child), mem_startp);
+                       child = kmalloc(sizeof(*child), GFP_ATOMIC);
+                       memset(child, 0, sizeof(*child));
                        child->next = bus->children;
                        bus->children = child;
                        child->self = dev;
@@ -203,11 +243,14 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                        pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
                        if ((buses & 0xFFFFFF) != 0)
                          {
+                           unsigned int cmax;
+
                            child->primary = buses & 0xFF;
                            child->secondary = (buses >> 8) & 0xFF;
                            child->subordinate = (buses >> 16) & 0xFF;
                            child->number = child->secondary;
-                           max = pci_scan_bus(child, mem_startp);
+                           cmax = pci_scan_bus(child);
+                           if (cmax > max) max = cmax;
                          }
                        else
                          {
@@ -223,7 +266,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                            /*
                             * Now we can scan all subordinate buses:
                             */
-                           max = pci_scan_bus(child, mem_startp);
+                           max = pci_scan_bus(child);
                            /*
                             * Set the subordinate bus number to its real
                             * value:
@@ -250,36 +293,31 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
 }
 
 
-__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end))
+__initfunc(void pci_init(void))
 {
-       mem_start = pcibios_init(mem_start, mem_end);
+       pcibios_init();
 
-       if (!pcibios_present()) {
+       if (!pci_present()) {
                printk("PCI: No PCI bus detected\n");
-               return mem_start;
        }
 
-       printk("Probing PCI hardware.\n");
+       printk("PCI: Probing PCI hardware.\n");
 
        memset(&pci_root, 0, sizeof(pci_root));
-       pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start);
+       pci_root.subordinate = pci_scan_bus(&pci_root);
 
        /* give BIOS a chance to apply platform specific fixes: */
-       mem_start = pcibios_fixup(mem_start, mem_end);
+       pcibios_fixup();
 
 #ifdef CONFIG_PCI_OPTIMIZE
        pci_quirks_init();
 #endif
-
-       return mem_start;
 }
 
-struct pci_dev *pci_find_dev(unsigned char bus, unsigned char devfn)
-{
-       struct pci_dev *pdev;
-       for (pdev = pci_devices; pdev; pdev = pdev->next) {
-               if ((pdev->bus->number==bus) && (pdev->devfn==devfn)) break;
 
-       }
-       return pdev;
+__initfunc(void pci_setup (char *str, int *ints))
+{
+       str = pcibios_setup(str);
+       if (*str)
+               printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
 }
diff --git a/drivers/pci/pcisyms.c b/drivers/pci/pcisyms.c
new file mode 100644 (file)
index 0000000..2f4501e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *     $Id: pcisyms.c,v 1.2 1998/02/16 10:35:57 mj Exp $
+ *
+ *     PCI Bus Services -- Exported Symbols
+ *
+ *     Copyright 1998 Martin Mares
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+EXPORT_SYMBOL(pcibios_present);
+EXPORT_SYMBOL(pcibios_read_config_byte);
+EXPORT_SYMBOL(pcibios_read_config_word);
+EXPORT_SYMBOL(pcibios_read_config_dword);
+EXPORT_SYMBOL(pcibios_write_config_byte);
+EXPORT_SYMBOL(pcibios_write_config_word);
+EXPORT_SYMBOL(pcibios_write_config_dword);
+EXPORT_SYMBOL(pcibios_strerror);
+EXPORT_SYMBOL(pci_devices);
+EXPORT_SYMBOL(pci_find_class);
+EXPORT_SYMBOL(pci_find_device);
+EXPORT_SYMBOL(pci_find_slot);
+
+/* Backward compatibility */
+
+EXPORT_SYMBOL(pcibios_find_class);
+EXPORT_SYMBOL(pcibios_find_device);
index d3a56837c7c824568a7b2dc938037d6fe68e164b..452481404bf9405836298261201582c7f1af138d 100644 (file)
@@ -1,14 +1,13 @@
 /*
- *     $Id: proc.c,v 1.1 1997/12/22 17:22:31 mj Exp $
+ *     $Id: proc.c,v 1.8 1998/03/12 14:32:51 mj Exp $
  *
  *     Procfs interface for the PCI bus.
  *
- *     Copyright (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *     Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
@@ -49,14 +48,27 @@ proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
        int pos = *ppos;
        unsigned char bus = dev->bus->number;
        unsigned char dfn = dev->devfn;
-       int cnt;
+       int cnt, size;
 
-       if (pos >= PCI_CFG_SPACE_SIZE)
+       /*
+        * Normal users can read only the standardized portion of the
+        * configuration space as several chips lock up when trying to read
+        * undefined locations (think of Intel PIIX4 as a typical example).
+        */
+
+       if (fsuser())
+               size = PCI_CFG_SPACE_SIZE;
+       else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+               size = 128;
+       else
+               size = 64;
+
+       if (pos >= size)
                return 0;
-       if (nbytes >= PCI_CFG_SPACE_SIZE)
-               nbytes = PCI_CFG_SPACE_SIZE;
-       if (pos + nbytes > PCI_CFG_SPACE_SIZE)
-               nbytes = PCI_CFG_SPACE_SIZE - pos;
+       if (nbytes >= size)
+               nbytes = size;
+       if (pos + nbytes > size)
+               nbytes = size - pos;
        cnt = nbytes;
 
        if (!access_ok(VERIFY_WRITE, buf, cnt))
@@ -260,16 +272,9 @@ static struct proc_dir_entry proc_pci_devices = {
        get_pci_dev_info
 };
 
-__initfunc(void proc_bus_pci_init(void))
+__initfunc(void proc_bus_pci_add(struct pci_bus *bus, struct proc_dir_entry *proc_pci))
 {
-       struct proc_dir_entry *proc_pci;
-       struct pci_bus *bus;
-
-       if (!pcibios_present())
-               return;
-       proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
-       proc_register(proc_pci, &proc_pci_devices);
-       for(bus = &pci_root; bus; bus = bus->next) {
+       while (bus) {
                char name[16];
                struct proc_dir_entry *de;
                struct pci_dev *dev;
@@ -287,5 +292,19 @@ __initfunc(void proc_bus_pci_init(void))
                        e->data = dev;
                        e->size = PCI_CFG_SPACE_SIZE;
                }
+               if (bus->children)
+                       proc_bus_pci_add(bus->children, proc_pci);
+               bus = bus->next;
        }
 }
+
+__initfunc(void proc_bus_pci_init(void))
+{
+       struct proc_dir_entry *proc_pci;
+
+       if (!pci_present())
+               return;
+       proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
+       proc_register(proc_pci, &proc_pci_devices);
+       proc_bus_pci_add(&pci_root, proc_pci);
+}
index eb51794af642876b7038453b52ff227d988fbc6c..1c2cc969d3400f2769ff53efae9df55254854bc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: quirks.c,v 1.2 1997/09/20 21:43:34 davem Exp $
+ * $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $
  *
  * PCI Chipset-Specific Quirks
  *
@@ -13,7 +13,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
index 092b8500a7bbc4e00602ffcdbcdcdb12b9a2d994..3b19ba4fe0fb8810f01876849168b4e2dca400f5 100644 (file)
@@ -243,7 +243,6 @@ typedef unsigned int  u32;
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
@@ -1413,53 +1412,47 @@ normal_init (Scsi_Host_Template *tpnt, int board, int chip,
 __initfunc(static int 
 ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, 
     unsigned char bus, unsigned char device_fn, long long options)) {
-    unsigned short vendor_id, device_id, command;
+    unsigned short command;
 #ifdef LINUX_1_2
     unsigned long
 #else
     unsigned int 
 #endif
        base, io_port; 
-    unsigned char irq, revision;
+    unsigned char revision;
     int error, expected_chip;
     int expected_id = -1, max_revision = -1, min_revision = -1;
-    int i;
+    int i, irq;
+    struct pci_dev *pdev = pci_find_slot(bus, device_fn);
 
     printk("scsi-ncr53c7,8xx : at PCI bus %d, device %d,  function %d\n",
        bus, (int) (device_fn & 0xf8) >> 3, 
        (int) device_fn & 7);
 
-    if (!pcibios_present()) {
-       printk("scsi-ncr53c7,8xx : not initializing due to lack of PCI BIOS,\n"
+    if (!pdev) {
+       printk("scsi-ncr53c7,8xx : not initializing -- PCI device not found,\n"
               "        try using memory, port, irq override instead.\n");
        return -1;
     }
 
-    if ((error = pcibios_read_config_word (bus, device_fn, PCI_VENDOR_ID, 
-       &vendor_id)) ||
-       (error = pcibios_read_config_word (bus, device_fn, PCI_DEVICE_ID, 
-           &device_id)) ||
-       (error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, 
+    if ((error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, 
            &command)) ||
-       (error = pcibios_read_config_dword (bus, device_fn, 
-           PCI_BASE_ADDRESS_0, &io_port)) || 
-       (error = pcibios_read_config_dword (bus, device_fn, 
-           PCI_BASE_ADDRESS_1, &base)) ||
        (error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION,
-           &revision)) ||
-       (error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE,
-           &irq))) {
+           &revision))) {
        printk ("scsi-ncr53c7,8xx : error %s not initializing due to error reading configuration space\n"
                "        perhaps you specified an incorrect PCI bus, device, or function.\n"
                , pcibios_strerror(error));
        return -1;
     }
+    io_port = pdev->base_address[0];
+    base = pdev->base_address[1];
+    irq = pdev->irq;
 
     /* If any one ever clones the NCR chips, this will have to change */
 
-    if (vendor_id != PCI_VENDOR_ID_NCR) {
+    if (pdev->vendor != PCI_VENDOR_ID_NCR) {
        printk ("scsi-ncr53c7,8xx : not initializing, 0x%04x is not NCR vendor ID\n",
-           (int) vendor_id);
+           (int) pdev->vendor);
        return -1;
     }
 
@@ -1467,14 +1460,16 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
     if ( ! (command & PCI_COMMAND_MASTER)) {
       printk("SCSI: PCI Master Bit has not been set. Setting...\n");
       command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-      pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
-      if (io_port >= 0x10000000) {
+      pci_write_config_word(pdev, PCI_COMMAND, command);
+
+      if (io_port >= 0x10000000 && is_prep ) {
              /* Mapping on PowerPC can't handle this! */
              unsigned long new_io_port;
              new_io_port = (io_port & 0x00FFFFFF) | 0x01000000;
              printk("SCSI: I/O moved from %08X to %08x\n", io_port, new_io_port);
              io_port = new_io_port;
-             pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+             pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port);
+             pdev->base_address[0] = io_port;
       }
     }
 #endif
@@ -1519,7 +1514,7 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
     }
 
     for (i = 0; i < NPCI_CHIP_IDS; ++i) {
-       if (device_id == pci_chip_ids[i].pci_device_id) {
+       if (pdev->device == pci_chip_ids[i].pci_device_id) {
            max_revision = pci_chip_ids[i].max_revision;
            min_revision = pci_chip_ids[i].min_revision;
            expected_chip = pci_chip_ids[i].chip;
@@ -1528,10 +1523,10 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
            expected_id = pci_chip_ids[i].pci_device_id;
     }
 
-    if (chip && device_id != expected_id) 
+    if (chip && pdev->device != expected_id) 
        printk ("scsi-ncr53c7,8xx : warning : device id of 0x%04x doesn't\n"
                 "                   match expected 0x%04x\n",
-           (unsigned int) device_id, (unsigned int) expected_id );
+           (unsigned int) pdev->device, (unsigned int) expected_id );
     
     if (max_revision != -1 && revision > max_revision) 
        printk ("scsi-ncr53c7,8xx : warning : revision of %d is greater than %d.\n",
@@ -1598,7 +1593,7 @@ NCR53c7xx_detect(Scsi_Host_Template *tpnt)) {
        } 
     }
 
-    if (pcibios_present()) {
+    if (pci_present()) {
        for (i = 0; i < NPCI_CHIP_IDS; ++i) 
            for (pci_index = 0;
                !pcibios_find_device (PCI_VENDOR_ID_NCR, 
index 93a30f3e9afafddaf8d9e07f271f16788a81f3eb..f123c8b2f15eaef5b919aa4f9aaa50e048fe698a 100644 (file)
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
@@ -670,6 +668,7 @@ find_host (int host) {
     return h;
 }
 
+#if 0
 /*
  * Function : request_synchronous (int host, int target)
  * 
@@ -717,6 +716,7 @@ request_synchronous (int host, int target) {
     restore_flags(flags);
     return 0;
 }
+#endif
 
 /*
  * Function : request_disconnect (int host, int on_or_off)
@@ -1121,16 +1121,12 @@ NCR53c7x0_init (struct Scsi_Host *host) {
 
 /* 
  * Function : static int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, 
- *     int chip, u32 base, int io_port, int irq, int dma,
- *     long long options, int clock);
+ *     int chip, u32 base, int io_port, int irq, int dma, long long options,
+ *     int clock);
  *
  * Purpose : initializes a NCR53c7,8x0 based on base addresses,
  *     IRQ, and DMA channel.   
  *     
- *     Useful where a new NCR chip is backwards compatible with
- *     a supported chip, but the DEVICE ID has changed so it 
- *     doesn't show up when the autoprobe does a pcibios_find_device.
- *
  * Inputs : tpnt - Template for this SCSI adapter, board - board level
  *     product, chip - 710
  * 
index a2a53f107ae5f0864e03ce783dbf0a569b004636..cbbcbf02f2d8934bca09cb1ba933c213128b491a 100644 (file)
@@ -1247,14 +1247,6 @@ struct NCR53c7x0_hostdata {
                                           digits of part number */
 
     char valid_ids[8];                 /* Valid SCSI ID's for adapter */
-    /*
-     * PCI bus, device, function, only for NCR53c8x0 chips.
-     * pci_valid indicates that the PCI configuration information
-     * is valid, and we can twiddle MAX_LAT, etc. as recommended
-     * for maximum performance in the NCR documentation.
-     */
-    unsigned char pci_bus, pci_device_fn;
-    unsigned pci_valid:1;
 
     u32 *dsp;                          /* dsp to restart with after
                                           all stacked interrupts are
index f19065027b6ddd68a556c3b1e20d2a1ca90c40fe..b21de77047106c6371c5abed33ad1cc86ae04167 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/blk.h>
@@ -35,6 +34,8 @@
  *   Robin Cutshaw (robin@xfree86.org) and is used here in a 
  *   slightly modified form.
  *
+ *  PCI detection rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
  *  For the remaining code:
  *    Copyright 1994, D. Frieauff
  *    EMail: fri@rsx42sun0.dofn.de
 #define DEF_RAE                 0    /* CNTLREG4, RAE active negation on REQ, ACK only */
 #define DEF_RADE                1    /* 1CNTLREG4, active negation on REQ, ACK and data */
 
-/*** PCI block ***/
-/* standard registers are defined in <linux/pci.h> */
-#ifndef PCI_VENDOR_ID_AMD
-#define PCI_VENDOR_ID_AMD      0x1022
-#define PCI_DEVICE_ID_AMD_SCSI  0x2020
-#endif
-#define PCI_BASE_MASK           0xFFFFFFE0
-#define PCI_COMMAND_PERREN      0x40
-#define PCI_SCRATCH_REG_0      0x40    /* 16 bits */
-#define PCI_SCRATCH_REG_1      0x42    /* 16 bits */
-#define PCI_SCRATCH_REG_2      0x44    /* 16 bits */
-#define PCI_SCRATCH_REG_3      0x46    /* 16 bits */
-#define PCI_SCRATCH_REG_4      0x48    /* 16 bits */
-#define PCI_SCRATCH_REG_5      0x4A    /* 16 bits */
-#define PCI_SCRATCH_REG_6      0x4C    /* 16 bits */
-#define PCI_SCRATCH_REG_7      0x4E    /* 16 bits */
-
 /*** SCSI block ***/
 #define CTCLREG                        0x00    /* r    current transf. count, low byte    */
 #define CTCMREG                        0x04    /* r    current transf. count, middle byte */
@@ -363,108 +347,15 @@ typedef struct _override_t {
     int max_offset;                    /* max. sync. offset, 0 = asynchronous */
     } override_t;
 
-/************ PCI stuff *************/
-#define AM53C974_PCIREG_OPEN()                    outb(0xF1, 0xCF8); outb(0, 0xCFA)
-#define AM53C974_PCIREG_CLOSE()                   outb(0, 0xCF8)
-#define AM53C974_PCIREG_READ_BYTE(instance,a)     ( inb((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_READ_WORD(instance,a)     ( inw((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_READ_DWORD(instance,a)    ( inl((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_BYTE(instance,x,a)  ( outb((x), (a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_WORD(instance,x,a)  ( outw((x), (a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_DWORD(instance,x,a) ( outl((x), (a) + (instance)->io_port) )
-
-typedef struct _pci_config_t {
-    /* start of official PCI config space header */
-    union {
-        unsigned int device_vendor;
-       struct {
-         unsigned short vendor;
-         unsigned short device;
-         } dv;
-        } dv_id;
-#define _device_vendor dv_id.device_vendor
-#define _vendor dv_id.dv.vendor
-#define _device dv_id.dv.device
-    union {
-        unsigned int status_command;
-       struct {
-         unsigned short command;
-         unsigned short status;
-         } sc;
-        } stat_cmd;
-#define _status_command stat_cmd.status_command
-#define _command stat_cmd.sc.command
-#define _status  stat_cmd.sc.status
-    union {
-        unsigned int class_revision;
-       struct {
-           unsigned char rev_id;
-           unsigned char prog_if;
-           unsigned char sub_class;
-           unsigned char base_class;
-       } cr;
-    } class_rev;
-#define _class_revision class_rev.class_revision
-#define _rev_id     class_rev.cr.rev_id
-#define _prog_if    class_rev.cr.prog_if
-#define _sub_class  class_rev.cr.sub_class
-#define _base_class class_rev.cr.base_class
-    union {
-        unsigned int bist_header_latency_cache;
-       struct {
-           unsigned char cache_line_size;
-           unsigned char latency_timer;
-           unsigned char header_type;
-           unsigned char bist;
-       } bhlc;
-    } bhlc;
-#define _bist_header_latency_cache bhlc.bist_header_latency_cache
-#define _cache_line_size bhlc.bhlc.cache_line_size
-#define _latency_timer   bhlc.bhlc.latency_timer
-#define _header_type     bhlc.bhlc.header_type
-#define _bist            bhlc.bhlc.bist
-    unsigned int _base0;
-    unsigned int _base1;
-    unsigned int _base2;
-    unsigned int _base3;
-    unsigned int _base4;
-    unsigned int _base5;
-    unsigned int rsvd1;
-    unsigned int rsvd2;
-    unsigned int _baserom;
-    unsigned int rsvd3;
-    unsigned int rsvd4;
-    union {
-        unsigned int max_min_ipin_iline;
-       struct {
-           unsigned char int_line;
-           unsigned char int_pin;
-           unsigned char min_gnt;
-           unsigned char max_lat;
-       } mmii;
-    } mmii;
-#define _max_min_ipin_iline mmii.max_min_ipin_iline
-#define _int_line mmii.mmii.int_line
-#define _int_pin  mmii.mmii.int_pin
-#define _min_gnt  mmii.mmii.min_gnt
-#define _max_lat  mmii.mmii.max_lat
-    /* end of official PCI config space header */
-    unsigned short _ioaddr; /* config type 1 - private I/O addr    */
-    unsigned int _pcibus;  /* config type 2 - private bus id      */
-    unsigned int _cardnum; /* config type 2 - private card number */
-} pci_config_t;
-
 
 #ifdef AM53C974_DEBUG
-static void AM53C974_print_pci(struct Scsi_Host *instance);
 static void AM53C974_print_phase(struct Scsi_Host *instance);
 static void AM53C974_print_queues(struct Scsi_Host *instance);
 #endif /* AM53C974_DEBUG */
 static void AM53C974_print(struct Scsi_Host *instance);
 static void AM53C974_keywait(void);
-static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt);
-static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt);
-static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config);
+static __inline__ int AM53C974_pci_detect(Scsi_Host_Template *tpnt);
+static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev);
 static void AM53C974_config_after_reset(struct Scsi_Host *instance);
 static __inline__ void initialize_SCp(Scsi_Cmnd *cmd);
 static __inline__ void run_main(void);
@@ -502,52 +393,6 @@ struct proc_dir_entry proc_scsi_am53c974 = {
 #ifdef AM53C974_DEBUG
 static int deb_stop = 1;
 
-/**************************************************************************
- * Function : void AM53C974_print_pci(struct Scsi_Host *instance)
- *
- * Purpose : dump the PCI registers for debugging purposes
- *
- * Input : instance - which AM53C974
- **************************************************************************/
-static void AM53C974_print_pci(struct Scsi_Host *instance)
-{
-int            i;
-unsigned short vendor_id, device_id, command, status, scratch[8];
-unsigned long  class_revision, base; 
-unsigned char  irq, cache_line_size, latency_timer, header_type;
-
-AM53C974_PCIREG_OPEN();
-
-for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i);
-vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID);
-device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID);
-command   = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND);
-status    = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS);
-class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION);
-cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE);
-latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER);
-header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE);
-base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0);
-irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE);
-
-AM53C974_PCIREG_CLOSE();
-
-
-printk("------------- start of PCI register dump -------------\n");
-printk("PCI_VENDOR_ID:       0x%x\n", vendor_id);
-printk("PCI_DEVICE_ID:       0x%x\n", device_id);
-printk("PCI_COMMAND:         0x%x\n", command);
-printk("PCI_STATUS:          0x%x\n", status);
-printk("PCI_CLASS_REVISION:  0x%lx\n", class_revision);
-printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size);
-printk("PCI_LATENCY_TIMER:   0x%x\n", latency_timer);
-printk("PCI_HEADER_TYPE:     0x%x\n", header_type);
-printk("PCI_BASE_ADDRESS_0:  0x%lx\n", base);
-printk("PCI_INTERRUPT_LINE:  %d\n", irq);
-for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d:       0x%x\n", i, scratch[i]);
-printk("------------- end of PCI register dump -------------\n\n");
-}
-
 static struct {
     unsigned char value;
     char *name;
@@ -732,7 +577,7 @@ if (ints[0] < 4)
 
 #if defined (CONFIG_PCI)
 /**************************************************************************
-* Function : int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
+* Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt)
 *
 * Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios
 *
@@ -740,160 +585,33 @@ if (ints[0] < 4)
 * 
 * Returns : number of host adapters detected
 **************************************************************************/
-static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
+static __inline__ int AM53C974_pci_detect(Scsi_Host_Template *tpnt)
 {
 int count = 0;        /* number of boards detected */
-int pci_index;
-pci_config_t pci_config;
-
-for (pci_index = 0; pci_index <= 16; ++pci_index) {
-    unsigned char pci_bus, pci_device_fn;
-    if (pcibios_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pci_index, &pci_bus, &pci_device_fn) != 0)
-       break;
-
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &pci_config._vendor);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &pci_config._device);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_config._command);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_STATUS, &pci_config._status);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_CLASS_REVISION, &pci_config._class_revision);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_CACHE_LINE_SIZE, &pci_config._cache_line_size);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_config._latency_timer);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_HEADER_TYPE, &pci_config._header_type);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_BIST, &pci_config._bist);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_config._base0);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_config._base1);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_config._base2);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_config._base3);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_config._base4);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_config._base5);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_ROM_ADDRESS, &pci_config._baserom);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_config._int_line);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_PIN, &pci_config._int_pin);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MIN_GNT, &pci_config._min_gnt);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MAX_LAT, &pci_config._max_lat);
-    pci_config._pcibus = 0xFFFFFFFF;
-    pci_config._cardnum = 0xFFFFFFFF;
+struct pci_dev *pdev = NULL;
+unsigned short command;
+
+while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pdev))) {
+    pci_read_config_word(pdev, PCI_COMMAND, &command);
+
     /* check whether device is I/O mapped -- should be */
-    if (!(pci_config._command & PCI_COMMAND_IO)) continue;
+    if (!(command & PCI_COMMAND_IO)) continue;
 
     /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
        to set the PCI Master Enable Bit if needed. 
        (from Mark Stockton <marks@schooner.sys.hou.compaq.com>) */
-    if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-       pci_config._command |= PCI_COMMAND_MASTER;
+    if (!(command & PCI_COMMAND_MASTER)) {
+       command |= PCI_COMMAND_MASTER;
        printk("PCI Master Bit has not been set. Setting...\n");
-       pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_config._command); }
+       pci_write_config_word(pdev, PCI_COMMAND, command); }
 
     /* everything seems OK now, so initialize */
-    if (AM53C974_init(tpnt, pci_config)) count++ ;
+    if (AM53C974_init(tpnt, pdev)) count++ ;
     }
 return (count);
 }
 #endif
 
-/**************************************************************************
-* Function : int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
-*
-* Purpose : detects and initializes AM53C974 SCSI chips using PCI config 2 
-*
-* Inputs : tpnt - host template
-* 
-* Returns : number of host adapters detected
-*
-* NOTE : This code assumes the controller on PCI bus 0.
-*
-* Origin: Robin Cutshaw (robin@xfree86.org)
-**************************************************************************/
-static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
-{
-int          count = 0;                /* number of boards detected */
-pci_config_t pci_config;
-
-/* first try PCI config method 1 */
-for (pci_config._pcibus = 0; pci_config._pcibus < 0x10; pci_config._pcibus++) {
-    for (pci_config._cardnum = 0; pci_config._cardnum < 0x20; pci_config._cardnum++) {
-        unsigned long config_cmd;
-       config_cmd = 0x80000000 | (pci_config._pcibus<<16) | (pci_config._cardnum<<11);
-
-        outl(config_cmd, 0xCF8);         /* ioreg 0 */
-        pci_config._device_vendor = inl(0xCFC);
-
-        if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) {
-           outl(config_cmd | PCI_COMMAND, 0xCF8); pci_config._status_command  = inl(0xCFC);
-           outl(config_cmd | PCI_CLASS_REVISION, 0xCF8); pci_config._class_revision = inl(0xCFC);
-           outl(config_cmd | PCI_CACHE_LINE_SIZE, 0xCF8); pci_config._bist_header_latency_cache = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_0, 0xCF8); pci_config._base0 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_1, 0xCF8); pci_config._base1 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_2, 0xCF8); pci_config._base2 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_3, 0xCF8); pci_config._base3 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_4, 0xCF8); pci_config._base4 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_5, 0xCF8); pci_config._base5 = inl(0xCFC);
-           outl(config_cmd | PCI_ROM_ADDRESS, 0xCF8); pci_config._baserom = inl(0xCFC);
-           outl(config_cmd | PCI_INTERRUPT_LINE, 0xCF8); pci_config._max_min_ipin_iline = inl(0xCFC);
-
-           /* check whether device is I/O mapped -- should be */
-           if (!(pci_config._command & PCI_COMMAND_IO)) continue;
-
-           /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
-              to set the PCI Master Enable Bit if needed. 
-              From Mark Stockton <marks@schooner.sys.hou.compaq.com> */
-           if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-              pci_config._command |= PCI_COMMAND_MASTER;
-              printk("Config 1; PCI Master Bit has not been set. Setting...\n");
-              outl(config_cmd | PCI_COMMAND, 0xCF8); outw(pci_config._command, 0xCFC); }
-
-           /* everything seems OK now, so initialize */
-           if (AM53C974_init(tpnt, pci_config)) count++ ;
-           }
-        }
-    }
-outb(0, 0xCF8); /* is this really necessary? */
-
-/* try PCI config method 2, if no device was detected by method 1 */
-if (!count) {
-   AM53C974_PCIREG_OPEN();
-
-   pci_config._pcibus = 0xFFFFFFFF;
-   pci_config._cardnum = 0xFFFFFFFF;
-
-   for (pci_config._ioaddr = 0xC000; pci_config._ioaddr < 0xD000; pci_config._ioaddr += 0x0100) {
-       pci_config._device_vendor = inl(pci_config._ioaddr);
-
-       if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) {
-          pci_config._status_command = inl(pci_config._ioaddr + PCI_COMMAND);
-          pci_config._class_revision = inl(pci_config._ioaddr + PCI_CLASS_REVISION);
-          pci_config._bist_header_latency_cache = inl(pci_config._ioaddr + PCI_CACHE_LINE_SIZE);
-          pci_config._base0 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_0);
-          pci_config._base1 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_1);
-          pci_config._base2 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_2);
-          pci_config._base3 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_3);
-          pci_config._base4 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_4);
-          pci_config._base5 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_5);
-          pci_config._baserom = inl(pci_config._ioaddr + PCI_ROM_ADDRESS);
-          pci_config._max_min_ipin_iline = inl(pci_config._ioaddr + PCI_INTERRUPT_LINE);
-
-          /* check whether device is I/O mapped -- should be */
-          if (!(pci_config._command & PCI_COMMAND_IO)) continue;
-
-          /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
-             to set the PCI Master Enable Bit if needed.
-             From Mark Stockton <marks@schooner.sys.hou.compaq.com> */
-          if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-              pci_config._command |= PCI_COMMAND_MASTER;
-              printk("Config 2; PCI Master Bit has not been set. Setting...\n");
-              outw(pci_config._command, pci_config._ioaddr + PCI_COMMAND); }
-
-          /* everything seems OK now, so initialize */
-          if (AM53C974_init(tpnt, pci_config)) count++ ;
-          }
-       }
-   AM53C974_PCIREG_CLOSE();
-   }
-
-return(count);
-}
-
 /**************************************************************************
 * Function : int AM53C974_detect(Scsi_Host_Template *tpnt)
 *
@@ -905,21 +623,19 @@ return(count);
 **************************************************************************/
 __initfunc(int AM53C974_detect(Scsi_Host_Template *tpnt))
 {
-int count;        /* number of boards detected */
+int count = 0;        /* number of boards detected */
 
 tpnt->proc_dir = &proc_scsi_am53c974;
 
 #if defined (CONFIG_PCI)
-if (pcibios_present())
-   count = AM53C974_bios_detect(tpnt);
-  else
+if (pci_present())
+   count = AM53C974_pci_detect(tpnt);
 #endif
-count = AM53C974_nobios_detect(tpnt);
 return (count);
 }
 
 /**************************************************************************
-* Function : int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config)
+* Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev)
 *
 * Purpose : initializes instance and corresponding AM53/79C974 chip,
 *
@@ -932,7 +648,7 @@ return (count);
 *       set up by the BIOS (as reflected by contents of register CNTLREG1).
 *       This is the only BIOS assistance we need.
 **************************************************************************/
-__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config))
+__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev))
 {
 AM53C974_local_declare();
 int                      i, j;
@@ -947,9 +663,8 @@ struct AM53C974_hostdata *hostdata;
 instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata));
 hostdata = (struct AM53C974_hostdata *)instance->hostdata;
 instance->base = NULL;
-instance->io_port = pci_config._base0 & (pci_config._base0 & 0x1 ? 
-                                         0xFFFFFFFC : 0xFFFFFFF0);
-instance->irq = pci_config._int_line;
+instance->io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+instance->irq = pdev->irq;
 instance->dma_channel = -1;
 AM53C974_setio(instance);
 
index 861d6efb238db7e7d8182a002b700e473436d039..8c48f0ff3e35ac324992a42f35d7ab3f74208654 100644 (file)
@@ -1,4 +1,11 @@
 
+UPDATE NEWS: version 1.32 - 28 Mar 98
+
+   Removed the check for legal IN2000 hardware versions:
+   It appears that the driver works fine with serial
+   EPROMs (the 8-pin chip that defines hardware rev) as
+   old as 2.1, so we'll assume that all cards are OK.
+
 UPDATE NEWS: version 1.31 - 6 Jul 97
 
    Fixed a bug that caused incorrect SCSI status bytes to be
index 7839a2399a40a1d40312721bd33b67c21544165b..5c6cbcd1f974c4793dc8b17a7b79e2dadde67c20 100644 (file)
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
@@ -625,49 +624,6 @@ struct seeprom_config {
  */
 #define aic7xxx_position(cmd)  ((cmd)->SCp.have_data_in)
 
-/*
- * "Static" structures. Note that these are NOT initialized
- * to zero inside the kernel - we have to initialize them all
- * explicitly.
- *
- * We support multiple adapter cards per interrupt, but keep a
- * linked list of Scsi_Host structures for each IRQ.  On an interrupt,
- * use the IRQ as an index into aic7xxx_boards[] to locate the card
- * information.
- */
-static struct Scsi_Host *aic7xxx_boards[NR_IRQS + 1];
-
-/*
- * When we detect and register the card, it is possible to
- * have the card raise a spurious interrupt.  Because we need
- * to support multiple cards, we cannot tell which card caused
- * the spurious interrupt.  And, we might not even have added
- * the card info to the linked list at the time the spurious
- * interrupt gets raised.  This variable is suppose to keep track
- * of when we are registering a card and how many spurious
- * interrupts we have encountered.
- *
- *   0 - do not allow spurious interrupts.
- *   1 - allow 1 spurious interrupt
- *   2 - have 1 spurious interrupt, do not allow any more.
- *
- * I've made it an integer instead of a boolean in case we
- * want to allow more than one spurious interrupt for debugging
- * purposes.  Otherwise, it could just go from true to false to
- * true (or something like that).
- *
- * When the driver detects the cards, we'll set the count to 1
- * for each card detection and registration.  After the registration
- * of a card completes, we'll set the count back to 0.  So far, it
- * seems to be enough to allow a spurious interrupt only during
- * card registration; if a spurious interrupt is going to occur,
- * this is where it happens.
- *
- * We should be able to find a way to avoid getting the spurious
- * interrupt.  But until we do, we have to keep this ugly code.
- */
-static int aic7xxx_spurious_count;
-
 /*
  * As of Linux 2.1, the mid-level SCSI code uses virtual addresses
  * in the scatter-gather lists.  We need to convert the virtual
@@ -746,11 +702,11 @@ struct aic7xxx_scb {
         struct aic7xxx_scb    *q_next;        /* next scb in queue */
        scb_flag_type          flags;         /* current state of scb */
        struct hw_scatterlist *sg_list;       /* SG list in adapter format */
-        unsigned char          sg_count;
        unsigned char          sense_cmd[6];  /*
                                                * Allocate 6 characters for
                                                * sense command.
                                                */
+        unsigned char          sg_count;
 };
 
 /*
@@ -792,13 +748,14 @@ typedef struct {
  */
 struct aic7xxx_host {
   struct Scsi_Host        *host;             /* pointer to scsi host */
+  struct aic7xxx_host     *next;             /* pointer to next aic7xxx device */
   int                      host_no;          /* SCSI host number */
   int                      instance;         /* aic7xxx instance number */
   int                      scsi_id;          /* host adapter SCSI ID */
   int                      scsi_id_b;        /*   channel B for twin adapters */
   int                      irq;              /* IRQ for this adapter */
-  int                      base;             /* card base address */
-  unsigned int             mbase;            /* I/O memory address */
+  unsigned long            base;             /* card base address */
+  unsigned long            mbase;            /* I/O memory address */
   volatile unsigned char  *maddr;            /* memory mapped address */
 #define A_SCANNED               0x0001
 #define B_SCANNED               0x0002
@@ -833,7 +790,6 @@ struct aic7xxx_host {
   unsigned char            qfullcount;
   unsigned char            cmdoutcnt;
   unsigned char            curqincnt;
-  struct Scsi_Host        *next;             /* allow for multiple IRQs */
   unsigned char            activescbs;       /* active scbs */
   scb_queue_type           waiting_scbs;     /*
                                               * SCBs waiting for space in
@@ -923,15 +879,15 @@ debug_scb(struct aic7xxx_scb *scb)
     hscb->control,
     hscb->target_channel_lun,
     hscb->SCSI_cmd_length,
-    hscb->SCSI_cmd_pointer );
+    le32_to_cpu(hscb->SCSI_cmd_pointer) );
   printk("        datlen:%d data:0x%lx segs:0x%x segp:0x%lx\n",
-    hscb->data_count,
-    hscb->data_pointer,
+    le32_to_cpu(hscb->data_count),
+    le32_to_cpu(hscb->data_pointer),
     hscb->SG_segment_count,
-    hscb->SG_list_pointer);
+    le32_to_cpu(hscb->SG_list_pointer));
   printk("        sg_addr:%lx sg_len:%ld\n",
-    hscb->sg_list[0].address,
-    hscb->sg_list[0].length);
+    le32_to_cpu(hscb->sg_list[0].address),
+    le32_to_cpu(hscb->sg_list[0].length));
 }
 #endif
 
@@ -963,6 +919,7 @@ static int aic7xxx_irq_trigger = -1;         /*
                                               */
 static int aic7xxx_enable_ultra = 0;         /* enable ultra SCSI speeds */
 static int aic7xxx_verbose = 0;                     /* verbose messages */
+static struct aic7xxx_host *first_aic7xxx = NULL; /* list of all our devices */
 
 
 /****************************************************************************
@@ -995,7 +952,7 @@ aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size)
 {
   if (p->maddr != NULL)
   {
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__powerpc__)
     int i;
 
     for (i=0; i < size; i++)
@@ -2300,7 +2257,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, char channel,
 
        busy_scb = p->scb_data->scb_array[busy_scbid];
   
-       next_scbid = busy_scb->hscb->data_count >> 24;
+       next_scbid = le32_to_cpu(busy_scb->hscb->data_count) >> 24;
 
        if (next_scbid == SCB_LIST_NULL)
         {
@@ -2492,8 +2449,12 @@ aic7xxx_clear_intstat(struct aic7xxx_host *p)
 static void
 aic7xxx_reset_current_bus(struct aic7xxx_host *p)
 {
+  unsigned long processor_flags;
   unsigned char scsiseq;
 
+  save_flags(processor_flags);
+  cli();
+
   /* Disable reset interrupts. */
   outb(inb(p->base + SIMODE1) & ~ENSCSIRST, p->base + SIMODE1);
 
@@ -2512,6 +2473,8 @@ aic7xxx_reset_current_bus(struct aic7xxx_host *p)
   outb(inb(p->base + SIMODE1) | ENSCSIRST, p->base + SIMODE1);
 
   udelay(1000);
+
+  restore_flags(processor_flags);
 }
 
 /*+F*************************************************************************
@@ -3257,8 +3220,8 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
        if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
        {
           printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-                "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%x.\n", p->host_no,
-                intstat, scb_index, scb->flags, (unsigned int) scb->cmd);
+                "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%lx.\n", p->host_no,
+                intstat, scb_index, scb->flags, (unsigned long) scb->cmd);
        }
        else
        {
@@ -3294,8 +3257,8 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
                scb->sense_cmd[1] = (cmd->lun << 5);
                scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
 
-               scb->sg_list[0].address = VIRT_TO_BUS(&cmd->sense_buffer);
-               scb->sg_list[0].length = sizeof(cmd->sense_buffer);
+               scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(&cmd->sense_buffer));
+               scb->sg_list[0].length = cpu_to_le32(sizeof(cmd->sense_buffer));
                cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
 
                 /*
@@ -3308,18 +3271,15 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
                hscb->SG_segment_count = 1;
 
                addr = VIRT_TO_BUS(&scb->sg_list[0]);
-               memcpy(&hscb->SG_list_pointer, &addr,
-                      sizeof(hscb->SG_list_pointer));
+                hscb->SG_list_pointer = cpu_to_le32(addr);
+                hscb->data_pointer = scb->sg_list[0].address;
 
-               memcpy(&hscb->data_pointer, &(scb->sg_list[0].address),
-                      sizeof(hscb->data_pointer));
                /* Maintain SCB_LINKED_NEXT */
-               hscb->data_count &= 0xFF000000;
+               hscb->data_count &= cpu_to_le32(0xFF000000);
                hscb->data_count |= scb->sg_list[0].length;
 
                addr = VIRT_TO_BUS(scb->sense_cmd);
-               memcpy(&hscb->SCSI_cmd_pointer, &addr,
-                      sizeof(hscb->SCSI_cmd_pointer));
+                hscb->SCSI_cmd_pointer = cpu_to_le32(addr);
                hscb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
 
                 scb->sg_count = hscb->SG_segment_count;
@@ -3496,7 +3456,9 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
         for (i = 0; i < scb->sg_count; i++)
         {
           printk(KERN_INFO "     sg[%d] - Addr 0x%x : Length %d\n",
-                 i, scb->sg_list[i].address, scb->sg_list[i].length);
+                 i,
+                 le32_to_cpu(scb->sg_list[i].address),
+                 le32_to_cpu(scb->sg_list[i].length));
         }
        /*
         * XXX - What do we really want to do on an overrun?  The
@@ -3835,43 +3797,21 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat)
  *
  * Description:
  *   SCSI controller interrupt handler.
- *
- *   NOTE: Since we declared this using SA_INTERRUPT, interrupts should
- *         be disabled all through this function unless we say otherwise.
  *-F*************************************************************************/
 static void
 aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct aic7xxx_host *p;
+  struct aic7xxx_host *p = (struct aic7xxx_host *) dev_id;
   unsigned char intstat;
   unsigned long flags;
 
-  p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
-
-  /*
-   * Search for the host with a pending interrupt.  If we can't find
-   * one, then we've encountered a spurious interrupt.
-   */
-  while ((p != NULL) && !(inb(p->base + INTSTAT) & INT_PEND))
-  {
-    if (p->next == NULL)
-    {
-      p = NULL;
-    }
-    else
-    {
-      p = (struct aic7xxx_host *) p->next->hostdata;
-    }
-  }
-
-  if (p == NULL)
-    return;
-
   /*
    * Handle all the interrupt sources - especially for SCSI
    * interrupts, we won't get a second chance at them.
    */
   intstat = inb(p->base + INTSTAT);
+  if (! (intstat & INT_PEND))  /* Interrupt for another device */
+    return;
 
   /*
    * Keep track of interrupts for /proc/scsi
@@ -4181,6 +4121,7 @@ aic7xxx_select_queue_depth(struct Scsi_Host *host,
   }
 }
 
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_probe
@@ -4258,6 +4199,7 @@ aic7xxx_probe(int slot, int base, aha_status_type *bios)
 
   return (AIC_NONE);
 }
+#endif /* __sparc_v9__ or __powerpc__ */
 
 /*+F*************************************************************************
  * Function:
@@ -4962,7 +4904,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
 {
   int i;
   unsigned char sblkctl, flags = 0;
-  int max_targets;
+  int max_targets, irq_flags = 0;
   int found = 1;
   char channel_ids[] = {'A', 'B', 'C'};
   unsigned char target_settings;
@@ -5066,7 +5008,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
   p->host = host;
   p->host_no = host->host_no;
   p->isr_count = 0;
-  p->next = NULL;
   p->completeq.head = NULL;
   p->completeq.tail = NULL;
   scbq_init(&p->scb_data->free_scbs);
@@ -5079,53 +5020,20 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
     p->device_status[i].active_cmds = 0;
     p->device_status[i].last_reset = 0;
   }
-  if (aic7xxx_boards[p->irq] == NULL)
-  {
-    int result;
-    int irq_flags = 0;
 
+  /*
+   * Request an IRQ for the board. Only allow sharing IRQs with PCI devices.
+   */
 #ifdef AIC7XXX_OLD_ISR_TYPE
-    irg_flags = SA_INTERRUPT;
+  irq_flags = SA_INTERRUPT;
 #endif
-    /*
-     * Warning! This must be done before requesting the irq.  It is
-     * possible for some boards to raise an interrupt as soon as
-     * they are enabled.  So when we request the irq from the Linux
-     * kernel, an interrupt is triggered immediately.  Therefore, we
-     * must ensure the board data is correctly set before the request.
-     */
-    aic7xxx_boards[p->irq] = host;
-
-    /*
-     * Register IRQ with the kernel.  Only allow sharing IRQs with
-     * PCI devices.
-     */
-    if (p->chip_class == AIC_777x)
-    {
-      result = (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", NULL));
-    }
-    else
-    {
-      result = (request_irq(p->irq, aic7xxx_isr, irq_flags | SA_SHIRQ,
-                "aic7xxx", NULL));
-    }
-    if (result < 0)
-    {
-      printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n",
-             p->irq);
-      aic7xxx_boards[p->irq] = NULL;
-      return (0);
-    }
-  }
-  else
+  if (p->chip_class != AIC_777x)
+    irq_flags |= SA_SHIRQ;
+  if (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", p) < 0)
   {
-    /*
-     * We have found a host adapter sharing an IRQ of a previously
-     * registered host adapter. Add this host adapter's Scsi_Host
-     * to the beginning of the linked list of hosts at the same IRQ.
-     */
-    p->next = aic7xxx_boards[p->irq];
-    aic7xxx_boards[p->irq] = host;
+    printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n",
+           p->irq);
+    return (0);
   }
 
   /*
@@ -5325,17 +5233,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
       printk("aic7xxx: Unable to allocate hardware SCB array; "
              "failing detection.\n");
       release_region(p->base, MAXREG - MINREG);
-      /*
-       * Ensure that we only free the IRQ when there is _not_ another
-       * aic7xxx adapter sharing this IRQ.  The adapters are always
-       * added to the beginning of the list, so we can grab the next
-       * pointer and place it back in the board array.
-       */
-      if (p->next == NULL)
-      {
-        free_irq(p->irq, aic7xxx_isr);
-      }
-      aic7xxx_boards[p->irq] = p->next;
+      free_irq(p->irq, p);
       return(0);
     }
     /* At least the control byte of each SCB needs to be 0. */
@@ -5399,6 +5297,12 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
    */
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
+  /*
+   * Add it to our list of adapters.
+   */
+  p->next = first_aic7xxx;
+  first_aic7xxx = p;
+
   return (found);
 }
 
@@ -5453,7 +5357,7 @@ aic7xxx_chip_reset(struct aic7xxx_host *p)
  *   and a pointer to a aic7xxx_host struct upon success.
  *-F*************************************************************************/
 static struct aic7xxx_host *
-aic7xxx_alloc(Scsi_Host_Template *sht, unsigned int base, unsigned int mbase,
+aic7xxx_alloc(Scsi_Host_Template *sht, unsigned long base, unsigned long mbase,
     aha_chip_type chip_type, int flags, scb_data_type *scb_data)
 {
   struct aic7xxx_host *p = NULL;
@@ -5768,36 +5672,23 @@ int
 aic7xxx_detect(Scsi_Host_Template *template)
 {
   int found = 0;
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
   aha_status_type adapter_bios;
+  unsigned char hcntrl, hostconf, irq = 0;
+  int slot, base;
+#endif
   aha_chip_class_type chip_class;
   aha_chip_type chip_type;
-  int slot, base;
   int chan_num = 0;
-  unsigned char hcntrl, sxfrctl1, sblkctl, hostconf, irq = 0;
+  unsigned char sxfrctl1, sblkctl;
   int i;
   struct aic7xxx_host *p;
 
-  /*
-   * Since we may allow sharing of IRQs, it is imperative
-   * that we "null-out" the aic7xxx_boards array. It is
-   * not guaranteed to be initialized to 0 (NULL). We use
-   * a NULL entry to indicate that no prior hosts have
-   * been found/registered for that IRQ.
-   */
-  for (i = 0; i < NUMBER(aic7xxx_boards); i++)
-  {
-    aic7xxx_boards[i] = NULL;
-  }
-
   template->proc_dir = &proc_scsi_aic7xxx;
   template->name = aic7xxx_info(NULL);
   template->sg_tablesize = AIC7XXX_MAX_SG;
 
-  /*
-   * Initialize the spurious count to 0.
-   */
-  aic7xxx_spurious_count = 0;
-
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
   /*
    * EISA/VL-bus card signature probe.
    */
@@ -5833,11 +5724,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
           break;
       }
 
-      /*
-       * We found a card, allow 1 spurious interrupt.
-       */
-      aic7xxx_spurious_count = 1;
-
       /*
        * Pause the card preserving the IRQ type.  Allow the operator
        * to override the IRQ trigger.
@@ -5925,7 +5811,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
           default:  /* Won't get here. */
             break;
         }
-        printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, IRQ %d (%s), ",
+        printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s), ",
                (p->flags & USE_DEFAULTS) ? "dis" : "en", p->base, p->irq,
                (p->pause & IRQMS) ? "level sensitive" : "edge triggered");
         /*
@@ -5984,18 +5870,15 @@ aic7xxx_detect(Scsi_Host_Template *template)
           aic7xxx_free(p);
         }
       }
-      /*
-       * Disallow spurious interrupts.
-       */
-      aic7xxx_spurious_count = 0;
     }
   }
+#endif /* __sparc_v9__ or __powerpc__ */
 
 #ifdef CONFIG_PCI
   /*
    * PCI-bus probe.
    */
-  if (pcibios_present())
+  if (pci_present())
   {
     struct
     {
@@ -6021,102 +5904,94 @@ aic7xxx_detect(Scsi_Host_Template *template)
     };
 
     int error, flags;
-    int done = 0;
-    unsigned int iobase, mbase;
     unsigned short index = 0;
-    unsigned char pci_bus, pci_device_fn;
     unsigned char ultra_enb = 0;
     unsigned int  devconfig, class_revid;
     scb_data_type *shared_scb_data = NULL;
     char rev_id[] = {'B', 'C', 'D'};
+    struct pci_dev *pdev = NULL;
+    unsigned long iobase, mbase;
+    unsigned int irq;
 
     for (i = 0; i < NUMBER(aic7xxx_pci_devices); i++)
-    {
-      done = FALSE;
-      while (!done)
+      while ((pdev = pci_find_device(aic7xxx_pci_devices[i].vendor_id,
+                                     aic7xxx_pci_devices[i].device_id,
+                                   pdev)))
       {
-        if (pcibios_find_device(aic7xxx_pci_devices[i].vendor_id,
-                                aic7xxx_pci_devices[i].device_id,
-                                index, &pci_bus, &pci_device_fn))
-        {
-          index = 0;
-          done = TRUE;
-        }
-        else  /* Found an Adaptec PCI device. */
+        chip_class = aic7xxx_pci_devices[i].chip_class;
+        chip_type = aic7xxx_pci_devices[i].chip_type;
+        chan_num = 0;
+        flags = 0;
+        switch (aic7xxx_pci_devices[i].chip_type)
         {
-          chip_class = aic7xxx_pci_devices[i].chip_class;
-          chip_type = aic7xxx_pci_devices[i].chip_type;
-          chan_num = 0;
-          flags = 0;
-          switch (aic7xxx_pci_devices[i].chip_type)
-          {
-            case AIC_7855:
-              flags |= USE_DEFAULTS;
-              break;
-
-            case AIC_7872:  /* 3940 */
-            case AIC_7882:  /* 3940-Ultra */
-              flags |= MULTI_CHANNEL;
-              chan_num = number_of_3940s & 0x1;  /* Has 2 controllers */
-              number_of_3940s++;
-              break;
-
-            case AIC_7873:  /* 3985 */
-            case AIC_7883:  /* 3985-Ultra */
-              chan_num = number_of_3985s;  /* Has 3 controllers */
-              flags |= MULTI_CHANNEL;
-              number_of_3985s++;
-              if (number_of_3985s == 3)
-              {
-                number_of_3985s = 0;
-                shared_scb_data = NULL;
-              }
-              break;
+          case AIC_7855:
+            flags |= USE_DEFAULTS;
+            break;
 
-            default:
-              break;
-          }
+          case AIC_7872:  /* 3940 */
+          case AIC_7882:  /* 3940-Ultra */
+            flags |= MULTI_CHANNEL;
+            chan_num = number_of_3940s & 0x1;  /* Has 2 controllers */
+            number_of_3940s++;
+            break;
 
-          /*
-           * Read sundry information from PCI BIOS.
-           */
-          error = pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                            PCI_BASE_ADDRESS_0, &iobase);
-          error += pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                            PCI_INTERRUPT_LINE, &irq);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                            PCI_BASE_ADDRESS_1, &mbase);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                             DEVCONFIG, &devconfig);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                             CLASS_PROGIF_REVID, &class_revid);
-
-          printk("aic7xxx: <%s> at PCI %d\n",
-                 board_names[chip_type], PCI_SLOT(pci_device_fn));
+          case AIC_7873:  /* 3985 */
+          case AIC_7883:  /* 3985-Ultra */
+            chan_num = number_of_3985s;  /* Has 3 controllers */
+            flags |= MULTI_CHANNEL;
+            number_of_3985s++;
+            if (number_of_3985s == 3)
+            {
+              number_of_3985s = 0;
+              shared_scb_data = NULL;
+            }
+            break;
 
-          /*
-           * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so
-           * we mask it off.
-           */
-          iobase &= PCI_BASE_ADDRESS_IO_MASK;
+          default:
+            break;
+        }
 
-          p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags,
-                            shared_scb_data);
+        /*
+         * Read sundry information from PCI BIOS.
+         */
+       iobase = pdev->base_address[0];
+       mbase = pdev->base_address[1];
+       irq = pdev->irq;
+        error = pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
+        error += pci_read_config_dword(pdev, CLASS_PROGIF_REVID, &class_revid);
+        printk("aic7xxx: <%s> at PCI %d\n",
+               board_names[chip_type], PCI_SLOT(pdev->devfn));
 
-          if (p == NULL)
-          {
-            printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
-            continue;
-          }
+        /*
+         * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so
+         * we mask it off.
+         */
+       iobase &= PCI_BASE_ADDRESS_IO_MASK;
+        p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags, shared_scb_data);
+        if(p) {
+          unsigned short pci_command;
+
+          /* Enable bus mastering since this thing must do DMA. */
+          pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+          pci_command |= PCI_COMMAND_MASTER;
+#ifdef __powerpc__
+          /* Enable I/O and memory-space access */
+          pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+#endif
+          pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+        } else {
+          printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+          continue;
+        }
 
-          /* Remember to set the channel number, irq, and chip class. */
-          p->chan_num = chan_num;
-          p->irq = irq;
-          p->chip_class = chip_class;
+        /* Remember to set the channel number, irq, and chip class. */
+        p->chan_num = chan_num;
+        p->irq = irq;
+        p->chip_class = chip_class;
 #ifdef AIC7XXX_PAGE_ENABLE
-          p->flags |= PAGE_ENABLED;
+        p->flags |= PAGE_ENABLED;
 #endif
-          p->instance = found;
+        p->instance = found;
 
           /*
            * Remember how the card was setup in case there is no seeprom.
@@ -6236,8 +6111,8 @@ aic7xxx_detect(Scsi_Host_Template *template)
           /*
            * Print some additional information about the adapter.
            */
-          printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, "
-                 "IO Mem 0x%x, IRQ %d",
+          printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, "
+                 "IO Mem 0x%lx, IRQ %x",
                  (p->flags & USE_DEFAULTS) ? "dis" : "en",
                  p->base, p->mbase, p->irq);
           if ((class_revid & DEVREVID) < 3)
@@ -6246,13 +6121,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
           }
           printk("\n");
 
-          /*
-           * I don't think we need to bother with allowing
-           * spurious interrupts for the 787x/785x, but what
-           * the hey.
-           */
-          aic7xxx_spurious_count = 1;
-
           if (aic7xxx_extended)
             p->flags |= EXTENDED_TRANSLATION;
 
@@ -6294,13 +6162,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
           }
 
           index++;
-          /*
-           * Disable spurious interrupts.
-           */
-          aic7xxx_spurious_count = 0;
-        }  /* Found an Adaptec PCI device. */
-      }
-    }
+      }  /* Found an Adaptec PCI device. */
   }
 #endif CONFIG_PCI
 
@@ -6391,9 +6253,11 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
   /*
    * XXX - this relies on the host data being stored in a
    *       little-endian format.
+   *
+   * No longer is that an issue, I've "big-endian'ified" this driver. -DaveM
    */
   hscb->SCSI_cmd_length = cmd->cmd_len;
-  hscb->SCSI_cmd_pointer = VIRT_TO_BUS(cmd->cmnd);
+  hscb->SCSI_cmd_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->cmnd));
 
   if (cmd->use_sg)
   {
@@ -6410,19 +6274,19 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     sg = (struct scatterlist *)cmd->request_buffer;
     for (i = 0; i < cmd->use_sg; i++)
     {
-      scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
-      scb->sg_list[i].length = (unsigned int) sg[i].length;
+      scb->sg_list[i].address = cpu_to_le32(VIRT_TO_BUS(sg[i].address));
+      scb->sg_list[i].length = cpu_to_le32((unsigned int) sg[i].length);
     }
-    hscb->SG_list_pointer = VIRT_TO_BUS(scb->sg_list);
+    hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(scb->sg_list));
     hscb->SG_segment_count = cmd->use_sg;
     scb->sg_count = hscb->SG_segment_count;
 
     /* Copy the first SG into the data pointer area. */
     hscb->data_pointer = scb->sg_list[0].address;
-    hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24);
+    hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24);
 #if 0
     printk("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
-           cmd->use_sg, aic7xxx_length(cmd, 0), hscb->data_count);
+           cmd->use_sg, aic7xxx_length(cmd, 0), le32_to_cpu(hscb->data_count));
 #endif
   }
   else
@@ -6435,11 +6299,11 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     {
       hscb->SG_segment_count = 1;
       scb->sg_count = 1;
-      scb->sg_list[0].address = VIRT_TO_BUS(cmd->request_buffer);
-      scb->sg_list[0].length = cmd->request_bufflen;
-      hscb->SG_list_pointer = VIRT_TO_BUS(&scb->sg_list[0]);
-      hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24);
-      hscb->data_pointer = VIRT_TO_BUS(cmd->request_buffer);
+      scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
+      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
+      hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[0]));
+      hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24);
+      hscb->data_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
     }
     else
     {
@@ -6447,7 +6311,7 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
       scb->sg_count = 0;
       hscb->SG_list_pointer = 0;
       hscb->data_pointer = 0;
-      hscb->data_count = SCB_LIST_NULL << 24;
+      hscb->data_count = cpu_to_le32(SCB_LIST_NULL << 24);
     }
   }
 }
@@ -6594,7 +6458,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
   pause_sequencer(p);
   while (inb(p->base + INTSTAT) & INT_PEND);
   {
-    aic7xxx_isr(p->irq, (void *) NULL, (void *) NULL);
+    aic7xxx_isr(p->irq, (void *) p, (void *) NULL);
     pause_sequencer(p);
   } 
   if ((cmd != scb->cmd) || ((scb->flags & SCB_ACTIVE) == 0))
@@ -6749,7 +6613,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
       if (hscb_index == SCB_LIST_NULL)
       {
         disconnected = TRUE;
-        linked_next = (scb->hscb->data_count >> 24) & 0xFF;
+        linked_next = (le32_to_cpu(scb->hscb->data_count) >> 24) & 0xFF;
       }
       else
       {
@@ -6767,8 +6631,8 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
          * linked next pointer.
          */
         scb->hscb->control |= ABORT_SCB | MK_MESSAGE;
-        scb->hscb->data_count &= ~0xFF000000;
-        scb->hscb->data_count |= linked_next << 24;
+        scb->hscb->data_count &= cpu_to_le32(~0xFF000000);
+        scb->hscb->data_count |= cpu_to_le32(linked_next << 24);
         if ((p->flags & PAGE_ENABLED) == 0)
         {
           scb->hscb->control &= ~DISCONNECTED;
@@ -6942,7 +6806,8 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
 {
   struct aic7xxx_scb *scb = NULL;
   struct aic7xxx_host *p;
-  int    base, found, tindex, min_target, max_target;
+  unsigned long base;
+  int    found, tindex, min_target, max_target;
   int    result = -1;
   char   channel = 'A';
   unsigned long processor_flags;
index fd40554f3c66e4089d8db6adb7fe0a0eb3e92d8f..d1b92b556368cbd460db6c6dca7e759bf09b2282 100644 (file)
 
 #define AIC7XXX_H_VERSION  "$Revision: 3.2 $"
 
+#ifdef __i386__
+#define AIC7XXX_BIOSPARAM      aic7xxx_biosparam
+#else
+#define AIC7XXX_BIOSPARAM      NULL
+#endif
+
 /*
  * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
  * to do with card config are filled in after the card is detected.
@@ -36,7 +42,7 @@
        queuecommand:    aic7xxx_queue,                                         \
        abort:           aic7xxx_abort,                                         \
        reset:           aic7xxx_reset,                                         \
-       bios_param:      aic7xxx_biosparam,                                     \
+       bios_param:      AIC7XXX_BIOSPARAM,                                     \
        can_queue:       -1,                    /* max simultaneous cmds      */\
        this_id:         -1,                    /* scsi id of host adapter    */\
        sg_tablesize:    SG_ALL,                /* max scatter-gather cmds    */\
index 8ad2cfb030f8c61f3e3bdb0a20c40969df1ddbf8..fe5f624616456750533205836ca838a538b3a9a5 100644 (file)
@@ -86,45 +86,18 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
 {
   struct Scsi_Host *HBAptr;
   struct aic7xxx_host *p;
-  int    found = FALSE;
   int    size = 0;
-  unsigned char i;
 #ifdef AIC7XXX_PROC_STATS
   struct aic7xxx_xferstats *sp;
   unsigned char target, lun;
+  int i;
 #endif
 
   HBAptr = NULL;
-  for (i=0; i < NUMBER(aic7xxx_boards); i++)
-  {
-    if ((HBAptr = aic7xxx_boards[i]) != NULL)
-    {
-      if (HBAptr->host_no == hostno)
-      {
-        break;
-      }
-
-      while ((HBAptr->hostdata != NULL) && !found &&
-          ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL))
-      {
-        if (HBAptr->host_no == hostno)
-        {
-          found = TRUE;
-        }
-      }
-
-      if (!found)
-      {
-        HBAptr = NULL;
-      }
-      else
-      {
-        break;
-      }
-    }
-  }
+  for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
+    ;
 
-  if (HBAptr == NULL)
+  if (!p)
   {
     size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
     if (size > length)
@@ -136,6 +109,7 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
       return (length);
     }
   }
+  HBAptr = p->host;
 
   if (inout == TRUE) /* Has data been written to the file? */ 
   {
@@ -217,8 +191,8 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
   size += sprintf(BLS, "                         (%s chipset)\n",
       chip_names[p->chip_class]);
   size += sprintf(BLS, "               Host Bus: %s\n", bus_names[p->bus_type]);
-  size += sprintf(BLS, "                Base IO: %#.4x\n", p->base);
-  size += sprintf(BLS, "         Base IO Memory: 0x%x\n", p->mbase);
+  size += sprintf(BLS, "                Base IO: 0x%lx\n", p->base);
+  size += sprintf(BLS, "         Base IO Memory: 0x%lx\n", p->mbase);
   size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
   size += sprintf(BLS, "                   SCBs: Used %d, HW %d, Page %d\n",
       p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs);
index aeda681c1a8055d5f7e41edfb7f5782277d956ea..33c43e44cc0ac61e07f4df02c772bfeb85dd8562 100644 (file)
@@ -1,6 +1,14 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *   
+ *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
+ *          io_port is now unsigned long.
+ *
+ *      17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88
+ *          Use new scsi error handling code (if linux version >= 2.1.88).
+ *          Use new interrupt code.
+ *
+ *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -331,9 +339,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
-#undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
-#undef  DEBUG_SMP
 
 #define MAX_ISA 4
 #define MAX_VESA 0 
@@ -343,15 +349,14 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #define MAX_CHANNEL 4
 #define MAX_LUN 32
 #define MAX_TARGET 32
-#define MAX_IRQ 16
 #define MAX_MAILBOXES 64
 #define MAX_SGLIST 64
-#define MAX_LARGE_SGLIST 252
+#define MAX_LARGE_SGLIST 122
 #define MAX_INTERNAL_RETRIES 64
 #define MAX_CMD_PER_LUN 2
 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)
 
-#define SKIP UINT_MAX
+#define SKIP ULONG_MAX
 #define FALSE 0
 #define TRUE 1
 #define FREE 0
@@ -415,15 +420,15 @@ struct eata_info {
    ulong  data_len;     /* Number of valid bytes after this field */
    ulong  sign;         /* ASCII "EATA" signature */
    unchar        :4,    /* unused low nibble */
-         version:4;    /* EATA version, should be 0x1 */
+          version:4;    /* EATA version, should be 0x1 */
    unchar  ocsena:1,    /* Overlap Command Support Enabled */
-          tarsup:1,    /* Target Mode Supported */
+           tarsup:1,    /* Target Mode Supported */
            trnxfr:1,    /* Truncate Transfer Cmd NOT Necessary */
            morsup:1,    /* More Supported */
-          dmasup:1,    /* DMA Supported */
-          drqvld:1,    /* DRQ Index (DRQX) is valid */
-             ata:1,    /* This is an ATA device */
-          haaval:1;    /* Host Adapter Address Valid */
+           dmasup:1,    /* DMA Supported */
+           drqvld:1,    /* DRQ Index (DRQX) is valid */
+              ata:1,    /* This is an ATA device */
+           haaval:1;    /* Host Adapter Address Valid */
    ushort cp_pad_len;   /* Number of pad bytes after cp_len */
    unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */
    ulong  cp_len;       /* Number of valid bytes in cp */
@@ -432,19 +437,19 @@ struct eata_info {
    ushort unused;
    ushort scatt_size;   /* Max number of entries in scatter/gather table */
    unchar     irq:4,    /* Interrupt Request assigned to this controller */
-          irq_tr:1,    /* 0 for edge triggered, 1 for level triggered */
-          second:1,    /* 1 if this is a secondary (not primary) controller */
-            drqx:2;    /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */
+           irq_tr:1,    /* 0 for edge triggered, 1 for level triggered */
+           second:1,    /* 1 if this is a secondary (not primary) controller */
+             drqx:2;    /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */
    unchar  sync;        /* 1 if scsi target id 7...0 is running sync scsi */
 
    /* Structure extension defined in EATA 2.0B */
    unchar  isaena:1,    /* ISA i/o addressing is disabled/enabled */
-        forcaddr:1,    /* Port address has been forced */
+         forcaddr:1,    /* Port address has been forced */
          large_sg:1,    /* 1 if large SG lists are supported */
              res1:1,
-                :4;
+                 :4;
    unchar  max_id:5,    /* Max SCSI target ID number */
-        max_chan:3;    /* Max SCSI channel number on this board */
+         max_chan:3;    /* Max SCSI channel number on this board */
 
    /* Structure extension defined in EATA 2.0C */
    unchar   max_lun;    /* Max SCSI LUN number */
@@ -463,17 +468,17 @@ struct eata_info {
 struct eata_config {
    ushort len;          /* Number of bytes following this field */
    unchar edis:1,       /* Disable EATA interface after config command */
-        ocena:1,       /* Overlapped Commands Enabled */
-       mdpena:1,       /* Transfer all Modified Data Pointer Messages */
-       tarena:1,       /* Target Mode Enabled for this controller */
-             :4;
+         ocena:1,       /* Overlapped Commands Enabled */
+        mdpena:1,       /* Transfer all Modified Data Pointer Messages */
+        tarena:1,       /* Target Mode Enabled for this controller */
+              :4;
    unchar cpad[511];
    };
 
 /* Returned status packet structure */
 struct mssp {
    unchar adapter_status:7,    /* State related to current command */
-                    eoc:1;    /* End Of Command (1 = command completed) */
+                     eoc:1;    /* End Of Command (1 = command completed) */
    unchar target_status;       /* SCSI status received after data transfer */
    unchar unused[2];
    ulong inv_res_len;          /* Number of bytes not transferred */
@@ -489,13 +494,13 @@ struct sg_list {
 /* MailBox SCSI Command Packet */
 struct mscp {
    unchar  sreset:1,     /* SCSI Bus Reset Signal should be asserted */
-            init:1,     /* Re-initialize controller and self test */
-          reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
-              sg:1,     /* Use Scatter/Gather */
-                :1,
-          interp:1,     /* The controller interprets cp, not the target */ 
-            dout:1,     /* Direction of Transfer is Out (Host to Target) */
-             din:1;     /* Direction of Transfer is In (Target to Host) */
+             init:1,     /* Re-initialize controller and self test */
+           reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
+               sg:1,     /* Use Scatter/Gather */
+                 :1,
+           interp:1,     /* The controller interprets cp, not the target */ 
+             dout:1,     /* Direction of Transfer is Out (Host to Target) */
+              din:1;     /* Direction of Transfer is In (Target to Host) */
    unchar sense_len;     /* Request Sense Length */
    unchar unused[3];
    unchar  fwnest:1,     /* Send command to a component of an Array Group */
@@ -507,9 +512,9 @@ struct mscp {
    unchar  target:5,     /* SCSI target ID */
           channel:3;     /* SCSI channel number */
    unchar     lun:5,     /* SCSI logical unit number */
-          luntar:1,     /* This cp is for Target (not LUN) */
-          dispri:1,     /* Disconnect Privilege granted */
-             one:1;     /* 1 */
+           luntar:1,     /* This cp is for Target (not LUN) */
+           dispri:1,     /* Disconnect Privilege granted */
+              one:1;     /* 1 */
    unchar mess[3];       /* Massage to/from Target */
    unchar cdb[12];       /* Command Descriptor Block */
    ulong  data_len;      /* If sg=0 Data Length, if sg=1 sglist length */
@@ -526,7 +531,6 @@ struct hostdata {
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
    unsigned int last_cp_used;           /* Index of last mailbox used */
    unsigned int iocount;                /* Total i/o done for this board */
-   unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
@@ -542,9 +546,12 @@ struct hostdata {
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "EATA";
-static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
+static char sha[MAX_BOARDS];
 
-static unsigned int io_port[] __initdata = { 
+/* Initialize num_boards so that ihdlr can work while detect is in progress */
+static unsigned int num_boards = MAX_BOARDS;
+
+static unsigned long io_port[] __initdata = { 
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -665,7 +672,7 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    return;
 }
 
-static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
+static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {
 
    while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) {
       udelay(1L);
@@ -675,7 +682,7 @@ static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
    return FALSE;
 }
 
-static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) {
+static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) {
 
    if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE;
 
@@ -690,7 +697,7 @@ static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) {
    return FALSE;
 }
 
-static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
+static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) {
    unsigned int loop = MAXLOOP;
    ushort *p;
 
@@ -698,7 +705,7 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
 
       while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {
          udelay(1L);
-        if (--loop == 0) return TRUE;
+         if (--loop == 0) return TRUE;
          }
 
       loop = MAXLOOP;
@@ -709,7 +716,7 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
 }
 
 __initfunc (static inline int port_detect \
-      (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char protocol_rev;
    struct eata_info info;
@@ -723,7 +730,7 @@ __initfunc (static inline int port_detect \
    sprintf(name, "%s%d", driver_name, j);
 
    if(check_region(port_base, REGION_SIZE)) {
-      printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base);
+      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
       return FALSE;
       }
 
@@ -738,7 +745,7 @@ __initfunc (static inline int port_detect \
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
       printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
-            name, DEV2H(info.data_len));
+             name, DEV2H(info.data_len));
       return FALSE;
       }
    else if (DEV2H(info.data_len) == EATA_2_0A_SIZE)
@@ -774,7 +781,7 @@ __initfunc (static inline int port_detect \
       }
 
    if (!info.haaval || info.ata) {
-      printk("%s: address 0x%03x, unusable %s board (%d%d), detaching.\n",
+      printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n",
              name, port_base, bus_type, info.haaval, info.ata);
       return FALSE;
       }
@@ -782,7 +789,7 @@ __initfunc (static inline int port_detect \
    if (info.drqvld) {
 
       if (subversion ==  ESA)
-        printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
+         printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
 
       subversion = ISA;
       dma_channel = dma_channel_table[3 - info.drqx];
@@ -790,7 +797,7 @@ __initfunc (static inline int port_detect \
    else {
 
       if (subversion ==  ISA)
-        printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
+         printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
 
       subversion = ESA;
       dma_channel = NO_DMA;
@@ -803,19 +810,20 @@ __initfunc (static inline int port_detect \
 
    if (subversion == ESA && !info.irq_tr)
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
-            name, irq);
+             name, irq);
 
-   /* Board detected, allocate its IRQ if not already done */
-   if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq,
-              eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
+   /* Board detected, allocate its IRQ */
+   if (request_irq(irq, eata2x_interrupt_handler,
+             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
+             driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
       return FALSE;
       }
 
    if (subversion == ISA && request_dma(dma_channel, driver_name)) {
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
-            name, dma_channel);
-      free_irq(irq, NULL);
+             name, dma_channel);
+      free_irq(irq, &sha[j]);
       return FALSE;
       }
 
@@ -840,7 +848,7 @@ __initfunc (static inline int port_detect \
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
 
-      if (!irqlist[irq]) free_irq(irq, NULL);
+      free_irq(irq, &sha[j]);
 
       if (subversion == ISA) free_dma(dma_channel);
 
@@ -865,7 +873,6 @@ __initfunc (static inline int port_detect \
    HD(j)->subversion = subversion;
    HD(j)->protocol_rev = protocol_rev;
    HD(j)->board_number = j;
-   irqlist[irq]++;
 
    if (HD(j)->subversion == ESA)
       sh[j]->unchecked_isa_dma = FALSE;
@@ -937,10 +944,11 @@ __initfunc (static inline int port_detect \
       }
    else                                 tag_type = 'n';
 
-   printk("%s: 2.0%c, %s 0x%03x, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\
-          "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type, sh[j]->io_port,
-          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
-          tag_type, YESNO(linked_comm), max_queue_depth);
+   printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\
+          "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type,
+          (unsigned long)sh[j]->io_port, sh[j]->irq, dma_name,
+          sh[j]->sg_tablesize, sh[j]->can_queue, tag_type, YESNO(linked_comm),
+          max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -1012,7 +1020,7 @@ __initfunc (static void add_pci_ports(void)) {
    unsigned char bus, devfn;
    unsigned int addr, k;
 
-   if (!pcibios_present()) return;
+   if (!pci_present()) return;
 
    for (k = 0; k < MAX_PCI; k++) {
 
@@ -1056,11 +1064,6 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) {
       }
 #endif
 
-   for (k = 0; k < MAX_IRQ; k++) {
-      irqlist[k] = 0;
-      calls[k] = 0;
-      }
-
    for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;
 
    if (!setup_done) add_pci_ports();
@@ -1073,8 +1076,9 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) {
       }
 
    if (j > 0) 
-      printk("EATA/DMA 2.0x: Copyright (C) 1994-1997 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
+   num_boards = j;
    restore_flags(flags);
    return j;
 }
@@ -1138,26 +1142,26 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       if (i >= sh[j]->can_queue) i = 0;
 
       if (HD(j)->cp_stat[i] == FREE) {
-        HD(j)->last_cp_used = i;
-        break;
-        }
+         HD(j)->last_cp_used = i;
+         break;
+         }
       }
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
       if (HD(j)->in_reset) 
-        printk("%s: qcomm, already in reset.\n", BN(j));
+         printk("%s: qcomm, already in reset.\n", BN(j));
       else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
                == SCSI_RESET_SUCCESS) 
-        panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
+         panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    /* Set pointer to control packet structure */
@@ -1178,21 +1182,21 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-                       BN(j), i, SCpnt->channel, SCpnt->target,
+                        BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-       cpp->dout = TRUE;
-       break;
-       }
+        cpp->dout = TRUE;
+        break;
+        }
 
    if ((cpp->din = !cpp->dout))
       for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-          cpp->din = FALSE;
-          break;
-          }
+           cpp->din = FALSE;
+           break;
+           }
 
    cpp->reqsen = TRUE;
    cpp->dispri = TRUE;
@@ -1253,7 +1257,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
              SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    HD(j)->cp_stat[i] = IN_USE;
@@ -1272,14 +1276,14 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
    if (SCarg->host_scribble == NULL
        || SCarg->serial_number != SCarg->serial_number_at_timeout) {
       printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
-            BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+             BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", 
-         BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+          BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1300,8 +1304,8 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
       printk("%s: abort, mbox %d is in use.\n", BN(j), i);
 
       if (SCarg != HD(j)->cp[i].SCpnt)
-        panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
-              BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
+         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
+               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
 
       if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
@@ -1327,7 +1331,7 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-            BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->pid);
       SCarg->scsi_done(SCarg);
       restore_flags(flags);
       return SCSI_ABORT_SUCCESS;
@@ -1347,7 +1351,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
    printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
-         BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
    if (SCarg->host_scribble == NULL)
@@ -1384,13 +1388,13 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
       if (HD(j)->cp_stat[i] == FREE) continue;
 
       if (HD(j)->cp_stat[i] == LOCKED) {
-        HD(j)->cp_stat[i] = FREE;
-        printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
-        continue;
-        }
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
+         continue;
+         }
 
       if (!(SCpnt = HD(j)->cp[i].SCpnt))
-        panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
@@ -1405,13 +1409,13 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          }
 
       if (SCpnt->host_scribble == NULL)
-        panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
+         panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
       if (*(unsigned int *)SCpnt->host_scribble != i) 
-        panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
+         panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
       if (SCpnt->scsi_done == NULL) 
-        panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
       }
@@ -1446,7 +1450,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-               BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1458,7 +1462,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-               BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else
@@ -1640,229 +1644,200 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
 
 }
 
-static void eata2x_interrupt_handler(int irq, void *dev_id,
+static void eata2x_interrupt_handler(int irq, void *shap,
                                      struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, reg;
+   unsigned int i, j, k, c, status, tstatus, reg;
+   unsigned int n, n_ready, il[MAX_MAILBOXES];
    struct mssp *spp;
    struct mscp *cpp;
 
-   save_flags(flags);
-   cli();
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+   if (sh[j]->irq != irq)
+       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
+   /* Check if this board need to be serviced */
+   if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return;
 
-   if (!irqlist[irq]) {
-      printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq);
-      restore_flags(flags);
-      return;
-      }
+   n_ready = 0;
 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", 
-                       driver_name, irq, calls[irq]);
+   /* Find the mailboxes to be serviced on this board */
+   for (i = 0; i < sh[j]->can_queue; i++) {
+      spp = &HD(j)->sp[i];
 
-   /* Service all the boards configured on this irq */
-   for (j = 0; sh[j] != NULL; j++) {
+      /* Check if this mailbox has completed the operation */
+      if (spp->eoc == FALSE) continue;
 
-      if (sh[j]->irq != irq) continue;
+      spp->eoc = FALSE;
+      il[n_ready++] = i;
+      }
 
-      loops = 0;
+   /* Read the status register to clear the interrupt indication */
+   reg = inb(sh[j]->io_port + REG_STATUS);
 
-      /* Loop until all interrupts for a board are serviced */
-      while (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) {
-        total_loops++;
-        loops++;
+   /* Mailbox service loop */
+   for (n = 0; n < n_ready; n++) {
+      i = il[n];
+      spp = &HD(j)->sp[i];
 
-        if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
-                             BN(j), HD(j)->iocount);
-   
-        /* Read the status register to clear the interrupt indication */
-        reg = inb(sh[j]->io_port + REG_STATUS);
-   
-        /* Service all mailboxes of this board */
-        for (i = 0; i < sh[j]->can_queue; i++) {
-           spp = &HD(j)->sp[i];
-   
-           /* Check if this mailbox has completed the operation */
-           if (spp->eoc == FALSE) continue;
-   
-           spp->eoc = FALSE;
-   
-           if (HD(j)->cp_stat[i] == IGNORE) {
-              HD(j)->cp_stat[i] = FREE;
-              continue;
-              }
-           else if (HD(j)->cp_stat[i] == LOCKED) {
-              HD(j)->cp_stat[i] = FREE;
-              printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
-                     BN(j), i, HD(j)->iocount);
-              continue;
-              }
-           else if (HD(j)->cp_stat[i] == FREE) {
-              printk("%s: ihdlr, mbox %d is free, count %d.\n", 
-                     BN(j), i, HD(j)->iocount);
-              continue;
-              }
-           else if (HD(j)->cp_stat[i] == IN_RESET)
-              printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-           else if (HD(j)->cp_stat[i] != IN_USE) 
-              panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
-   
-           HD(j)->cp_stat[i] = FREE;
-           cpp = &HD(j)->cp[i];
-           SCpnt = spp->SCpnt;
-   
-           if (SCpnt == NULL)
-              panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
-   
-           if (SCpnt != cpp->SCpnt)
-              panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n",
-                    BN(j), i, SCpnt, cpp->SCpnt);
-   
-           if (SCpnt->host_scribble == NULL)
-              panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n",
-                    BN(j), i, SCpnt->pid, SCpnt);
-   
-           if (*(unsigned int *)SCpnt->host_scribble != i) 
-              panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\
-                    " irq %d.\n", BN(j), i, SCpnt->pid, 
-                    *(unsigned int *)SCpnt->host_scribble, irq);
-   
-         if (linked_comm && SCpnt->device->queue_depth > 2
-                                           && TLDEV(SCpnt->device->type))
-            flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
+      if (HD(j)->cp_stat[i] == IGNORE) {
+         HD(j)->cp_stat[i] = FREE;
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == LOCKED) {
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+                HD(j)->iocount);
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == FREE) {
+         printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+                HD(j)->iocount);
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == IN_RESET)
+         printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+      else if (HD(j)->cp_stat[i] != IN_USE) 
+         panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
 
-           tstatus = status_byte(spp->target_status);
-   
-           switch (spp->adapter_status) {
-              case ASOK:     /* status OK */
-   
-                 /* Forces a reset if a disk drive keeps returning BUSY */
-                 if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-                    status = DID_ERROR << 16;
-   
-                 /* If there was a bus reset, redo operation on each target */
-                 else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-                          && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-                    status = DID_BUS_BUSY << 16;
-   
-                 /* Works around a flaw in scsi.c */
-                 else if (tstatus == CHECK_CONDITION
-                          && SCpnt->device->type == TYPE_DISK
-                          && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-                    status = DID_BUS_BUSY << 16;
-
-                 else
-                    status = DID_OK << 16;
-   
-                 if (tstatus == GOOD)
-                    HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-   
-                 if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-                    printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                            "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-                           SCpnt->channel, SCpnt->target, SCpnt->lun, 
-                            SCpnt->pid, spp->target_status, 
-                            SCpnt->sense_buffer[2]);
-   
-                 HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-   
-                  if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+      HD(j)->cp_stat[i] = FREE;
+      cpp = &HD(j)->cp[i];
+      SCpnt = spp->SCpnt;
 
-                 break;
-              case ASST:     /* Selection Time Out */
-              case 0x02:     /* Command Time Out   */
-   
-                 if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-                    status = DID_ERROR << 16;
-                 else {
-                    status = DID_TIME_OUT << 16;
-                    HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-                    }
-   
-                 break;
+      if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-               /* Perform a limited number of internal retries */
-              case 0x03:     /* SCSI Bus Reset Received */
-              case 0x04:     /* Initial Controller Power-up */
-   
-                 for (c = 0; c <= sh[j]->max_channel; c++) 
-                    for (k = 0; k < sh[j]->max_id; k++) 
-                       HD(j)->target_redo[k][c] = TRUE;
-   
-                 if (SCpnt->device->type != TYPE_TAPE
-                      && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-                    status = DID_BUS_BUSY << 16;
-                    HD(j)->retries++;
-                     HD(j)->last_retried_pid = SCpnt->pid;
-                     }
-                 else 
-                    status = DID_ERROR << 16;
-
-                 break;
-              case 0x05:     /* Unexpected Bus Phase */
-              case 0x06:     /* Unexpected Bus Free */
-              case 0x07:     /* Bus Parity Error */
-              case 0x08:     /* SCSI Hung */
-              case 0x09:     /* Unexpected Message Reject */
-              case 0x0a:     /* SCSI Bus Reset Stuck */
-              case 0x0b:     /* Auto Request-Sense Failed */
-              case 0x0c:     /* Controller Ram Parity Error */
-              default:
-                 status = DID_ERROR << 16;
-                 break;
-              }
-   
-           SCpnt->result = status | spp->target_status;
-           HD(j)->iocount++;
+      if (SCpnt != cpp->SCpnt)
+         panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i,
+               SCpnt, cpp->SCpnt);
 
-           if (loops > 1) HD(j)->multicount++;
+      if (SCpnt->host_scribble == NULL)
+         panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+               SCpnt->pid, SCpnt);
+
+      if (*(unsigned int *)SCpnt->host_scribble != i) 
+         panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n",
+              BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+
+      if (linked_comm && SCpnt->device->queue_depth > 2
+                                        && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
+
+      tstatus = status_byte(spp->target_status);
+
+      switch (spp->adapter_status) {
+         case ASOK:     /* status OK */
+
+            /* Forces a reset if a disk drive keeps returning BUSY */
+            if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+               status = DID_ERROR << 16;
+
+            /* If there was a bus reset, redo operation on each target */
+            else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                     && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+               status = DID_BUS_BUSY << 16;
+
+            /* Works around a flaw in scsi.c */
+            else if (tstatus == CHECK_CONDITION
+                     && SCpnt->device->type == TYPE_DISK
+                     && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+               status = DID_BUS_BUSY << 16;
+
+            else
+               status = DID_OK << 16;
+
+            if (tstatus == GOOD)
+               HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
+
+            if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+               printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                      "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                      SCpnt->channel, SCpnt->target, SCpnt->lun, 
+                      SCpnt->pid, spp->target_status, 
+                      SCpnt->sense_buffer[2]);
+
+            HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
+
+            if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+
+            break;
+         case ASST:     /* Selection Time Out */
+         case 0x02:     /* Command Time Out   */
+
+            if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+               status = DID_ERROR << 16;
+            else {
+               status = DID_TIME_OUT << 16;
+               HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+               }
+
+            break;
+
+         /* Perform a limited number of internal retries */
+         case 0x03:     /* SCSI Bus Reset Received */
+         case 0x04:     /* Initial Controller Power-up */
+
+            for (c = 0; c <= sh[j]->max_channel; c++) 
+               for (k = 0; k < sh[j]->max_id; k++) 
+                  HD(j)->target_redo[k][c] = TRUE;
+
+            if (SCpnt->device->type != TYPE_TAPE
+                && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+               status = DID_BUS_BUSY << 16;
+               HD(j)->retries++;
+               HD(j)->last_retried_pid = SCpnt->pid;
+               }
+            else 
+               status = DID_ERROR << 16;
+
+            break;
+         case 0x05:     /* Unexpected Bus Phase */
+         case 0x06:     /* Unexpected Bus Free */
+         case 0x07:     /* Bus Parity Error */
+         case 0x08:     /* SCSI Hung */
+         case 0x09:     /* Unexpected Message Reject */
+         case 0x0a:     /* SCSI Bus Reset Stuck */
+         case 0x0b:     /* Auto Request-Sense Failed */
+         case 0x0c:     /* Controller Ram Parity Error */
+         default:
+            status = DID_ERROR << 16;
+            break;
+         }
+
+      SCpnt->result = status | spp->target_status;
+      HD(j)->iocount++;
 
 #if defined (DEBUG_INTERRUPT)
-           if (SCpnt->result || do_trace)
+      if (SCpnt->result || do_trace)
 #else
-           if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-               (spp->adapter_status != ASOK && 
-               spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-               do_trace || msg_byte(spp->target_status))
+      if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+          (spp->adapter_status != ASOK && 
+          spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+          do_trace || msg_byte(spp->target_status))
 #endif
-              printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                     " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-                     BN(j), i, spp->adapter_status, spp->target_status,
-                     SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                      reg, HD(j)->iocount);
-   
-           /* Set the command state to inactive */
-           SCpnt->host_scribble = NULL;
-   
-           restore_flags(flags);
-           SCpnt->scsi_done(SCpnt);
-           cli();
-
-           }   /* Mailbox loop */
+         printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+                " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+                BN(j), i, spp->adapter_status, spp->target_status,
+                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                reg, HD(j)->iocount);
 
-        }   /* Multiple command loop */
-
-      }   /* Boards loop */
+      /* Set the command state to inactive */
+      SCpnt->host_scribble = NULL;
 
-   calls[irq]++;
+      SCpnt->scsi_done(SCpnt);
 
-#if defined (DEBUG_SMP)
-   if (total_loops == 0) 
-     printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
-           driver_name, irq, calls[irq]);
-#endif
+      }   /* Mailbox loop */
 
-   if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", 
-                       driver_name, irq, calls[irq]);
+   if (n_ready > 1)
+      printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready);
 
-#if defined (DEBUG_STATISTICS)
-   if ((calls[irq] % 100000) == 10000)
-      for (j = 0; sh[j] != NULL; j++)
-        printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j),
-               calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount);
-#endif
+   if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-   restore_flags(flags);
    return;
 }
 
@@ -1881,7 +1856,7 @@ int eata2x_release(struct Scsi_Host *shpnt) {
    for (i = 0; i < sh[j]->can_queue; i++) 
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL);
+   free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
 
index 0a01d00b0f36b5f9b38610468717bb685f025e12..3322a5eb512e9967b380af1c857ad3b92202f358 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     eata.h - used by the low-level driver for EATA/DMA SCSI host adapters.
+ *        eata.h - used by the low-level driver for EATA/DMA SCSI host adapters.
  */
 #ifndef _EATA_H
 #define _EATA_H
@@ -12,19 +12,41 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "3.11.00"
-
-
-#define EATA {                                                                 \
-               name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",      \
-               detect:            eata2x_detect,                               \
-               release:           eata2x_release,                              \
-               queuecommand:      eata2x_queuecommand,                         \
-               abort:             eata2x_abort,                                \
-               reset:             eata2x_reset,                                \
-               bios_param:        scsicam_bios_param,                          \
-               this_id:           7,   /* this_id, reset by detect */          \
-               unchecked_isa_dma: 1,   /* unchecked isa dma, reset by detect */\
-               use_clustering:    ENABLE_CLUSTERING                            \
-               }
+#define EATA_VERSION "4.02.00"
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88)
+
+#define EATA {                                                               \
+                name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
+                detect:            eata2x_detect,                            \
+                release:           eata2x_release,                           \
+                queuecommand:      eata2x_queuecommand,                      \
+                abort:             eata2x_abort,                             \
+                reset:             eata2x_reset,                             \
+                bios_param:        scsicam_bios_param,                       \
+                this_id:           7,                                        \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering:    ENABLE_CLUSTERING,                        \
+                use_new_eh_code: 1    /* Enable new error code */            \
+             }
+
+#else /* Use old scsi code */
+
+#define EATA {                                                               \
+                name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
+                detect:            eata2x_detect,                            \
+                release:           eata2x_release,                           \
+                queuecommand:      eata2x_queuecommand,                      \
+                abort:             eata2x_abort,                             \
+                reset:             eata2x_reset,                             \
+                bios_param:        scsicam_bios_param,                       \
+                this_id:           7,                                        \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering:    ENABLE_CLUSTERING                         \
+             }
+
+#endif
+
 #endif
index 41b91acb02cad25d4c3ba0ffb53a29648e9c0ef9..4b2c5c12f344d392f79da010307bdd9f475494d2 100644 (file)
@@ -1406,7 +1406,7 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
     u32 error, i, x;
     u8 pal1, pal2, pal3;
 
-    if (pcibios_present()) {
+    if (pci_present()) {
        for (i = 0; i <= MAXPCI; ++i, ++pci_index) {
            if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, 
                                    pci_index, &pci_bus, &pci_device_fn))
index 90dc81f3cc125db5d9827c613721d47d00220036..d46c0a7e14bfb91b2b2e39a1b886f5ac4c710977 100644 (file)
@@ -880,7 +880,7 @@ void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
     u16 rev_device;
     u32 error, i, x;
 
-    if (pcibios_present()) {
+    if (pci_present()) {
        for (i = 0; i <= MAXPCI; ++i, ++pci_index) {
            if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, 
                                    pci_index, &pci_bus, &pci_device_fn))
index 2f59d69f3bc9940a179c98c99bb41f36f6319b7d..0276ac45890b9e952869af855afe7773d8877c26 100644 (file)
@@ -20,6 +20,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
 
+ * PCI detection rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
  **************************************************************************
 
  SUMMARY:
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/proc_fs.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/stat.h>
 
@@ -749,168 +750,63 @@ static int fdomain_isa_detect( int *irq, int *iobase )
    return 1;                   /* success */
 }
 
-static int fdomain_pci_nobios_detect( int *irq, int *iobase )
-{
-   int i;
-   int flag = 0;
-
-   /* The proper way of doing this is to use ask the PCI bus for the device
-      IRQ and interrupt level.  But we can't do that if PCI BIOS32 support
-      isn't compiled into the kernel, or if a PCI BIOS32 isn't present.
-
-      Instead, we scan down a bunch of addresses (Future Domain tech
-      support says we will probably find the address before we get to
-      0xf800).  This works fine on some systems -- other systems may have
-      to scan more addresses.  If you have to modify this section for your
-      installation, please send mail to faith@cs.unc.edu. */
-
-   for (i = 0xfff8; i > 0xe000; i -= 8) {
-      if (check_region( i, 0x10 )) {
-#if DEBUG_DETECT
-        printk( " (%x inuse)," , i );
-#endif
-        continue;
-      }
-      if ((flag = fdomain_is_valid_port( i ))) break;
-   }
-
-   if (!flag) return 0;                /* iobase not found */
-
-   *irq    = fdomain_get_irq( i );
-   *iobase = i;
-
-   return 1;                   /* success */
-}
-
 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
    iobase) This function gets the Interrupt Level and I/O base address from
-   the PCI configuration registers.  The I/O base address is masked with
-   0xfff8 since on my card the address read from the PCI config registers
-   is off by one from the actual I/O base address necessary for accessing
-   the status and control registers on the card (PCI config register gives
-   0xf801, actual address is 0xf800).  This is likely a bug in the FD
-   config code that writes to the PCI registers, however using a mask
-   should be safe since I think the scan done by the card to determine the
-   I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at
-   least the old scan code we used to use to get the I/O base did...  Also,
-   the device ID from the PCI config registers is 0x0 and should be 0x60e9
-   as it is in the status registers (offset 5 from I/O base).  If this is
-   changed in future hardware/BIOS changes it will need to be fixed in this
-   detection function.  Comments, bug reports, etc... on this function
-   should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley.  */
+   the PCI configuration registers. */
 
 #ifdef CONFIG_PCI
 static int fdomain_pci_bios_detect( int *irq, int *iobase )
 {
-   int              error;
-   unsigned char    pci_bus, pci_dev_fn;    /* PCI bus & device function */
-   unsigned char    pci_irq;                /* PCI interrupt line */
-   unsigned int     pci_base;               /* PCI I/O base address */
-   unsigned short   pci_vendor, pci_device; /* PCI vendor & device IDs */
-
-   /* If the PCI BIOS doesn't exist, use the old-style detection routines.
-      Otherwise, get the I/O base address and interrupt from the PCI config
-      registers. */
-   
-   if (!pcibios_present()) return fdomain_pci_nobios_detect( irq, iobase );
+   unsigned int     pci_irq;                /* PCI interrupt line */
+   unsigned long    pci_base;               /* PCI I/O base address */
+   struct pci_dev   *pdev = NULL;
+
+   if (!pci_present()) return 0;
 
 #if DEBUG_DETECT
    /* Tell how to print a list of the known PCI devices from bios32 and
       list vendor and device IDs being used if in debug mode.  */
       
-   printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
+   printk( "\nINFO: use lspci -v to see list of PCI devices\n" );
    printk( "\nTMC-3260 detect:"
           " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
           PCI_VENDOR_ID_FD, 
           PCI_DEVICE_ID_FD_36C70 );
 #endif 
 
-   /* We will have to change this if more than 1 PCI bus is present and the
-      FD scsi host is not on the first bus (i.e., a PCI to PCI bridge,
-      which is not supported by bios32 right now anyway).  This should
-      probably be done by a call to pcibios_find_device but I can't get it
-      to work...  Also the device ID reported from the PCI config registers
-      does not match the device ID quoted in the tech manual or available
-      from offset 5 from the I/O base address.  It should be 0x60E9, but it
-      is 0x0 if read from the PCI config registers.  I guess the FD folks
-      neglected to write it to the PCI registers...  This loop is necessary
-      to get the device function (at least until someone can get
-      pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */
-    
-   pci_bus = 0;
-
-   for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) {
-      pcibios_read_config_word( pci_bus,
-                               pci_dev_fn,
-                               PCI_VENDOR_ID,
-                               &pci_vendor );
-
-      if (pci_vendor == PCI_VENDOR_ID_FD) {
-        pcibios_read_config_word( pci_bus,
-                                  pci_dev_fn,
-                                  PCI_DEVICE_ID,
-                                  &pci_device );
-
-        if (pci_device == PCI_DEVICE_ID_FD_36C70) {
-           /* Break out once we have the correct device.  If other FD
-              PCI devices are added to this driver we will need to add
-              an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */
-           break;
-        } else {
-           /* If we can't find an FD scsi card we give up. */
-           return 0;
-        }
-      }
-   }
+   if ((pdev = pci_find_device(PCI_VENDOR_ID, PCI_DEVICE_ID, pdev)) == NULL)
+     return 0;
        
 #if DEBUG_DETECT
    printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
-          pci_bus,
-          (pci_dev_fn & 0xf8) >> 3, 
-          pci_dev_fn & 7 );
+          pdev->bus->number,
+          PCI_SLOT(pdev->devfn),
+          PCI_FUNC(pdev->devfn));
 #endif
 
    /* We now have the appropriate device function for the FD board so we
       just read the PCI config info from the registers.  */
 
-   if ((error = pcibios_read_config_dword( pci_bus,
-                                          pci_dev_fn, 
-                                          PCI_BASE_ADDRESS_0,
-                                          &pci_base ))
-       || (error = pcibios_read_config_byte( pci_bus,
-                                            pci_dev_fn, 
-                                            PCI_INTERRUPT_LINE,
-                                            &pci_irq ))) {
-      printk ( "PCI ERROR: Future Domain 36C70 not initializing"
-              " due to error reading configuration space\n" );
-      return 0;
-   } else {
+   pci_base = pdev->base_address[0];
+   pci_irq = pdev->irq;
 #if DEBUG_DETECT
       printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", 
              pci_irq, pci_base );
 #endif
 
-      /* Now we have the I/O base address and interrupt from the PCI
-        configuration registers.  Unfortunately it seems that the I/O base
-        address is off by one on my card so I mask it with 0xfff8.  This
-        must be some kind of goof in the FD code that does the autoconfig
-        and writes to the PCI registers (or maybe I just don't understand
-        something).  If they fix it in later versions of the card or BIOS
-        we may have to adjust the address based on the signature or
-        something...  */
+   /* Now we have the I/O base address and interrupt from the PCI
+      configuration registers. */
 
-      *irq    = pci_irq;
-      *iobase = (pci_base & 0xfff8);
+   *irq    = pci_irq;
+   *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
 
 #if DEBUG_DETECT
-      printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); 
-      printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
+   printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); 
+   printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
 #endif
 
-      if (!fdomain_is_valid_port( *iobase )) return 0;
-      return 1;
-   }
-   return 0;
+   if (!fdomain_is_valid_port( *iobase )) return 0;
+   return 1;
 }
 #endif
 
@@ -978,7 +874,8 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
 #ifdef CONFIG_PCI
         flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
 #else
-        flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
+        printk(KERN_ERR "No PCI support in this kernel, giving up.\n");
+        flag = 0;
 #endif
       }
         
index 77a9abacd857284b84e52eda0c8b26aea25219be..d7ba32d15c4898e99980dbfae93a2cf6a4b65a34 100644 (file)
  * Tested with Linux 1.2.13, ..., 2.1.61                                *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.3  1998/02/25 23:52:32  ecd
+ * Final round of PCI device driver patches by Martin Mares.
+ *
+ * I could not verify each and every change to the drivers locally,
+ * please consult linux/Documentation/pci.txt to understand changes
+ * made in case patching should be necessary.
+ *
+ * Revision 1.2  1997/11/12 23:58:51  davem
+ * Merge to 2.1.63 to get the Ingo P5 bugfix.
+ * I did not touch the sound changes at all, Alan
+ * please look into that stuff as it is your
+ * territory.
+ *
  * Revision 1.10  1997/10/31 12:29:57  achim
  * Read heads/sectors from host drive
  *
@@ -60,7 +73,7 @@
  * Initial revision
  *
  *
- * $Id: gdth.c,v 1.10 1997/10/31 12:29:57 achim Exp $ 
+ * $Id: gdth.c,v 1.3 1998/02/25 23:52:32 ecd Exp $ 
  ************************************************************************/
 
 #ifdef MODULE
@@ -71,7 +84,6 @@
 #include <linux/kernel.h>
 #include <linux/head.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -83,6 +95,8 @@
 #include <linux/timer.h>
 #if LINUX_VERSION_CODE >= 0x020100
 #include <linux/reboot.h>
+#else
+#include <linux/bios32.h>
 #endif
 
 #include <asm/dma.h>
@@ -440,7 +454,7 @@ static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)
     TRACE(("gdth_search_pci() device_id %d, index %d\n",
                  device_id,index));
 
-    if (!pcibios_present())
+    if (!pci_present())
         return 0;
 
     if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
@@ -448,6 +462,22 @@ static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)
         return 0;
 
     /* GDT PCI controller found, now read resources from config space */
+#if LINUX_VERSION_CODE >= 0x20155
+    {
+       struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn);
+       base0 = pdev->base_address[0];
+       base1 = pdev->base_address[1];
+       base2 = pdev->base_address[2];
+       if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
+                                           PCI_ROM_ADDRESS,
+                                           (int *) &pcistr->bios))) {
+               printk("GDT-PCI: error %s reading configuration space",
+                      pcibios_strerror(error));
+               return -1;
+               }
+       pcistr->irq = pdev->irq;
+    }
+#else
 #if LINUX_VERSION_CODE >= 0x010300
 #define GDTH_BASEP      (int *)
 #else
@@ -471,6 +501,7 @@ static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)
                pcibios_strerror(error));
         return -1;
     }
+#endif
 
     pcistr->device_id = device_id;
     if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000 or GDT6000B */
index d493fa167ecfaac95ba5649955b3cf4ed92b37fb..a26d4200bb847e8222e9a233128075c2f67c595c 100644 (file)
 #include "hosts.h"
 
 
-#define IN2000_VERSION    "1.31"
-#define IN2000_DATE       "06/July/1997"
+#define IN2000_VERSION    "1.32"
+#define IN2000_DATE       "28/March/1998"
 
 /*
  * Note - the following defines have been moved to 'in2000.h':
@@ -2031,18 +2031,12 @@ char buf[32];
          continue;
          }
 
-/* Let's expect only known legal hardware version here. There
- * can't be THAT many of them, and it's easy to add new ones
- * as we hear about them.
+/* Let's assume any hardware version will work, although the driver
+ * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll
+ * print out the rev number for reference later, but accept them all.
  */
 
       hrev = inb(base + IO_HARDWARE);
-      if ((hrev != 0x27) && (hrev != 0x26) && (hrev != 0x25)) {
-         printk("The IN-2000 SCSI card at IOport 0x%03x ",base);
-         printk("has unknown version %02x hardware - ",hrev);
-         printk("Sorry, cancelling detection.\n");
-         continue;
-         }
 
   /* Bit 2 tells us if interrupts are disabled */
       if (switches & SW_DISINT) {
index 557ca60e857f930d7d2e9821c9069718240d428d..9e011a7e6417db24c7c21b543b8c9be6fe65d9e1 100644 (file)
@@ -2,7 +2,7 @@
  *    in2000.h -  Linux device driver definitions for the
  *                Always IN2000 ISA SCSI card.
  *
- *    IMPORTANT: This file is for version 1.31 - 06/Jul/1997
+ *    IMPORTANT: This file is for version 1.32 - 28/Mar/1998
  *
  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
  *    john@geolog.com
@@ -404,8 +404,8 @@ int in2000_reset(Scsi_Cmnd *, unsigned int);
                   this_id:         IN2000_HOST_ID,      /* host-adapter scsi id */ \
                   sg_tablesize:    IN2000_SG,           /* scatter-gather table size */ \
                   cmd_per_lun:     IN2000_CPL,          /* commands per lun */ \
-                  use_clustering:  DISABLE_CLUSTERING, \
-                 use_new_eh_code: 0                    /* Enable new error code */ \
+                  use_clustering:  DISABLE_CLUSTERING,  /* ENABLE_CLUSTERING may speed things up */ \
+                  use_new_eh_code: 0                    /* new error code - not using it yet */ \
                 }
 
 
index fa27ee2a803c06d95e1ef3428384b85783048868..3fc9f9873a084298ddd584a3d8daf19229138f70 100644 (file)
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35)
 #include <linux/init.h>
 #else
+#include <linux/bios32.h>
 #ifndef        __initdata
 #define        __initdata
 #endif
@@ -275,8 +275,12 @@ typedef u32 u_int32;
 typedef        u_long          vm_offset_t;
 typedef        int             vm_size_t;
 
+#ifndef bcopy
 #define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif
+#ifndef bzero
 #define bzero(d, n)    memset((d), 0, (n))
+#endif
 
 #ifndef offsetof
 #define offsetof(t, m) ((size_t) (&((t *)0)->m))
@@ -309,6 +313,12 @@ typedef    int             vm_size_t;
 **     architecture.
 */
 
+#ifdef __sparc__
+#define remap_pci_mem(base, size)      ((vm_offset_t) __va(base))
+#define unmap_pci_mem(vaddr, size)
+#define pcivtophys(p)                  ((p) & pci_dvma_mask)
+#else  /* __sparc__ */
+#define pcivtophys(p)                  (p)
 #ifndef NCR_IOMAPPED
 __initfunc(
 static vm_offset_t remap_pci_mem(u_long base, u_long size)
@@ -337,6 +347,7 @@ static void unmap_pci_mem(vm_offset_t vaddr, u_long size)
 #endif
 }
 #endif /* !NCR_IOMAPPED */
+#endif /* __sparc__ */
 
 #else /* linux-1.2.13 */
 
@@ -1795,8 +1806,8 @@ struct ncb {
        **      Profiling data
        */
        struct profile  profile;
-       u_long          disc_phys;
-       u_long          disc_ref;
+       u_int           disc_phys;
+       u_int           disc_ref;
 
        /*
        **      The global control block.
@@ -1839,7 +1850,7 @@ struct ncb {
        /*
        **      irq level
        */
-       u_short         irq;
+       u_int           irq;
 };
 
 #define NCB_SCRIPT_PHYS(np,lbl)         (np->p_script  + offsetof (struct script, lbl))
@@ -3795,7 +3806,8 @@ static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int le
 
                                switch (old & RELOC_MASK) {
                                case RELOC_REGISTER:
-                                       new = (old & ~RELOC_MASK) + np->paddr;
+                                       new = (old & ~RELOC_MASK)
+                                                       + pcivtophys(np->paddr);
                                        break;
                                case RELOC_LABEL:
                                        new = (old & ~RELOC_MASK) + np->p_script;
@@ -4388,9 +4400,15 @@ static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
        u_long flags = 0;
        ncr_nvram *nvram = device->nvram;
 
+#ifdef __sparc__
+printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=0x%x\n",
+       device->chip.name, unit, device->chip.revision_id, device->slot.base,
+       device->slot.io_port, device->slot.irq);
+#else
 printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
        device->chip.name, unit, device->chip.revision_id, device->slot.base,
        device->slot.io_port, device->slot.irq);
+#endif
 
        /*
        **      Allocate host_data structure
@@ -4543,7 +4561,7 @@ printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
        np->p_scripth   = vtophys(np->scripth);
 
        np->script      = (np->vaddr2) ? (struct script *) np->vaddr2 : np->script0;
-       np->p_script    = (np->vaddr2) ? np->paddr2 : vtophys(np->script0);
+       np->p_script    = (np->vaddr2) ? pcivtophys(np->paddr2) : vtophys(np->script0);
 
        ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script));
        ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth));
@@ -4618,7 +4636,7 @@ printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
        **      Then enable disconnects.
        */
        save_flags(flags); cli();
-       if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) {
+       if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) {
                printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
                restore_flags(flags);
                goto attach_error;
@@ -5504,8 +5522,12 @@ static int ncr_detach(ncb_p np)
 */
 
 #ifdef DEBUG_NCR53C8XX
+#ifdef __sparc__
+       printf("%s: freeing irq 0x%x\n", ncr_name(np), np->irq);
+#else
        printf("%s: freeing irq %d\n", ncr_name(np), np->irq);
 #endif
+#endif
 #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
        free_irq(np->irq, np);
 #else
@@ -5812,8 +5834,14 @@ void ncr_complete (ncb_p np, ccb_p cp)
                **  Announce changes to the generic driver.
                */
                if (tp->numtags) {
+                       /*
+                        * Decrease tp->maxtags (ecd, 980110)
+                        */
+                       tp->maxtags = tp->numtags - 1;
+
                        PRINT_ADDR(cmd);
-                       printf("QUEUE FULL! suspending tagged command queueing\n");
+                       printf("QUEUE FULL! suspending tagged command queueing (setting maxtags to %d)\n", tp->maxtags);
+
                        tp->numtags     = 0;
                        tp->num_good    = 0;
                        if (lp) {
@@ -7317,10 +7345,10 @@ static void ncr_int_ma (ncb_p np)
 
        if (dsp == vtophys (&cp->patch[2])) {
                vdsp = &cp->patch[0];
-               nxtdsp = vdsp[3];
+               nxtdsp = scr_to_cpu(vdsp[3]);
        } else if (dsp == vtophys (&cp->patch[6])) {
                vdsp = &cp->patch[4];
-               nxtdsp = vdsp[3];
+               nxtdsp = scr_to_cpu(vdsp[3]);
        } else if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) {
                vdsp = (u_int32 *) ((char*)np->script - np->p_script + dsp -8);
                nxtdsp = dsp;
@@ -8233,13 +8261,13 @@ static  void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun)
                        cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
                tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval));
                tp->getscr[2] =
-               cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer));
+               cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_sxfer));
 
                tp->getscr[3] = (np->features & FE_PFEN) ?
                        cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
                tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval));
                tp->getscr[5] =
-               cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3));
+               cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_scntl3));
 
                assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
                        offsetof(struct tcb    , sval    )) &3) == 0);
@@ -8635,8 +8663,8 @@ static int ncr_snooptest (struct ncb* np)
 #define PROFILE  cp->phys.header.stamp
 static void ncb_profile (ncb_p np, ccb_p cp)
 {
-       int co, st, en, di, se, post,work,disc;
-       u_long diff;
+       long co, st, en, di, se, post, work, disc;
+       u_int diff;
 
        PROFILE.end = jiffies;
 
@@ -8659,7 +8687,7 @@ static    void ncb_profile (ncb_p np, ccb_p cp)
 
        work = (st - co) - disc;
 
-       diff = (np->disc_phys - np->disc_ref) & 0xff;
+       diff = (scr_to_cpu(np->disc_phys) - np->disc_ref) & 0xff;
        np->disc_ref += diff;
 
        np->profile.num_trans   += 1;
@@ -9085,7 +9113,7 @@ ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr
        int i, j;
        int attach_count = 0;
        ncr_nvram  *nvram;
-       ncr_device *devp;
+       ncr_device *devp = 0;   /* to shut up gcc */
 
        if (!nvram_index)
                return 0;
@@ -9211,7 +9239,7 @@ if (ncr53c8xx)
        ** the order they are detected.
        */
 
-       if (!pcibios_present())
+       if (!pci_present())
                return 0;
 
        chips   = sizeof(ncr_chip_ids)  / sizeof(ncr_chip_ids[0]);
@@ -9295,14 +9323,17 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
 {
        ushort vendor_id, device_id, command;
        uchar cache_line_size, latency_timer;
-       uchar irq, revision;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-       ulong base, base_2, io_port;
+       uchar revision;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
        struct pci_dev *pdev;
-#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
+       ulong base, base_2, io_port; 
+       uint irq;
+#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) 
+       uchar irq;
        uint base, base_2, io_port; 
 #else
-       ulong base, base_2; 
+       uchar irq;
+       ulong base, base_2, io_port; 
 #endif
        int i;
 
@@ -9312,7 +9343,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        ncr_chip *chip;
 
        printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
-               bus, PCI_SLOT(device_fn), PCI_FUNC(device_fn));
+               bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
        /*
         * Read info from the PCI config space.
         * pcibios_read_config_xxx() functions are assumed to be used for 
@@ -9326,12 +9357,12 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
                                        PCI_DEVICE_ID, &device_id);
        (void) pcibios_read_config_word(bus, device_fn,
                                        PCI_COMMAND, &command);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-       pdev = pci_find_dev(bus, device_fn);
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
+       pdev = pci_find_slot(bus, device_fn);
        io_port = pdev->base_address[0];
-       base    = pdev->base_address[1];
-       base_2  = pdev->base_address[2];
-       irq     = pdev->irq;
+       base = pdev->base_address[1];
+       base_2 = pdev->base_address[2];
+       irq = pdev->irq;
 #else
        (void) pcibios_read_config_dword(bus, device_fn,
                                        PCI_BASE_ADDRESS_0, &io_port);  
@@ -9343,7 +9374,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
                                        PCI_INTERRUPT_LINE, &irq);
 #endif
        (void) pcibios_read_config_byte(bus, device_fn,
-                                       PCI_CLASS_REVISION, &revision); 
+                                       PCI_CLASS_REVISION,&revision);  
        (void) pcibios_read_config_byte(bus, device_fn,
                                        PCI_CACHE_LINE_SIZE, &cache_line_size);
        (void) pcibios_read_config_byte(bus, device_fn,
@@ -9369,24 +9400,105 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        }
 
 #ifdef __powerpc__
+       if (!(command & PCI_COMMAND_MASTER)) {
+               printk("ncr53c8xx: attempting to force PCI_COMMAND_MASTER...");
+               command |= PCI_COMMAND_MASTER;
+               pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+               pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+               if (!(command & PCI_COMMAND_MASTER)) {
+                       printk("failed!\n");
+               } else {
+                       printk("succeeded.\n");
+               }
+       }
+
+       if (!(command & PCI_COMMAND_IO)) {
+               printk("ncr53c8xx: attempting to force PCI_COMMAND_IO...");
+               command |= PCI_COMMAND_IO;
+               pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+               pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+               if (!(command & PCI_COMMAND_IO)) {
+                       printk("failed!\n");
+               } else {
+                       printk("succeeded.\n");
+               }
+       }
+
+       if (!(command & PCI_COMMAND_MEMORY)) {
+               printk("ncr53c8xx: attempting to force PCI_COMMAND_MEMORY...");
+               command |= PCI_COMMAND_MEMORY;
+               pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+               pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+               if (!(command & PCI_COMMAND_MEMORY)) {
+                       printk("failed!\n");
+               } else {
+                       printk("succeeded.\n");
+               }
+       }
+       
+       if ( is_prep ) {
+               if (io_port >= 0x10000000) {
+                       printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
+                       io_port = (io_port & 0x00FFFFFF) | 0x01000000;
+                       pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+               }
+               if (base >= 0x10000000) {
+                       printk("ncr53c8xx: reallocating base (Wacky IBM)");
+                       base = (base & 0x00FFFFFF) | 0x01000000;
+                       pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+               }
+               if (base_2 >= 0x10000000) {
+                       printk("ncr53c8xx: reallocating base2 (Wacky IBM)");
+                       base_2 = (base_2 & 0x00FFFFFF) | 0x01000000;
+                       pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2);
+               }
+       }
+#endif
+#ifdef __sparc__
        /*
-        *      Severall fix-up for power/pc.
-        *      Should not be performed by the driver.
+        *      Severall fix-ups for sparc.
+        *
+        *      Should not be performed by the driver, but how can OBP know
+        *      each and every PCI card, if they don't use Fcode?
         */
-       if ((command &
-               (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) !=
-               (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
-               printk("ncr53c8xx : setting PCI master/io/command bit\n");
-               command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY;
+
+       base = __pa(base);
+       base_2 = __pa(base_2);
+
+       if (!(command & PCI_COMMAND_MASTER)) {
+               if (initverbose >= 2)
+                       printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n");
+               command |= PCI_COMMAND_MASTER;
                pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+               pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
        }
-       if (io_port >= 0x10000000) {
-               io_port = (io_port & 0x00FFFFFF) | 0x01000000;
-               pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+
+       if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
+               if (initverbose >= 2)
+                       printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fixup)\n");
+               command |= PCI_COMMAND_INVALIDATE;
+               pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+               pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
        }
-       if (base >= 0x10000000) {
-               base = (base & 0x00FFFFFF) | 0x01000000;
-               pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+
+       if ((chip->features & FE_CLSE) && !cache_line_size) {
+               cache_line_size = 16;
+               if (initverbose >= 2)
+                       printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
+               pcibios_write_config_byte(bus, device_fn,
+                                         PCI_CACHE_LINE_SIZE, cache_line_size);
+               pcibios_read_config_byte(bus, device_fn,
+                                        PCI_CACHE_LINE_SIZE, &cache_line_size);
+       }
+
+       if (!latency_timer) {
+               latency_timer = 248;
+               if (initverbose >= 2)
+                       printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
+               pcibios_write_config_byte(bus, device_fn,
+                                         PCI_LATENCY_TIMER, latency_timer);
+               pcibios_read_config_byte(bus, device_fn,
+                                        PCI_LATENCY_TIMER, &latency_timer);
        }
 #endif
 
@@ -9425,8 +9537,13 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
 
        if (io_port && check_region (io_port, 128)) {
+#ifdef __sparc__
+               printk("ncr53c8xx: IO region 0x%lx to 0x%lx is in use\n",
+                       io_port, (io_port + 127));
+#else
                printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n",
                        (int) io_port, (int) (io_port + 127));
+#endif
                return -1;
        }
        
@@ -9459,7 +9576,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        /*
         * Try to fix up PCI config according to wished features.
         */
-#if defined(__i386) && !defined(MODULE)
+#if defined(__i386__) && !defined(MODULE)
        if ((driver_setup.pci_fix_up & 1) &&
            (chip->features & FE_CLSE) && cache_line_size == 0) {
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75)
index 9b54fc3b231a73d1732b1219a8083e9c08b145da..6a3a165a3942113b72cec3c9f6960ebfe83b58da 100644 (file)
 #define        SCSI_NCR_IOMAPPED
 #elif defined(__alpha__) || defined(__powerpc__)
 #define        SCSI_NCR_IOMAPPED
+#elif defined(__sparc__)
+#undef SCSI_NCR_IOMAPPED
 #endif
 
 /*
@@ -347,13 +349,18 @@ int ncr53c8xx_release(struct Scsi_Host *);
 #error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0"
 #endif
 
-#ifdef __powerpc__
+#if defined(__powerpc__)
 #define        inw_l2b         inw
 #define        inl_l2b         inl
 #define        outw_b2l        outw
 #define        outl_b2l        outl
+#elif defined(__sparc__)
+#define        readw_l2b       readw
+#define        readl_l2b       readl
+#define        writew_b2l      writew
+#define        writel_b2l      writel
 #else
-#error "Support for BIG ENDIAN is only available for the PowerPC"
+#error "Support for BIG ENDIAN is only available for PowerPC and SPARC"
 #endif
 
 #else  /* Assumed x86 or alpha */
index 89ef9beb04f6f9af44a9b8fdca7c59a514a76ad9..8c3d67c1775d3d41131d56792fd45714bffd85e7 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/head.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -519,21 +518,15 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
        PADAPTER2000        padapter;
        int                                     z;
        int                                     setirq;
+       struct pci_dev     *pdev = NULL;
 
-       if ( pcibios_present () )
-               {
-               for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
+       if ( pci_present () )
+               while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_ROY_1, pdev)))
                        {
-                       UCHAR   pci_bus, pci_device_fn;
-
-                       if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
-                               break;
-
                        pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
                        padapter = HOSTDATA(pshost);
 
-                       pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
-                       padapter->basePort &= 0xFFFE;
+                       padapter->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
                        DEB (printk ("\nBase Regs = %#04X", padapter->basePort));                       // get the base I/O port address
                        padapter->mb0   = padapter->basePort + RTR_MAILBOX;                                     // get the 32 bit mail boxes
                        padapter->mb1   = padapter->basePort + RTR_MAILBOX + 4;
@@ -550,7 +543,7 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
                        if ( WaitReady (padapter) )
                                goto unregister;
 
-                       pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+                       pshost->irq = pdev->irq;
                        setirq = 1;
                        for ( z = 0;  z < pci_index;  z++ )                                                                                     // scan for shared interrupts
                                {
@@ -573,13 +566,12 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt)
 
                        printk("\nPSI-2000 EIDE CONTROLLER: at I/O = %X  IRQ = %d\n", padapter->basePort, pshost->irq);
                        printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
+                       NumAdapters++;
                        continue;
 unregister:;
                        scsi_unregister (pshost);
                        }
-               }
-       NumAdapters = pci_index;
-       return pci_index;
+       return NumAdapters;
        }
 /****************************************************************
  *     Name:   Pci2220i_Abort
index 124cc7b44997af8b1d05f4fa987fecac2fafb839..128976a9a5a283b2d41969ce644184ac54477782 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/head.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -632,7 +631,7 @@ VOID ReadFlash (PADAPTER2220I hostdata, VOID *pdata, ULONG base, ULONG length)
  ****************************************************************/
 int Pci2220i_Detect (Scsi_Host_Template *tpnt)
        {
-       int                                     pci_index = 0;
+       struct pci_dev     *pdev = NULL;
        struct Scsi_Host   *pshost;
        PADAPTER2220I       hostdata;
        ULONG                           modearray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
@@ -640,20 +639,13 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt)
        int                                     z;
        int                                     setirq;
 
-       if ( pcibios_present () )
-               {
-               for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
+       if ( pci_present () )
+               while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_DALE_1, pdev)))
                        {
-                       UCHAR   pci_bus, pci_device_fn;
-
-                       if ( pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
-                               break;
-
                        pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
                        hostdata = HOSTDATA(pshost);
 
-                       pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &hostdata->basePort);
-                       hostdata->basePort &= 0xFFFE;
+                       hostdata->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
                        DEB (printk ("\nBase Regs = %#04X", hostdata->basePort));
                        hostdata->regRemap              = hostdata->basePort + RTR_LOCAL_REMAP;                         // 32 bit local space remap
                        DEB (printk (" %#04X", hostdata->regRemap));
@@ -666,8 +658,7 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt)
                        hostdata->regScratchPad = hostdata->basePort + RTR_MAILBOX;                                     // 16 byte scratchpad I/O base address
                        DEB (printk (" %#04X", hostdata->regScratchPad));
 
-                       pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &hostdata->regBase);
-                       hostdata->regBase &= 0xFFFE;
+                       hostdata->regBase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
                        for ( z = 0;  z < 9;  z++ )                                                                                                     // build regester address array
                                hostdata->ports[z] = hostdata->regBase + 0x80 + (z * 4);
                        hostdata->ports[PORT_FAIL] = hostdata->regBase + REG_FAIL;
@@ -691,11 +682,11 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt)
                        if ( !inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES) )                                       // if no devices on this board
                                goto unregister;
 
-                       pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+                       pshost->irq = pdev->irq;
                        setirq = 1;
-                       for ( z = 0;  z < pci_index;  z++ )                                                                                     // scan for shared interrupts
+                       for ( z = 0;  z < NumAdapters;  z++ )                                                                           // scan for shared interrupts
                                {
-                               if ( PsiHost[z]->irq == pshost->irq )                                           // if shared then, don't posses
+                               if ( PsiHost[z]->irq == pshost->irq )                                                                   // if shared then, don't posses
                                        setirq = 0;
                                }
                        if ( setirq )                                                                                                                           // if not shared, posses
@@ -706,7 +697,7 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt)
                                        goto unregister;
                                        }
                                }
-                       PsiHost[pci_index]      = pshost;                                                                                               // save SCSI_HOST pointer
+                       PsiHost[NumAdapters]    = pshost;                                                                                       // save SCSI_HOST pointer
 
                        pshost->unique_id       = hostdata->regBase;
                        pshost->max_id          = 4;
@@ -743,7 +734,6 @@ unregister:
                        scsi_unregister (pshost);
                        NumAdapters++;
                        }
-               }
        return NumAdapters;
        }
 /****************************************************************
index 2e9d3a90d8dd3379bf52a71cad32bfce63fe7938..4a0d34e13c6234e4974b69308854176ba247f746 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/unistd.h>
@@ -55,8 +54,6 @@
 
 #define DEFAULT_LOOP_COUNT     1000000
 
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
 /* End Configuration section *************************************************/
 
 #include <linux/module.h>
@@ -488,11 +485,10 @@ struct dev_param {
 #define QUEUE_ENTRY_LEN                64
 
 struct isp1020_hostdata {
-       u_char  bus;
        u_char  revision;
-       u_char  device_fn;
        struct  host_param host_param;
        struct  dev_param dev_param[MAX_TARGETS];
+       struct  pci_dev *pci_dev;
        
        /* result and request queues (shared with isp1020): */
        u_int   req_in_ptr;             /* index of next request slot */
@@ -511,8 +507,6 @@ struct isp1020_hostdata {
                                                    QLOGICISP_REQ_QUEUE_LEN)
 #define RES_QUEUE_DEPTH(in, out)       QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
 
-static struct Scsi_Host *irq2host[NR_IRQS];
-
 static void    isp1020_enable_irqs(struct Scsi_Host *);
 static void    isp1020_disable_irqs(struct Scsi_Host *);
 static int     isp1020_init(struct Scsi_Host *);
@@ -557,33 +551,26 @@ static inline void isp1020_disable_irqs(struct Scsi_Host *host)
 int isp1020_detect(Scsi_Host_Template *tmpt)
 {
        int hosts = 0;
-       u_short index;
-       u_char bus, device_fn;
        struct Scsi_Host *host;
        struct isp1020_hostdata *hostdata;
+       struct pci_dev *pdev = NULL;
 
        ENTER("isp1020_detect");
 
        tmpt->proc_dir = &proc_scsi_isp1020;
 
-       if (pcibios_present() == 0) {
-               printk("qlogicisp : PCI bios not present\n");
+       if (pci_present() == 0) {
+               printk("qlogicisp : PCI not present\n");
                return 0;
        }
 
-       memset(irq2host, 0, sizeof(irq2host));
-
-       for (index = 0; pcibios_find_device(PCI_VENDOR_ID_QLOGIC,
-                                           PCI_DEVICE_ID_QLOGIC_ISP1020,
-                                           index, &bus, &device_fn) == 0;
-            index++)
+       while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, pdev)))
        {
                host = scsi_register(tmpt, sizeof(struct isp1020_hostdata));
                hostdata = (struct isp1020_hostdata *) host->hostdata;
 
                memset(hostdata, 0, sizeof(struct isp1020_hostdata));
-               hostdata->bus = bus;
-               hostdata->device_fn = device_fn;
+               hostdata->pci_dev = pdev;
 
                if (isp1020_init(host) || isp1020_reset_hardware(host)
 #if USE_NVRAM_DEFAULTS
@@ -598,8 +585,8 @@ int isp1020_detect(Scsi_Host_Template *tmpt)
 
                host->this_id = hostdata->host_param.initiator_scsi_id;
 
-               if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT,
-                               "qlogicisp", NULL))
+               if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT | SA_SHIRQ,
+                               "qlogicisp", host))
                {
                        printk("qlogicisp : interrupt %d already in use\n",
                               host->irq);
@@ -611,13 +598,12 @@ int isp1020_detect(Scsi_Host_Template *tmpt)
                        printk("qlogicisp : i/o region 0x%lx-0x%lx already "
                               "in use\n",
                               host->io_port, host->io_port + 0xff);
-                       free_irq(host->irq, NULL);
+                       free_irq(host->irq, host);
                        scsi_unregister(host);
                        continue;
                }
 
                request_region(host->io_port, 0xff, "qlogicisp");
-               irq2host[host->irq] = host;
 
                outw(0x0, host->io_port + PCI_SEMAPHORE);
                outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
@@ -641,7 +627,7 @@ int isp1020_release(struct Scsi_Host *host)
        hostdata = (struct isp1020_hostdata *) host->hostdata;
 
        outw(0x0, host->io_port + PCI_INTF_CTL);
-       free_irq(host->irq, NULL);
+       free_irq(host->irq, host);
 
        release_region(host->io_port, 0xff);
 
@@ -660,8 +646,8 @@ const char *isp1020_info(struct Scsi_Host *host)
 
        hostdata = (struct isp1020_hostdata *) host->hostdata;
        sprintf(buf,
-               "QLogic ISP1020 SCSI on PCI bus %d device %d irq %d base 0x%lx",
-               hostdata->bus, (hostdata->device_fn & 0xf8) >> 3, host->irq,
+               "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
+               hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
                host->io_port);
 
        LEAVE("isp1020_info");
@@ -819,18 +805,13 @@ void isp1020_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
        Scsi_Cmnd *Cmnd;
        struct Status_Entry *sts;
-       struct Scsi_Host *host;
+       struct Scsi_Host *host = dev_id;
        struct isp1020_hostdata *hostdata;
        u_int in_ptr, out_ptr;
        u_short status;
 
        ENTER_INTR("isp1020_intr_handler");
 
-       host = irq2host[irq];
-       if (!host) {
-               printk("qlogicisp : unexpected interrupt on line %d\n", irq);
-               return;
-       }
        hostdata = (struct isp1020_hostdata *) host->hostdata;
 
        DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq));
@@ -1168,53 +1149,36 @@ static int isp1020_reset_hardware(struct Scsi_Host *host)
 
 static int isp1020_init(struct Scsi_Host *sh)
 {
-       u_long io_base = 0;
+       u_int io_base;
        struct isp1020_hostdata *hostdata;
-       u_char bus, device_fn, revision, irq;
-       u_short vendor_id, device_id, command;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
+       u_char revision;
+       u_int irq;
+       u_short command;
        struct pci_dev *pdev;
-#endif
 
        ENTER("isp1020_init");
 
        hostdata = (struct isp1020_hostdata *) sh->hostdata;
-       bus = hostdata->bus;
-       device_fn = hostdata->device_fn;
-
-       if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)
-            || pcibios_read_config_word(bus, device_fn,
-                                       PCI_DEVICE_ID, &device_id)
-            || pcibios_read_config_word(bus, device_fn,
-                                       PCI_COMMAND, &command)
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,90)
-            || pcibios_read_config_dword(bus, device_fn,
-                                        PCI_BASE_ADDRESS_0, &io_base)
-           || pcibios_read_config_byte(bus, device_fn,
-                                       PCI_INTERRUPT_LINE, &irq)
-#endif
-            || pcibios_read_config_byte(bus, device_fn,
-                                       PCI_CLASS_REVISION, &revision))
+       pdev = hostdata->pci_dev;
+
+       if (pci_read_config_word(pdev, PCI_COMMAND, &command)
+           || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision))
        {
                printk("qlogicisp : error reading PCI configuration\n");
                return 1;
        }
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-       pdev = pci_find_dev(bus, device_fn);
        io_base = pdev->base_address[0];
-       irq     = pdev->irq;
-#endif
+       irq = pdev->irq;
 
-       if (vendor_id != PCI_VENDOR_ID_QLOGIC) {
+       if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
                printk("qlogicisp : 0x%04x is not QLogic vendor ID\n",
-                      vendor_id);
+                      pdev->vendor);
                return 1;
        }
 
-       if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) {
+       if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP1020) {
                printk("qlogicisp : 0x%04x does not match ISP1020 device id\n",
-                      device_id);
+                      pdev->device);
                return 1;
        }
 
index cbdd95f71331764956c83bb0cbb345475f7a4441..32eca4960788685165b6544b0419f297e771d3d3 100644 (file)
@@ -141,7 +141,7 @@ static unsigned char   ** dma_malloc_pages = NULL;
  */
 unsigned int              scsi_logging_level = 0;
 
-static volatile struct Scsi_Host * host_active = NULL;
+volatile struct Scsi_Host * host_active = NULL;
 
 #if CONFIG_PROC_FS
 /* 
index daede4a5682f4f8ec72f7ae5bdc9af5f719e14b3..5f4d401729f0f2e66d2dd274e1866bd07da314ba 100644 (file)
@@ -83,7 +83,7 @@ static int update_timeout (Scsi_Cmnd *, int);
 extern void scsi_old_times_out (Scsi_Cmnd * SCpnt);
 extern void internal_cmnd (Scsi_Cmnd * SCpnt);
 
-static volatile struct Scsi_Host * host_active = NULL;
+extern volatile struct Scsi_Host * host_active;
 #define SCSI_BLOCK(HOST) ((HOST->block && host_active && HOST != host_active) \
                          || (HOST->can_queue && HOST->host_busy >= HOST->can_queue))
 
index 980aadccc4889f815f13146fdd03e3557d9050fb..06fd935c63792c66da76438852dbc62e2a5df9b1 100644 (file)
@@ -26,7 +26,7 @@
  *                             pending interrupt in DC390_detect()     *
  *     1.11  02/05/97  KG/CLH  Fixeds problem with partitions greater  *
  *                             than 1GB                                *
- *     1.12  25/02/98  KG      Cleaned up ifdefs for 2.1 kernel        *
+ *      1.12  15/02/98  MJ      Rewritten PCI probing                  *
  ***********************************************************************/
 
 
@@ -47,7 +47,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
@@ -118,8 +117,6 @@ static PDCB pPrevDCB = NULL;
 static USHORT  adapterCnt = 0;
 static USHORT  InitialTime = 0;
 static USHORT  CurrSyncOffset = 0;
-static ULONG   mech1addr;
-static UCHAR   mech2bus, mech2Agent, mech2CfgSPenR;
 
 static PVOID DC390_phase0[]={
        DC390_DataOut_0,
@@ -1200,147 +1197,7 @@ __initfunc(int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT inde
 
 
 void
-DC390_EnableCfg( USHORT mechnum, UCHAR regval )
-{
-    ULONG wlval;
-
-    if(mechnum == 2)
-    {
-       outb(mech2bus, PCI_CFG2_FORWARD_REG);
-       outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG);
-    }
-    else
-    {
-       regval &= 0xFC;
-       wlval = mech1addr;
-       wlval |= (((ULONG)regval) & 0xff);
-       outl(wlval, PCI_CFG1_ADDRESS_REG);
-    }
-}
-
-
-void
-DC390_DisableCfg( USHORT mechnum )
-{
-
-    if(mechnum == 2)
-       outb(0, PCI_CFG2_ENABLE_REG);
-    else
-       outl(0, PCI_CFG1_ADDRESS_REG);
-}
-
-
-UCHAR
-DC390_inByte( USHORT mechnum, UCHAR regval )
-{
-    UCHAR bval;
-    ULONG wval;
-    ULONG flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg( mechnum, regval );
-    if(mechnum == 2)
-    {
-       wval = mech2Agent;
-       wval <<= 8;
-       wval |= ((USHORT) regval) & 0xff;
-       bval = inb(wval);
-    }
-    else
-    {
-       regval &= 3;
-       bval = inb(PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(bval);
-}
-
-
-USHORT
-DC390_inWord( USHORT mechnum, UCHAR regval )
-{
-    USHORT wval;
-    ULONG flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-       wval = mech2Agent;
-       wval <<= 8;
-       wval |= regval;
-       wval = inw(wval);
-    }
-    else
-    {
-       regval &= 3;
-       wval = inw(PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(wval);
-}
-
-
-ULONG
-DC390_inDword(USHORT mechnum, UCHAR regval )
-{
-    ULONG wlval;
-    ULONG flags;
-    USHORT wval;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-       wval = mech2Agent;
-       wval <<= 8;
-       wval |= regval;
-       wlval = inl(wval);
-    }
-    else
-    {
-       wlval = inl(PCI_CFG1_DATA_REG);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(wlval);
-}
-
-
-void
-DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
-{
-
-    USHORT wval;
-    ULONG  flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-       wval = mech2Agent;
-       wval <<= 8;
-       wval |= regval;
-       outb(bval, wval);
-    }
-    else
-    {
-       regval &= 3;
-       outb(bval, PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-}
-
-
-void
-DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
+DC390_EnDisableCE( UCHAR mode, struct pci_dev *pdev, PUCHAR regval )
 {
 
     UCHAR bval;
@@ -1350,15 +1207,15 @@ DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
        *regval = 0xc0;
     else
        *regval = 0x80;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     if(mode == DISABLE_CE)
-       DC390_OutB(mechnum,*regval,bval);
+       pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
 }
 
 
 void
-DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
+DC390_EEpromOutDI( struct pci_dev *pdev, PUCHAR regval, USHORT Carry )
 {
     UCHAR bval;
 
@@ -1367,32 +1224,28 @@ DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
     {
        bval = 0x40;
        *regval = 0x80;
-       DC390_OutB(mechnum,*regval,bval);
+       pci_write_config_byte(pdev, *regval, bval);
     }
     udelay(160);
     bval |= 0x80;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
     bval = 0;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
 }
 
 
 UCHAR
-DC390_EEpromInDO( USHORT mechnum )
+DC390_EEpromInDO( struct pci_dev *pdev )
 {
-    UCHAR bval,regval;
+    UCHAR bval;
 
-    regval = 0x80;
-    bval = 0x80;
-    DC390_OutB(mechnum,regval,bval);
+    pci_write_config_byte(pdev, 0x80, 0x80);
     udelay(160);
-    bval = 0x40;
-    DC390_OutB(mechnum,regval,bval);
+    pci_write_config_byte(pdev, 0x80, 0x40);
     udelay(160);
-    regval = 0x0;
-    bval = DC390_inByte(mechnum,regval);
+    pci_read_config_byte(pdev, 0x00, &bval);
     if(bval == 0x22)
        return(1);
     else
@@ -1401,7 +1254,7 @@ DC390_EEpromInDO( USHORT mechnum )
 
 
 USHORT
-EEpromGetData1( USHORT mechnum )
+EEpromGetData1( struct pci_dev *pdev )
 {
     UCHAR i;
     UCHAR carryFlag;
@@ -1411,7 +1264,7 @@ EEpromGetData1( USHORT mechnum )
     for(i=0; i<16; i++)
     {
        wval <<= 1;
-       carryFlag = DC390_EEpromInDO(mechnum);
+       carryFlag = DC390_EEpromInDO(pdev);
        wval |= carryFlag;
     }
     return(wval);
@@ -1419,7 +1272,7 @@ EEpromGetData1( USHORT mechnum )
 
 
 void
-DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
+DC390_Prepare( struct pci_dev *pdev, PUCHAR regval, UCHAR EEpromCmd )
 {
     UCHAR i,j;
     USHORT carryFlag;
@@ -1428,7 +1281,7 @@ DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
     j = 0x80;
     for(i=0; i<9; i++)
     {
-       DC390_EEpromOutDI(mechnum,regval,carryFlag);
+       DC390_EEpromOutDI(pdev,regval,carryFlag);
        carryFlag = (EEpromCmd & j) ? 1 : 0;
        j >>= 1;
     }
@@ -1436,7 +1289,7 @@ DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
 
 
 void
-DC390_ReadEEprom( USHORT mechnum, USHORT index )
+DC390_ReadEEprom( struct pci_dev *pdev, int index )
 {
     UCHAR   regval,cmd;
     PUSHORT ptr;
@@ -1446,23 +1299,23 @@ DC390_ReadEEprom( USHORT mechnum, USHORT index )
     cmd = EEPROM_READ;
     for(i=0; i<0x40; i++)
     {
-       DC390_EnDisableCE(ENABLE_CE, mechnum, &regval);
-       DC390_Prepare(mechnum, &regval, cmd);
-       *ptr = EEpromGetData1(mechnum);
+       DC390_EnDisableCE(ENABLE_CE, pdev, &regval);
+       DC390_Prepare(pdev, &regval, cmd);
+       *ptr = EEpromGetData1(pdev);
        ptr++;
        cmd++;
-       DC390_EnDisableCE(DISABLE_CE,mechnum,&regval);
+       DC390_EnDisableCE(DISABLE_CE, pdev, &regval);
     }
 }
 
 
 USHORT
-DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
+DC390_CheckEEpromCheckSum( struct pci_dev *pdev, int index )
 {
     USHORT wval, rc, *ptr;
     UCHAR  i;
 
-    DC390_ReadEEprom( MechNum, index );
+    DC390_ReadEEprom( pdev, index );
     wval = 0;
     ptr = (PUSHORT) &eepromBuf[index][0];
     for(i=0; i<128 ;i+=2, ptr++)
@@ -1475,30 +1328,6 @@ DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
 }
 
 
-USHORT
-DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum )
-{
-    USHORT devnum;
-
-    devnum = BusDevFunNum;
-
-    if(Mechnum == 2)
-    {
-       if(devnum & 0x80)
-            return(-1);
-       mech2bus = (UCHAR)((devnum & 0xff00) >> 8);       /* Bus num */
-       mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3;       /* Dev num */
-       mech2Agent |= 0xc0;
-       mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07;  /* Fun num */
-       mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20;
-    }
-    else       /* use mech #1 method */
-    {
-       mech1addr = 0x80000000 | ((ULONG)devnum << 8);
-    }
-    return(0);
-}
-
 /***********************************************************************
  * Function : static int DC390_init (struct Scsi_Host *host)
  *
@@ -1511,12 +1340,12 @@ DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum )
  ***********************************************************************/
 
 __initfunc(static int
-DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum))
+DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, int index))
 {
     PSH   psh;
     PACB  pACB;
 
-    if( !DC390_CheckEEpromCheckSum( MechNum, index) )
+    if( !DC390_CheckEEpromCheckSum( pdev, index ) )
     {
        psh = scsi_register( psht, sizeof(DC390_ACB) );
        if( !psh )
@@ -1594,20 +1423,10 @@ DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum))
 __initfunc(int
 DC390_detect(Scsi_Host_Template *psht))
 {
-#ifdef FOR_PCI_OK
-    UCHAR   pci_bus, pci_device_fn;
-    int     error = 0;
-    USHORT  chipType = 0;
-    USHORT  i;
-#endif
-
-    UCHAR   irq;
-    UCHAR   istatus;
+    struct pci_dev *pdev = NULL;
+    UINT    irq;
     UINT    io_port;
     USHORT  adaptCnt = 0;      /* Number of boards detected */
-    USHORT  pci_index = 0;     /* Device index to PCI BIOS calls */
-    USHORT  MechNum, BusDevFunNum;
-    ULONG   wlval;
 
     psht->proc_dir = &proc_scsi_tmscsim;
 
@@ -1615,81 +1434,17 @@ DC390_detect(Scsi_Host_Template *psht))
     pSHT_start = psht;
     pACB_start = NULL;
 
-    MechNum = 1;
-    for( ; (MechNum < 3) && (!adaptCnt); MechNum++)
-    {
-       BusDevFunNum = 0;
-       for (; adaptCnt < MAX_ADAPTER_NUM ;)
+    if ( pci_present() )
+       while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev)))
        {
-           if( !DC390_ToMech( MechNum, BusDevFunNum) )
-           {
-                wlval = DC390_inDword( MechNum, PCI_VENDOR_ID);
-                if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+
-                               PCI_VENDOR_ID_AMD) )
-                {
-                   io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE;
-                   irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE);
+           io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+           irq = pdev->irq;
 #ifdef DC390_DEBUG0
-               printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
+           printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
 #endif
-                   if( !DC390_init(psht, io_port, irq, pci_index, MechNum) )
-                   {
-                       adaptCnt++;
-                       pci_index++;
-                       istatus = inb( (USHORT)io_port+INT_Status );    /* Reset Pending INT */
-#ifdef DC390_DEBUG0
-               printk("DC390: Mech=%2x,\n",(UCHAR) MechNum);
-#endif
-                   }
-                }
-           }
-           if( BusDevFunNum != 0xfff8 )
-               BusDevFunNum += 8;          /* next device # */
-           else
-               break;
+           if( !DC390_init(psht, io_port, irq, pdev, adaptCnt))
+               adaptCnt++;
        }
-    }
-
-#ifdef FOR_PCI_OK
-    if ( pcibios_present() )
-    {
-       for (i = 0; i < MAX_ADAPTER_NUM; ++i)
-       {
-           if( !pcibios_find_device( PCI_VENDOR_ID_AMD,
-                               PCI_DEVICE_ID_AMD53C974,
-                               pci_index, &pci_bus, &pci_device_fn) )
-           {
-               chipType = PCI_DEVICE_ID_AMD53C974;
-               pci_index++;
-           }
-
-           if( chipType )
-           {
-
-               error = pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                 PCI_BASE_ADDRESS_0, &io_port);
-               error |= pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                 PCI_INTERRUPT_LINE, &irq);
-               if( error )
-               {
-                   printk("DC390_detect: reading configuration registers error!\n");
-                   InitialTime = 0;
-                   return( 0 );
-               }
-
-               (USHORT) io_port = (USHORT) io_port & 0xFFFE;
-#ifdef DC390_DEBUG0
-               printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
-#endif
-               if( !DC390_init(psht, io_port, irq, i) )
-                   adaptCnt++;
-               chipType = 0;
-           }
-           else
-               break;
-       }
-    }
-#endif
 
     InitialTime = 0;
     adapterCnt = adaptCnt;
index ed22865fdf5ddef2fdea83178bd1c96d2ece5570..bdc582621627f15f9973ade064c494875b4f8c0a 100644 (file)
@@ -660,21 +660,4 @@ UCHAR      xx2;
        outl((value), DC390_ioport + (address)))
 
 
-/* Configuration method #1 */
-#define PCI_CFG1_ADDRESS_REG           0xcf8
-#define PCI_CFG1_DATA_REG              0xcfc
-#define PCI_CFG1_ENABLE                0x80000000
-#define PCI_CFG1_TUPPLE(bus, device, function, register)               \
-       (PCI_CFG1_ENABLE | (((bus) << 16) & 0xff0000) |                 \
-       (((device) << 11) & 0xf800) | (((function) << 8) & 0x700)|      \
-       (((register) << 2) & 0xfc))
-
-/* Configuration method #2 */
-#define PCI_CFG2_ENABLE_REG            0xcf8
-#define PCI_CFG2_FORWARD_REG           0xcfa
-#define PCI_CFG2_ENABLE                0x0f0
-#define PCI_CFG2_TUPPLE(function)                                      \
-       (PCI_CFG2_ENABLE | (((function) << 1) & 0xe))
-
-
 #endif /* _TMSCSIM_H */
index fa980051a6510ecf30234d9ca2382f0056e81a89..0095a6b0759b32211480dc600155b5a2f3085103 100644 (file)
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
+ *          io_port is now unsigned long.
+ *
+ *      17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88
+ *          Use new scsi error handling code (if linux version >= 2.1.88).
+ *          Use new interrupt code.
+ *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
  * 
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -329,9 +336,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
-#undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
-#undef  DEBUG_SMP
 
 #define MAX_ISA 3
 #define MAX_VESA 1 
@@ -341,7 +346,6 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #define MAX_CHANNEL 1
 #define MAX_LUN 8
 #define MAX_TARGET 8
-#define MAX_IRQ 16
 #define MAX_MAILBOXES 16
 #define MAX_SGLIST 32
 #define MAX_SAFE_SGLIST 16
@@ -349,7 +353,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #define MAX_CMD_PER_LUN 2
 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)
 
-#define SKIP UINT_MAX
+#define SKIP ULONG_MAX
 #define FALSE 0
 #define TRUE 1
 #define FREE 0
@@ -424,7 +428,6 @@ struct hostdata {
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
    unsigned int last_cp_used;           /* Index of last mailbox used */
    unsigned int iocount;                /* Total i/o done for this board */
-   unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
@@ -443,9 +446,12 @@ struct hostdata {
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "Ux4F";
-static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
+static char sha[MAX_BOARDS];
 
-static unsigned int io_port[] __initdata = { 
+/* Initialize num_boards so that ihdlr can work while detect is in progress */
+static unsigned int num_boards = MAX_BOARDS;
+
+static unsigned long io_port[] __initdata = { 
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -462,10 +468,10 @@ static unsigned int io_port[] __initdata = {
 #define BN(board) (HD(board)->board_name)
 
 #define SWAP_BYTE(x) ((unsigned long)( \
-       (((unsigned long)(x) & 0x000000ffU) << 24) | \
-       (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
-       (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
-       (((unsigned long)(x) & 0xff000000U) >> 24)))
+        (((unsigned long)(x) & 0x000000ffU) << 24) | \
+        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
+        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
+        (((unsigned long)(x) & 0xff000000U) >> 24)))
 
 #if defined(__BIG_ENDIAN)
 #define H2DEV(x) SWAP_BYTE(x)
@@ -560,7 +566,7 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    return;
 }
 
-static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
+static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {
 
    while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {
       udelay(1L);
@@ -614,7 +620,7 @@ static int board_inquiry(unsigned int j) {
 }
 
 __initfunc (static inline int port_detect \
-      (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
    char *bus_type, dma_name[16];
@@ -637,8 +643,8 @@ __initfunc (static inline int port_detect \
       unsigned char heads;
       unsigned char sectors;
       } mapping_table[4] = { 
-          { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
-          };
+           { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
+           };
 
    struct config_1 {
       unsigned char bios_segment: 3;
@@ -659,7 +665,7 @@ __initfunc (static inline int port_detect \
    sprintf(name, "%s%d", driver_name, j);
 
    if(check_region(port_base, REGION_SIZE)) {
-      printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base);
+      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
       return FALSE;
       }
 
@@ -676,17 +682,18 @@ __initfunc (static inline int port_detect \
    dma_channel = dma_channel_table[config_1.dma_channel];
    subversion = (in_byte & 0x0f);
 
-   /* Board detected, allocate its IRQ if not already done */
-   if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq,
-              u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
+   /* Board detected, allocate its IRQ */
+   if (request_irq(irq, u14_34f_interrupt_handler,
+             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
+             driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
       return FALSE;
       }
 
    if (subversion == ISA && request_dma(dma_channel, driver_name)) {
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
-            name, dma_channel);
-      free_irq(irq, NULL);
+             name, dma_channel);
+      free_irq(irq, &sha[j]);
       return FALSE;
       }
 
@@ -695,7 +702,7 @@ __initfunc (static inline int port_detect \
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
 
-      if (!irqlist[irq]) free_irq(irq, NULL);
+      free_irq(irq, &sha[j]);
 
       if (subversion == ISA) free_dma(dma_channel);
 
@@ -734,7 +741,6 @@ __initfunc (static inline int port_detect \
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
    HD(j)->subversion = subversion;
    HD(j)->board_number = j;
-   irqlist[irq]++;
 
    if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 
@@ -767,12 +773,12 @@ __initfunc (static inline int port_detect \
       HD(j)->board_id[40] = 0;
 
       if (strcmp(&HD(j)->board_id[32], "06000600")) {
-        printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
-        printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
-               BN(j), &HD(j)->board_id[32]);
-        sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
-        sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
-        }
+         printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
+         printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
+                BN(j), &HD(j)->board_id[32]);
+         sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
+         }
       }
 
    if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST");
@@ -792,10 +798,11 @@ __initfunc (static inline int port_detect \
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
-   printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
-          "lc:%c, mq:%d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base,
-          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
-          YESNO(have_old_firmware), YESNO(linked_comm), max_queue_depth);
+   printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
+          "lc:%c, mq:%d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port,
+          (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
+          sh[j]->can_queue, YESNO(have_old_firmware), YESNO(linked_comm),
+          max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -857,11 +864,6 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) {
       }
 #endif
 
-   for (k = 0; k < MAX_IRQ; k++) {
-      irqlist[k] = 0;
-      calls[k] = 0;
-      }
-
    for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;
 
    for (k = 0; io_port[k]; k++) {
@@ -872,8 +874,9 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) {
       }
 
    if (j > 0) 
-      printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
+   num_boards = j;
    restore_flags(flags);
    return j;
 }
@@ -938,26 +941,26 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       if (i >= sh[j]->can_queue) i = 0;
 
       if (HD(j)->cp_stat[i] == FREE) {
-        HD(j)->last_cp_used = i;
-        break;
-        }
+         HD(j)->last_cp_used = i;
+         break;
+         }
       }
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
       if (HD(j)->in_reset) 
-        printk("%s: qcomm, already in reset.\n", BN(j));
+         printk("%s: qcomm, already in reset.\n", BN(j));
       else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
                == SCSI_RESET_SUCCESS) 
-        panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
+         panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    /* Set pointer to control packet structure */
@@ -969,16 +972,16 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-                       BN(j), i, SCpnt->channel, SCpnt->target, 
+                        BN(j), i, SCpnt->channel, SCpnt->target, 
                         SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
       if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-        cpp->xdir = DTD_OUT;
-        break;
-        }
+         cpp->xdir = DTD_OUT;
+         break;
+         }
 
    if (cpp->xdir == DTD_IN)
       for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
@@ -1023,7 +1026,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
              SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);
-      return 0;
+      return 1;
       }
 
    /* Store pointer in OGM address bytes */
@@ -1048,14 +1051,14 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
    if (SCarg->host_scribble == NULL
        || SCarg->serial_number != SCarg->serial_number_at_timeout) {
       printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
-            BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+             BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
-         BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+          BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1076,8 +1079,8 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
       printk("%s: abort, mbox %d is in use.\n", BN(j), i);
 
       if (SCarg != HD(j)->cp[i].SCpnt)
-        panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
-              BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
+         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
+               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
 
       if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED)
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
@@ -1103,7 +1106,7 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-            BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->pid);
       SCarg->scsi_done(SCarg);
       restore_flags(flags);
       return SCSI_ABORT_SUCCESS;
@@ -1123,7 +1126,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
    printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
-         BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
    if (SCarg->host_scribble == NULL)
@@ -1160,13 +1163,13 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
       if (HD(j)->cp_stat[i] == FREE) continue;
 
       if (HD(j)->cp_stat[i] == LOCKED) {
-        HD(j)->cp_stat[i] = FREE;
-        printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
-        continue;
-        }
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
+         continue;
+         }
 
       if (!(SCpnt = HD(j)->cp[i].SCpnt))
-        panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
@@ -1181,13 +1184,13 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          }
 
       if (SCpnt->host_scribble == NULL)
-        panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
+         panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
       if (*(unsigned int *)SCpnt->host_scribble != i) 
-        panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
+         panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
       if (SCpnt->scsi_done == NULL) 
-        panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
       }
@@ -1223,7 +1226,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-               BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1235,7 +1238,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-               BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else
@@ -1428,224 +1431,182 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
       }
 }
 
-static void u14_34f_interrupt_handler(int irq, void *dev_id,
-                                      struct pt_regs *regs) {
+static void u14_34f_interrupt_handler(int irq, void *shap,
+                                               struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, reg, ret;
+   unsigned int i, j, k, c, status, tstatus, reg, ret;
    struct mscp *spp;
 
-   save_flags(flags);
-   cli();
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
 
-   if (!irqlist[irq]) {
-      printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq);
-      restore_flags(flags);
+   if (sh[j]->irq != irq)
+       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
+
+   /* Check if this board need to be serviced */
+   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+
+   spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+
+   /* Clear interrupt pending flag */
+   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+
+   i = spp - HD(j)->cp;
+
+   if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+                                     || i >= sh[j]->can_queue)
+      panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
+            (void *)ret, HD(j)->cp);
+
+   if (HD(j)->cp_stat[i] == IGNORE) {
+      HD(j)->cp_stat[i] = FREE;
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == LOCKED) {
+      HD(j)->cp_stat[i] = FREE;
+      printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == FREE) {
+      printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+             HD(j)->iocount);
       return;
       }
+   else if (HD(j)->cp_stat[i] == IN_RESET)
+      printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE) 
+      panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", 
-                       driver_name, irq, calls[irq]);
-
-   /* Service all the boards configured on this irq */
-   for (j = 0; sh[j] != NULL; j++) {
+   HD(j)->cp_stat[i] = FREE;
+   SCpnt = spp->SCpnt;
 
-      if (sh[j]->irq != irq) continue;
+   if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-      loops = 0;
+   if (SCpnt->host_scribble == NULL) 
+      panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+            SCpnt->pid, SCpnt);
 
-      /* Loop until all interrupts for a board are serviced */
-      while ((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED) {
-        total_loops++;
-        loops++;
-
-        if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
-                             BN(j), HD(j)->iocount);
+   if (*(unsigned int *)SCpnt->host_scribble != i) 
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", 
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
 
-        spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+   if (linked_comm && SCpnt->device->queue_depth > 2
+                                     && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
 
-        /* Clear interrupt pending flag */
-        outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
-
-        i = spp - HD(j)->cp;
+   tstatus = status_byte(spp->target_status);
 
-        if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
-                                            || i >= sh[j]->can_queue)
-           panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n",
-                  BN(j), (void *)ret, HD(j)->cp);
-
-        if (HD(j)->cp_stat[i] == IGNORE) {
-           HD(j)->cp_stat[i] = FREE;
-           continue;
-           }
-        else if (HD(j)->cp_stat[i] == LOCKED) {
-           HD(j)->cp_stat[i] = FREE;
-           printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
-                  BN(j), i, HD(j)->iocount);
-           continue;
-           }
-        else if (HD(j)->cp_stat[i] == FREE) {
-           printk("%s: ihdlr, mbox %d is free, count %d.\n", 
-                  BN(j), i, HD(j)->iocount);
-           continue;
-           }
-        else if (HD(j)->cp_stat[i] == IN_RESET)
-           printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-        else if (HD(j)->cp_stat[i] != IN_USE) 
-           panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
-
-        HD(j)->cp_stat[i] = FREE;
-        SCpnt = spp->SCpnt;
-
-        if (SCpnt == NULL) 
-           panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
-
-        if (SCpnt->host_scribble == NULL) 
-           panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n",
-                 BN(j), i, SCpnt->pid, SCpnt);
-
-        if (*(unsigned int *)SCpnt->host_scribble != i) 
-           panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\
-                 " irq %d.\n", BN(j), i, SCpnt->pid, 
-                 *(unsigned int *)SCpnt->host_scribble, irq);
-
-         if (linked_comm && SCpnt->device->queue_depth > 2
-                                           && TLDEV(SCpnt->device->type))
-            flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
-
-        tstatus = status_byte(spp->target_status);
-
-        switch (spp->adapter_status) {
-           case ASOK:     /* status OK */
-
-              /* Forces a reset if a disk drive keeps returning BUSY */
-              if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-                 status = DID_ERROR << 16;
-
-              /* If there was a bus reset, redo operation on each target */
-              else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-                       && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-                 status = DID_BUS_BUSY << 16;
-
-              /* Works around a flaw in scsi.c */
-              else if (tstatus == CHECK_CONDITION
-                       && SCpnt->device->type == TYPE_DISK
-                       && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-                 status = DID_BUS_BUSY << 16;
-
-              else
-                 status = DID_OK << 16;
-
-              if (tstatus == GOOD)
-                 HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-
-              if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-                 printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                         "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-                        SCpnt->channel, SCpnt->target, SCpnt->lun,
-                         SCpnt->pid, spp->target_status,
-                         SCpnt->sense_buffer[2]);
-
-              HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-
-               if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
-
-              break;
-           case ASST:     /* Selection Time Out */
-
-              if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-                 status = DID_ERROR << 16;
-              else {
-                 status = DID_TIME_OUT << 16;
-                 HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-                 }
-
-              break;
-
-            /* Perform a limited number of internal retries */
-           case 0x93:     /* Unexpected bus free */
-           case 0x94:     /* Target bus phase sequence failure */
-           case 0x96:     /* Illegal SCSI command */
-           case 0xa3:     /* SCSI bus reset error */
-
-              for (c = 0; c <= sh[j]->max_channel; c++) 
-                 for (k = 0; k < sh[j]->max_id; k++) 
-                    HD(j)->target_redo[k][c] = TRUE;
-   
+   switch (spp->adapter_status) {
+      case ASOK:     /* status OK */
 
-           case 0x92:     /* Data over/under-run */
-
-              if (SCpnt->device->type != TYPE_TAPE
-                   && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-                 status = DID_BUS_BUSY << 16;
-                 HD(j)->retries++;
-                  HD(j)->last_retried_pid = SCpnt->pid;
-                  }
-              else 
-                 status = DID_ERROR << 16;
-
-              break;
-           case 0x01:     /* Invalid command */
-           case 0x02:     /* Invalid parameters */
-           case 0x03:     /* Invalid data list */
-           case 0x84:     /* SCSI bus abort error */
-           case 0x9b:     /* Auto request sense error */
-           case 0x9f:     /* Unexpected command complete message error */
-           case 0xff:     /* Invalid parameter in the S/G list */
-           default:
-              status = DID_ERROR << 16;
-              break;
-           }
-
-        SCpnt->result = status | spp->target_status;
-        HD(j)->iocount++;
-
-        if (loops > 1) HD(j)->multicount++;
+         /* Forces a reset if a disk drive keeps returning BUSY */
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+            status = DID_ERROR << 16;
 
-#if defined (DEBUG_INTERRUPT)
-        if (SCpnt->result || do_trace) 
-#else
-        if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-            (spp->adapter_status != ASOK && 
-             spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-              do_trace || msg_byte(spp->target_status))
-#endif
-           printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                  " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-                  BN(j), i, spp->adapter_status, spp->target_status,
-                  SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                   reg, HD(j)->iocount);
+         /* If there was a bus reset, redo operation on each target */
+         else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                  && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+            status = DID_BUS_BUSY << 16;
+
+         /* Works around a flaw in scsi.c */
+         else if (tstatus == CHECK_CONDITION
+                  && SCpnt->device->type == TYPE_DISK
+                  && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+            status = DID_BUS_BUSY << 16;
 
-        /* Set the command state to inactive */
-        SCpnt->host_scribble = NULL;
+         else
+            status = DID_OK << 16;
 
-        restore_flags(flags);
-        SCpnt->scsi_done(SCpnt);
-        cli();
+         if (tstatus == GOOD)
+            HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
 
-        }   /* Multiple command loop */
+         if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+            printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                   SCpnt->channel, SCpnt->target, SCpnt->lun,
+                   SCpnt->pid, spp->target_status,
+                   SCpnt->sense_buffer[2]);
 
-      }   /* Boards loop */
+         HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
 
-   calls[irq]++;
+         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
 
-#if defined (DEBUG_SMP)
-   if (total_loops == 0) 
-     printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
-           driver_name, irq, calls[irq]);
-#endif
+         break;
+      case ASST:     /* Selection Time Out */
+
+         if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+            status = DID_ERROR << 16;
+         else {
+            status = DID_TIME_OUT << 16;
+            HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+            }
 
-   if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
-                       driver_name, irq, calls[irq]);
+         break;
 
-#if defined (DEBUG_STATISTICS)
-   if ((calls[irq] % 100000) == 10000)
-      for (j = 0; sh[j] != NULL; j++)
-        printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j),
-               calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount);
+      /* Perform a limited number of internal retries */
+      case 0x93:     /* Unexpected bus free */
+      case 0x94:     /* Target bus phase sequence failure */
+      case 0x96:     /* Illegal SCSI command */
+      case 0xa3:     /* SCSI bus reset error */
+
+         for (c = 0; c <= sh[j]->max_channel; c++) 
+            for (k = 0; k < sh[j]->max_id; k++) 
+               HD(j)->target_redo[k][c] = TRUE;
+   
+
+      case 0x92:     /* Data over/under-run */
+
+         if (SCpnt->device->type != TYPE_TAPE
+             && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+            status = DID_BUS_BUSY << 16;
+            HD(j)->retries++;
+            HD(j)->last_retried_pid = SCpnt->pid;
+            }
+         else 
+            status = DID_ERROR << 16;
+
+         break;
+      case 0x01:     /* Invalid command */
+      case 0x02:     /* Invalid parameters */
+      case 0x03:     /* Invalid data list */
+      case 0x84:     /* SCSI bus abort error */
+      case 0x9b:     /* Auto request sense error */
+      case 0x9f:     /* Unexpected command complete message error */
+      case 0xff:     /* Invalid parameter in the S/G list */
+      default:
+         status = DID_ERROR << 16;
+         break;
+      }
+
+   SCpnt->result = status | spp->target_status;
+   HD(j)->iocount++;
+
+#if defined (DEBUG_INTERRUPT)
+   if (SCpnt->result || do_trace) 
+#else
+   if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+       (spp->adapter_status != ASOK && 
+        spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+        do_trace || msg_byte(spp->target_status))
 #endif
+      printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+             " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+             BN(j), i, spp->adapter_status, spp->target_status,
+             SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+             reg, HD(j)->iocount);
+
+   /* Set the command state to inactive */
+   SCpnt->host_scribble = NULL;
+
+   SCpnt->scsi_done(SCpnt);
+
+   if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-   restore_flags(flags);
    return;
 }
 
@@ -1664,7 +1625,7 @@ int u14_34f_release(struct Scsi_Host *shpnt) {
    for (i = 0; i < sh[j]->can_queue; i++) 
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL);
+   free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
 
index 244bc811d3b1be3726afbeb325ea9ac64738d9fb..7420b6fc60d2d914d1ba3244c686f14a95258ce4 100644 (file)
@@ -11,18 +11,41 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "3.11.00"
-
-#define ULTRASTOR_14_34F {                                                        \
-               name:              "UltraStor 14F/34F rev. " U14_34F_VERSION " ",  \
-               detect:            u14_34f_detect,                                 \
-               release:           u14_34f_release,                                \
-               queuecommand:      u14_34f_queuecommand,                           \
-               abort:             u14_34f_abort,                                  \
-               reset:             u14_34f_reset,                                  \
-               bios_param:        u14_34f_biosparam,                              \
-               this_id:           7,   /* this_id, reset by detect */             \
-               unchecked_isa_dma: 1,   /* unchecked isa dma, reset by detect */   \
-               use_clustering:    ENABLE_CLUSTERING                               \
-               }
+#define U14_34F_VERSION "4.02.00"
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88)
+
+#define ULTRASTOR_14_34F {                                                   \
+                name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
+                detect:       u14_34f_detect,                                \
+                release:      u14_34f_release,                               \
+                queuecommand: u14_34f_queuecommand,                          \
+                abort:        u14_34f_abort,                                 \
+                reset:        u14_34f_reset,                                 \
+                bios_param:   u14_34f_biosparam,                             \
+                this_id:      7,                                             \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering: ENABLE_CLUSTERING,                           \
+                use_new_eh_code: 1    /* Enable new error code */            \
+                }
+
+#else /* Use old scsi code */
+
+#define ULTRASTOR_14_34F {                                                   \
+                name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
+                detect:       u14_34f_detect,                                \
+                release:      u14_34f_release,                               \
+                queuecommand: u14_34f_queuecommand,                          \
+                abort:        u14_34f_abort,                                 \
+                reset:        u14_34f_reset,                                 \
+                bios_param:   u14_34f_biosparam,                             \
+                this_id:      7,                                             \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering: ENABLE_CLUSTERING,                           \
+                }
+
+#endif
+
 #endif
index 46c79fd2c07813bf8821b0484525e8292ed87c89..3db04b2a6afd9f211803c6427fb4380820bc1d14 100644 (file)
@@ -62,7 +62,7 @@ tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
 tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
 tristate 'Apple Macintosh filesystem support (experimental)' CONFIG_HFS_FS
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
-tristate 'Kernel automounter support (experimental)' CONFIG_AUTOFS_FS
+tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 if [ "$CONFIG_AFFS_FS" != "n" ]; then
   define_bool CONFIG_AMIGA_PARTITION y
 fi
@@ -74,6 +74,7 @@ if [ "$CONFIG_UFS_FS" != "n" ]; then
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS
+  tristate '/dev/pts filesystem support (EXPERIMENTAL)' CONFIG_DEVPTS_FS
 fi
 bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
 endmenu
index eb3458f9b8ac0664954c984950ae77e24756ba8f..5b14c03369cf44d58197ac601727574b74098539 100644 (file)
@@ -17,7 +17,8 @@ O_OBJS    = open.o read_write.o devices.o file_table.o buffer.o \
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
-               hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd nls
+               hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \
+               nls devpts
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -226,6 +227,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_DEVPTS_FS),y)
+SUB_DIRS += devpts
+else
+  ifeq ($(CONFIG_DEVPTS_FS),m)
+  MOD_SUB_DIRS += devpts
+  endif
+endif
+
 ifeq ($(CONFIG_BINFMT_ELF),y)
 BINFMTS += binfmt_elf.o
 else
index 3ddd5d5ccec96fd488db1a811dfb4a77c66689f7..234d8cf21c10c6277c3fa506ea557591eaaadf6e 100644 (file)
@@ -98,13 +98,11 @@ static struct super_operations adfs_sops = {
 static void adfs_put_super (struct super_block *sb)
 {
        int i;
-       lock_super (sb);
-       sb->s_dev = 0;
+
        for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
                brelse (sb->u.adfs_sb.s_map[i]);
        kfree (sb->u.adfs_sb.s_map);
        brelse (sb->u.adfs_sb.s_sbh);
-       unlock_super (sb);
        MOD_DEC_USE_COUNT;
 }
 
index b4ce6756f693e2cdc8e52f105c5f3b849f21d980..ed6ae67b31684d65ffd44799a508001c7c69c6fb 100644 (file)
@@ -46,7 +46,6 @@ affs_put_super(struct super_block *sb)
 
        pr_debug("affs_put_super()\n");
 
-       lock_super(sb);
        for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
                affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
        if (!(sb->s_flags & MS_RDONLY)) {
@@ -67,8 +66,6 @@ affs_put_super(struct super_block *sb)
         */
        set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
 
-       sb->s_dev = 0;
-       unlock_super(sb);
        MOD_DEC_USE_COUNT;
        return;
 }
index cbcefc34ad7b0345eae6e85a763a827d74625137..d17115208d40233e62de4a74793c381fba6f7688 100644 (file)
@@ -41,16 +41,13 @@ static void autofs_put_super(struct super_block *sb)
        if ( !sbi->catatonic )
                autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
-       lock_super(sb);
        autofs_hash_nuke(&sbi->dirhash);
        for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
                if ( test_bit(n, sbi->symlink_bitmap) )
                        kfree(sbi->symlink[n].data);
        }
 
-       sb->s_dev = 0;
        kfree(sb->u.generic_sbp);
-       unlock_super(sb);
 
        DPRINTK(("autofs: shutting down\n"));
        
index 36d38b84e69de503202c37eace320f2e64de5edb..60f9efe0109c554c38b6d0d295f8f40e2d9464b9 100644 (file)
@@ -109,8 +109,7 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str
        if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) {
                do {
                        if ( status && dentry->d_inode ) {
-                               printk("autofs: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name);
-                               printk("autofs: trying to recover, but prepare for Armageddon\n");
+                               printk("autofs warning: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name);
                                break;
                        }
 
@@ -146,7 +145,10 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str
                return !autofs_wait(sbi, &dentry->d_name);
        }
 
-       autofs_update_usage(&sbi->dirhash,ent);
+       /* We don't update the usages for the autofs daemon itself, this
+          is necessary for recursive autofs mounts */
+       if ( !autofs_oz_mode(sbi) )
+               autofs_update_usage(&sbi->dirhash,ent);
 
        dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
        return 1;
@@ -188,8 +190,10 @@ static int autofs_revalidate(struct dentry * dentry)
        }
 
        /* Update the usage list */
-       ent = (struct autofs_dir_ent *) dentry->d_time;
-       autofs_update_usage(&sbi->dirhash,ent);
+       if ( !autofs_oz_mode(sbi) ) {
+               ent = (struct autofs_dir_ent *) dentry->d_time;
+               autofs_update_usage(&sbi->dirhash,ent);
+       }
        return 1;
 }
 
index 96d07e265c05b2bd7b78365bf681fbdd156cd7e5..92543a15c280ad8eebdf7bdcc4eab3ae1ba972f9 100644 (file)
@@ -161,9 +161,6 @@ static void coda_put_super(struct super_block *sb)
 
         ENTRY;
 
-        lock_super(sb);
-
-        sb->s_dev = 0;
        coda_cache_clear_all(sb);
        sb_info = coda_sbp(sb);
        sb_info->sbi_vcomm->vc_inuse = 0;
@@ -171,7 +168,6 @@ static void coda_put_super(struct super_block *sb)
        printk("Coda: Bye bye.\n");
        memset(sb_info, 0, sizeof(* sb_info));
 
-        unlock_super(sb);
         MOD_DEC_USE_COUNT;
        EXIT;
 }
index 801db79fb6a691612ecb7f6839b253e01862e9aa..597ee660d4c9bcccb87c94c6b90329b848ef6b12 100644 (file)
@@ -780,16 +780,26 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen)
 asmlinkage int sys_getcwd(char *buf, unsigned long size)
 {
        int error;
-       unsigned long len;
-       char * page = (char *) __get_free_page(GFP_USER);
-       char * cwd = d_path(current->fs->pwd, page, PAGE_SIZE);
-
-       error = -ERANGE;
-       len = PAGE_SIZE + page - cwd;
-       if (len <= size) {
-               error = len;
-               if (copy_to_user(buf, cwd, len))
-                       error = -EFAULT;
+       struct dentry *pwd = current->fs->pwd; 
+
+       error = -ENOENT;
+       /* Has the current directory has been unlinked? */
+       if (pwd->d_parent != pwd && list_empty(&pwd->d_hash)) {
+               char *page = (char *) __get_free_page(GFP_USER);
+               error = -ENOMEM;
+               if (page) {
+                       unsigned long len;
+                       char * cwd = d_path(pwd, page, PAGE_SIZE);
+
+                       error = -ERANGE;
+                       len = PAGE_SIZE + page - cwd;
+                       if (len <= size) {
+                               error = len;
+                               if (copy_to_user(buf, cwd, len))
+                                       error = -EFAULT;
+                       }
+                       free_page((unsigned long) page);
+               }
        }
        return error;
 }
diff --git a/fs/devpts/Makefile b/fs/devpts/Makefile
new file mode 100644 (file)
index 0000000..b8be35a
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux /dev/pts virtual filesystem.
+#
+
+O_TARGET := devpts.o
+O_OBJS   := root.o inode.o
+
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/fs/devpts/devpts_i.h b/fs/devpts/devpts_i.h
new file mode 100644 (file)
index 0000000..03b6b06
--- /dev/null
@@ -0,0 +1,42 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/devpts_i.h
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#define BUILDING_DEVPTS 1
+#include <linux/devpts_fs.h>
+
+struct devpts_sb_info {
+       u32 magic;
+       struct super_block *next;
+       struct super_block **back;
+       int setuid;
+       int setgid;
+       uid_t   uid;
+       gid_t   gid;
+       umode_t mode;
+
+       struct inode *inodes[NR_PTYS];
+};
+
+#define DEVPTS_SUPER_MAGIC 0x1cd1
+#define DEVPTS_SBI_MAGIC   0x01da1d02
+
+extern inline struct devpts_sb_info *SBI(struct super_block *sb)
+{
+       return (struct devpts_sb_info *)(sb->u.generic_sbp);
+}
+
+extern struct inode_operations devpts_root_inode_operations;
+extern struct inode_operations devpts_device_inode_operations;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
new file mode 100644 (file)
index 0000000..54025e7
--- /dev/null
@@ -0,0 +1,374 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/inode.c
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kdev_t.h>
+#include <linux/kernel.h>
+#include <linux/locks.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/stat.h>
+#include <linux/tty.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#include "devpts_i.h"
+
+static struct super_block *mounts = NULL;
+
+static void devpts_put_inode(struct inode *inode)
+{
+}
+
+static void devpts_delete_inode(struct inode *inode)
+{
+       inode->i_size = 0;
+}
+
+static void devpts_put_super(struct super_block *sb)
+{
+       struct devpts_sb_info *sbi = SBI(sb);
+       struct inode *inode;
+       int i;
+
+       for ( i = 0 ; i < NR_PTYS ; i++ ) {
+               if ( (inode = sbi->inodes[i]) ) {
+                       if ( inode->i_count != 1 )
+                               printk("devpts_put_super: badness: entry %d count %d\n",
+                                      i, inode->i_count);
+                       iput(inode);
+               }
+       }
+
+       *sbi->back = sbi->next;
+       if ( sbi->next )
+               SBI(sbi->next)->back = sbi->back;
+
+       kfree(sbi);
+
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static void devpts_read_inode(struct inode *inode);
+static void devpts_write_inode(struct inode *inode);
+
+static struct super_operations devpts_sops = {
+       devpts_read_inode,
+       devpts_write_inode,
+       devpts_put_inode,
+       devpts_delete_inode,
+       NULL,                   /* notify_change */
+       devpts_put_super,
+       NULL,                   /* write_super */
+       devpts_statfs,
+       NULL,                   /* remount_fs */
+       NULL,                   /* clear_inode */
+};
+
+static int devpts_parse_options(char *options, struct devpts_sb_info *sbi)
+{
+       int setuid = 0;
+       int setgid = 0;
+       uid_t uid = 0;          /* To shut up gcc */
+       gid_t gid = 0;
+       umode_t mode = 0600;
+       char *this_char, *value;
+
+       if ( !options ) return 1;
+       for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+               if ((value = strchr(this_char,'=')) != NULL)
+                       *value++ = 0;
+               if (!strcmp(this_char,"uid")) {
+                       if (!value || !*value)
+                               return 1;
+                       uid = simple_strtoul(value,&value,0);
+                       if (*value)
+                               return 1;
+                       setuid = 1;
+               }
+               else if (!strcmp(this_char,"gid")) {
+                       if (!value || !*value)
+                               return 1;
+                       gid = simple_strtoul(value,&value,0);
+                       if (*value)
+                               return 1;
+                       setgid = 1;
+               }
+               else if (!strcmp(this_char,"mode")) {
+                       if (!value || !*value)
+                               return 1;
+                       mode = simple_strtoul(value,&value,8);
+                       if (*value)
+                               return 1;
+               }
+               else
+                       return 1;
+       }
+       sbi->setuid  = setuid;
+       sbi->setgid  = setgid;
+       sbi->uid     = uid;
+       sbi->gid     = gid;
+       sbi->mode    = mode & ~S_IFMT;
+
+       return 0;
+}
+
+struct super_block *devpts_read_super(struct super_block *s, void *data,
+                                     int silent)
+{
+       struct inode * root_inode;
+       struct dentry * root;
+       struct devpts_sb_info *sbi;
+
+       MOD_INC_USE_COUNT;
+
+       lock_super(s);
+       /* Super block already completed? */
+       if (s->s_root)
+               goto out_unlock;
+
+       sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL);
+       if ( !sbi )
+               goto fail_unlock;
+
+       sbi->magic = DEVPTS_SBI_MAGIC;
+       memset(sbi->inodes, 0, sizeof sbi->inodes);
+
+       s->u.generic_sbp = (void *) sbi;
+       s->s_blocksize = 1024;
+       s->s_blocksize_bits = 10;
+       s->s_magic = DEVPTS_SUPER_MAGIC;
+       s->s_op = &devpts_sops;
+       s->s_root = NULL;
+       unlock_super(s); /* shouldn't we keep it locked a while longer? */
+
+       /*
+        * Get the root inode and dentry, but defer checking for errors.
+        */
+       root_inode = iget(s, 1); /* inode 1 == root directory */
+       root = d_alloc_root(root_inode, NULL);
+
+       /*
+        * Check whether somebody else completed the super block.
+        */
+       if (s->s_root)
+               goto out_dput;
+
+       if (!root)
+               goto fail_iput;
+
+       /* Can this call block?  (It shouldn't) */
+       if ( devpts_parse_options(data,sbi) ) {
+               printk("devpts: called with bogus options\n");
+               goto fail_dput;
+       }
+
+       /*
+        * Check whether somebody else completed the super block.
+        */
+       if (s->s_root)
+               goto out_dec;
+       
+       /*
+        * Success! Install the root dentry now to indicate completion.
+        */
+       lock_super(s);
+       s->s_root = root;
+
+       sbi->next = mounts;
+       if ( sbi->next )
+               SBI(sbi->next)->back = &(sbi->next);
+       sbi->back = &mounts;
+       mounts = s;
+
+       unlock_super(s);
+       return s;
+
+       /*
+        * Success ... somebody else completed the super block for us. 
+        */ 
+out_unlock:
+       unlock_super(s);
+       goto out_dec;
+out_dput:
+       if (root)
+               dput(root);
+       else
+               iput(root_inode);
+out_dec:
+       MOD_DEC_USE_COUNT;
+       return s;
+       
+       /*
+        * Failure ... clear the s_dev slot and clean up.
+        */
+fail_dput:
+       /*
+        * dput() can block, so we clear the super block first.
+        */
+       s->s_dev = 0;
+       dput(root);
+       goto fail_free;
+fail_iput:
+       printk("devpts: get root dentry failed\n");
+       /*
+        * iput() can block, so we clear the super block first.
+        */
+       s->s_dev = 0;
+       iput(root_inode);
+fail_free:
+       kfree(sbi);
+       goto fail_dec;
+fail_unlock:
+       unlock_super(s);
+fail_dec:
+       s->s_dev = 0;
+       MOD_DEC_USE_COUNT;
+       return NULL;
+}
+
+static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+       struct statfs tmp;
+
+       tmp.f_type = DEVPTS_SUPER_MAGIC;
+       tmp.f_bsize = 1024;
+       tmp.f_blocks = 0;
+       tmp.f_bfree = 0;
+       tmp.f_bavail = 0;
+       tmp.f_files = 0;
+       tmp.f_ffree = 0;
+       tmp.f_namelen = NAME_MAX;
+       return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static void devpts_read_inode(struct inode *inode)
+{
+       ino_t ino = inode->i_ino;
+
+       inode->i_op = NULL;
+       inode->i_mode = 0;
+       inode->i_nlink = 0;
+       inode->i_size = 0;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+       inode->i_blocks = 0;
+       inode->i_blksize = 1024;
+       inode->i_uid = inode->i_gid = 0;
+
+       if ( ino == 1 ) {
+               inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+               inode->i_op = &devpts_root_inode_operations;
+               inode->i_nlink = 2;
+               return;
+       } 
+
+       ino -= 2;
+       if ( ino >= NR_PTYS )
+               return;         /* Bogus */
+       
+       inode->i_nlink = 1;
+
+       inode->i_mode = S_IFCHR;
+       inode->i_rdev = MKDEV(0,0); /* Gets filled in by devpts_pty_new() */
+
+       inode->i_op = &chrdev_inode_operations;
+
+       return;
+}
+
+static void devpts_write_inode(struct inode *inode)
+{
+}
+
+static struct file_system_type devpts_fs_type = {
+       "devpts",
+       0,
+       devpts_read_super,
+       NULL
+};
+
+void devpts_pty_new(int number, kdev_t device)
+{
+       struct super_block *sb;
+       struct devpts_sb_info *sbi;
+       struct inode *inode;
+               
+       for ( sb = mounts ; sb ; sb = sbi->next ) {
+               sbi = SBI(sb);
+
+               if ( sbi->inodes[number] ) {
+                       continue; /* Already registered, this does happen */
+               }
+               
+               /* Yes, this looks backwards, but it is correct */
+               inode = iget(sb, number+2);
+               if ( inode ) {
+                       inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
+                       inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
+                       inode->i_mode = sbi->mode | S_IFCHR;
+                       inode->i_rdev = device;
+                       sbi->inodes[number] = inode;
+               }
+       }
+}
+
+void devpts_pty_kill(int number)
+{
+       struct super_block *sb;
+       struct devpts_sb_info *sbi;
+       struct inode *inode;
+               
+       for ( sb = mounts ; sb ; sb = sbi->next ) {
+               sbi = SBI(sb);
+
+               inode = sbi->inodes[number];
+
+               if ( inode ) {
+                       sbi->inodes[number] = NULL;
+                       inode->i_nlink = 0; /* Is this right? */
+                       iput(inode);
+               }
+       }
+}
+
+__initfunc(int init_devpts_fs(void))
+{
+       return register_filesystem(&devpts_fs_type);
+
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+       int err = init_devpts_fs();
+       if ( !err ) {
+               devpts_upcall_new  = devpts_pty_new;
+               devpts_upcall_kill = devpts_pty_kill;
+       }
+       return err;
+}
+
+void cleanup_module(void)
+{
+       devpts_upcall_new  = NULL;
+       devpts_upcall_kill = NULL;
+       unregister_filesystem(&devpts_fs_type);
+}
+
+#endif
diff --git a/fs/devpts/root.c b/fs/devpts/root.c
new file mode 100644 (file)
index 0000000..1d48836
--- /dev/null
@@ -0,0 +1,169 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/root.c
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/param.h>
+#include "devpts_i.h"
+
+static int devpts_root_readdir(struct file *,void *,filldir_t);
+static int devpts_root_lookup(struct inode *,struct dentry *);
+static int devpts_revalidate(struct dentry *);
+
+static struct file_operations devpts_root_operations = {
+       NULL,                   /* llseek */
+       NULL,                   /* read */
+       NULL,                   /* write */
+       devpts_root_readdir,    /* readdir */
+       NULL,                   /* poll */
+       NULL,                   /* ioctl */
+       NULL,                   /* mmap */
+       NULL,                   /* open */
+       NULL,                   /* release */
+       NULL,                   /* fsync */
+       NULL,                   /* fasync */
+       NULL,                   /* check_media_change */
+       NULL,                   /* revalidate */
+       NULL                    /* lock */
+};
+
+struct inode_operations devpts_root_inode_operations = {
+       &devpts_root_operations, /* file operations */
+       NULL,                   /* create */
+       devpts_root_lookup,     /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL,                   /* permission */
+       NULL,                   /* smap */
+       NULL,                   /* updatepage */
+       NULL                    /* revalidate */
+};
+
+static struct dentry_operations devpts_dentry_operations = {
+       devpts_revalidate,      /* d_revalidate */
+       NULL,                   /* d_hash */
+       NULL,                   /* d_compare */
+};
+
+/*
+ * The normal naming convention is simply /dev/pts/<number>; this conforms
+ * to the System V naming convention
+ */
+
+#define genptsname(buf,num) sprintf(buf, "%d", num)
+
+static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct inode * inode = filp->f_dentry->d_inode;
+       struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
+       off_t nr;
+       char numbuf[16];
+
+       if (!inode || !S_ISDIR(inode->i_mode))
+               return -ENOTDIR;
+
+       nr = filp->f_pos;
+
+       switch(nr)
+       {
+       case 0:
+               if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
+                       return 0;
+               filp->f_pos = ++nr;
+               /* fall through */
+       case 1:
+               if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
+                       return 0;
+               filp->f_pos = ++nr;
+               /* fall through */
+       default:
+               while ( nr < NR_PTYS+2 ) {
+                       int ptynr = nr - 2;
+                       if ( sbi->inodes[ptynr] ) {
+                               genptsname(numbuf, ptynr);
+                               if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
+                                       return 0;
+                       }
+                       filp->f_pos = ++nr;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Revalidate is called on every cache lookup.  We use it to check that
+ * the pty really does still exist.  Never revalidate negative dentries;
+ * for simplicity (fix later?)
+ */
+static int devpts_revalidate(struct dentry * dentry)
+{
+       struct devpts_sb_info *sbi;
+
+       if ( !dentry->d_inode )
+               return 0;
+
+       sbi = SBI(dentry->d_inode->i_sb);
+
+       return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
+}
+
+static int devpts_root_lookup(struct inode * dir, struct dentry * dentry)
+{
+       struct devpts_sb_info *sbi = SBI(dir->i_sb);
+       int entry, i;
+       const char *p;
+
+       if (!S_ISDIR(dir->i_mode))
+               return -ENOTDIR;
+
+       dentry->d_inode = NULL; /* Assume failure */
+       dentry->d_op    = &devpts_dentry_operations;
+
+       if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
+               entry = 0;
+       } else if ( dentry->d_name.len < 1 ) {
+               return 0;
+       } else {
+               p = dentry->d_name.name;
+               if ( *p < '1' || *p > '9' )
+                       return 0;
+               entry = *p++ - '0';
+
+               for ( i = dentry->d_name.len-1 ; i ; i-- ) {
+                       if ( *p < '0' || *p > '9' )
+                               return 0;
+                       entry *= 10;
+                       entry += (*p++ - '0');
+               }
+       }
+       
+       dentry->d_inode = sbi->inodes[entry];
+       if ( dentry->d_inode )
+               dentry->d_inode->i_count++;
+
+       d_add(dentry, dentry->d_inode);
+
+       return 0;
+}
index 835e4e9fdb991418d278e638e195bbe4e3bfedae..6a054ecdde26bfc1ce2578e2d7458f885a7bec5d 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -684,15 +684,8 @@ void compute_creds(struct linux_binprm *bprm)
        current->cap_permitted.cap = new_permitted;
        current->cap_effective.cap = new_permitted & bprm->cap_effective.cap;
        
-        /* XXX - Audit candidate */
-        if (!cap_isclear(current->cap_effective)) {
-                printk(KERN_NOTICE
-                      "raising capabilities on `%s'(pid=%d) [%04x]:%lu\n",
-                      current->comm, current->pid,
-                      kdev_t_to_nr(bprm->dentry->d_inode->i_dev), 
-                      bprm->dentry->d_inode->i_ino);
-        }
-       
+        /* AUD: Audit candidate if current->cap_effective is set */
+
         current->suid = current->euid = current->fsuid = bprm->e_uid;
         current->sgid = current->egid = current->fsgid = bprm->e_gid;
         if (current->euid != current->uid || current->egid != current->gid ||
index 4f2e65bfc994e690b69dac8b6696139d7639cbf3..de5b422eddecbc872b0b31d6d1b8f3f8113ac1cb 100644 (file)
 
 #define in_range(b, first, len)                ((b) >= (first) && (b) <= (first) + (len) - 1)
 
-static struct ext2_group_desc * get_group_desc (struct super_block * sb,
-                                               unsigned int block_group,
-                                               struct buffer_head ** bh)
+struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+                                            unsigned int block_group,
+                                            struct buffer_head ** bh)
 {
        unsigned long group_desc;
        unsigned long desc;
        struct ext2_group_desc * gdp;
 
-       if (block_group >= sb->u.ext2_sb.s_groups_count)
-               ext2_panic (sb, "get_group_desc",
+       if (block_group >= sb->u.ext2_sb.s_groups_count) {
+               ext2_error (sb, "ext2_get_group_desc",
                            "block_group >= groups_count - "
                            "block_group = %d, groups_count = %lu",
                            block_group, sb->u.ext2_sb.s_groups_count);
 
+               return NULL;
+       }
+       
        group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
        desc = block_group % EXT2_DESC_PER_BLOCK(sb);
-       if (!sb->u.ext2_sb.s_group_desc[group_desc])
-               ext2_panic (sb, "get_group_desc",
+       if (!sb->u.ext2_sb.s_group_desc[group_desc]) {
+               ext2_error (sb, "ext2_get_group_desc",
                            "Group descriptor not loaded - "
                            "block_group = %d, group_desc = %lu, desc = %lu",
                             block_group, group_desc, desc);
+               return NULL;
+       }
+       
        gdp = (struct ext2_group_desc *) 
              sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
        if (bh)
@@ -66,22 +72,40 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
        return gdp + desc;
 }
 
-static void read_block_bitmap (struct super_block * sb,
+/*
+ * Read the bitmap for a given block_group, reading into the specified 
+ * slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_block_bitmap (struct super_block * sb,
                               unsigned int block_group,
                               unsigned long bitmap_nr)
 {
        struct ext2_group_desc * gdp;
-       struct buffer_head * bh;
+       struct buffer_head * bh = NULL;
+       int retval = 0;
        
-       gdp = get_group_desc (sb, block_group, NULL);
+       gdp = ext2_get_group_desc (sb, block_group, NULL);
+       if (!gdp)
+               goto error_out;
        bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
-       if (!bh)
-               ext2_panic (sb, "read_block_bitmap",
+       if (!bh) {
+               ext2_error (sb, "read_block_bitmap",
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %lu",
-                           block_group, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
+                           block_group, (unsigned long) gdp->bg_block_bitmap);
+               retval = -EIO;
+       }
+       /*
+        * On IO error, just leave a zero in the superblock's block pointer for
+        * this group.  The IO will be retried next time.
+        */
+error_out:
        sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
+       return retval;
 }
 
 /*
@@ -94,11 +118,13 @@ static void read_block_bitmap (struct super_block * sb,
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ * 
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load__block_bitmap (struct super_block * sb,
                               unsigned int block_group)
 {
-       int i, j;
+       int i, j, retval = 0;
        unsigned long block_bitmap_number;
        struct buffer_head * block_bitmap;
 
@@ -110,16 +136,16 @@ static int load__block_bitmap (struct super_block * sb,
 
        if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
                if (sb->u.ext2_sb.s_block_bitmap[block_group]) {
-                       if (sb->u.ext2_sb.s_block_bitmap_number[block_group] !=
+                       if (sb->u.ext2_sb.s_block_bitmap_number[block_group] ==
                            block_group)
-                               ext2_panic (sb, "load_block_bitmap",
-                                           "block_group != block_bitmap_number");
-                       else
                                return block_group;
-               } else {
-                       read_block_bitmap (sb, block_group, block_group);
-                       return block_group;
+                       ext2_error (sb, "load_block_bitmap",
+                                   "block_group != block_bitmap_number");
                }
+               retval = read_block_bitmap (sb, block_group, block_group);
+               if (retval < 0)
+                       return retval;
+               return block_group;
        }
 
        for (i = 0; i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
@@ -137,6 +163,14 @@ static int load__block_bitmap (struct super_block * sb,
                }
                sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
                sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
+
+               /*
+                * There's still one special case here --- if block_bitmap == 0
+                * then our last attempt to read the bitmap failed and we have
+                * just ended up caching that failure.  Try again to read it.
+                */
+               if (!block_bitmap)
+                       retval = read_block_bitmap (sb, block_group, 0);
        } else {
                if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
                        sb->u.ext2_sb.s_loaded_block_bitmaps++;
@@ -148,24 +182,71 @@ static int load__block_bitmap (struct super_block * sb,
                        sb->u.ext2_sb.s_block_bitmap[j] =
                                sb->u.ext2_sb.s_block_bitmap[j - 1];
                }
-               read_block_bitmap (sb, block_group, 0);
+               retval = read_block_bitmap (sb, block_group, 0);
        }
-       return 0;
+       return retval;
 }
 
+/*
+ * Load the block bitmap for a given block group.  First of all do a couple
+ * of fast lookups for common cases and then pass the request onto the guts
+ * of the bitmap loader.
+ *
+ * Return the slot number of the group in the superblock bitmap cache's on
+ * success, or a -ve error code.
+ *
+ * There is still one inconsistancy here --- if the number of groups in this
+ * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of 
+ * differentiating between a group for which we have never performed a bitmap
+ * IO request, and a group for which the last bitmap read request failed.
+ */
 static inline int load_block_bitmap (struct super_block * sb,
                                     unsigned int block_group)
 {
-       if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
-           sb->u.ext2_sb.s_block_bitmap_number[0] == block_group)
-               return 0;
+       int slot;
        
-       if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
-           sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
-           sb->u.ext2_sb.s_block_bitmap[block_group]) 
-               return block_group;
+       /*
+        * Do the lookup for the slot.  First of all, check if we're asking
+        * for the same slot as last time, and did we succeed that last time?
+        */
+       if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
+           sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
+           sb->u.ext2_sb.s_block_bitmap[block_group]) {
+               slot = 0;
+       }
+       /*
+        * Or can we do a fast lookup based on a loaded group on a filesystem
+        * small enough to be mapped directly into the superblock?
+        */
+       else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
+                sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
+                sb->u.ext2_sb.s_block_bitmap[block_group]) {
+               slot = block_group;
+       }
+       /*
+        * If not, then do a full lookup for this block group.
+        */
+       else {
+               slot = load__block_bitmap (sb, block_group);
+       }
 
-       return load__block_bitmap (sb, block_group);
+       /*
+        * <0 means we just got an error
+        */
+       if (slot < 0)
+               return slot;
+       
+       /*
+        * If it's a valid slot, we may still have cached a previous IO error,
+        * in which case the bh in the superblock cache will be zero.
+        */
+       if (!sb->u.ext2_sb.s_block_bitmap[slot])
+               return -EIO;
+       
+       /*
+        * Must have been read in OK to get this far.
+        */
+       return slot;
 }
 
 void ext2_free_blocks (const struct inode * inode, unsigned long block,
@@ -194,8 +275,7 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
                ext2_error (sb, "ext2_free_blocks",
                            "Freeing blocks not in datazone - "
                            "block = %lu, count = %lu", block, count);
-               unlock_super (sb);
-               return;
+               goto error_return;
        }
 
        ext2_debug ("freeing block %lu\n", block);
@@ -215,8 +295,13 @@ do_more:
                count -= overflow;
        }
        bitmap_nr = load_block_bitmap (sb, block_group);
+       if (bitmap_nr < 0)
+               goto error_return;
+       
        bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
-       gdp = get_group_desc (sb, block_group, &bh2);
+       gdp = ext2_get_group_desc (sb, block_group, &bh2);
+       if (!gdp)
+               goto error_return;
 
        if (test_opt (sb, CHECK_STRICT) &&
            (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
@@ -259,6 +344,7 @@ do_more:
                goto do_more;
        }
        sb->s_dirt = 1;
+error_return:
        unlock_super (sb);
        return;
 }
@@ -312,7 +398,10 @@ repeat:
            goal >= le32_to_cpu(es->s_blocks_count))
                goal = le32_to_cpu(es->s_first_data_block);
        i = (goal - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb);
-       gdp = get_group_desc (sb, i, &bh2);
+       gdp = ext2_get_group_desc (sb, i, &bh2);
+       if (!gdp)
+               goto io_error;
+
        if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
                j = ((goal - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb));
 #ifdef EXT2FS_DEBUG
@@ -320,6 +409,9 @@ repeat:
                        goal_attempts++;
 #endif
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       goto io_error;
+               
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
                ext2_debug ("goal is at %d:%d.\n", i, j);
@@ -384,7 +476,12 @@ repeat:
                i++;
                if (i >= sb->u.ext2_sb.s_groups_count)
                        i = 0;
-               gdp = get_group_desc (sb, i, &bh2);
+               gdp = ext2_get_group_desc (sb, i, &bh2);
+               if (!gdp) {
+                       *err = -EIO;
+                       unlock_super (sb);
+                       return 0;
+               }
                if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
                        break;
        }
@@ -393,6 +490,9 @@ repeat:
                return 0;
        }
        bitmap_nr = load_block_bitmap (sb, i);
+       if (bitmap_nr < 0)
+               goto io_error;
+       
        bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
        r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
        j = (r - bh->b_data) << 3;
@@ -455,10 +555,16 @@ got_block:
         */
 #ifdef EXT2_PREALLOCATE
        if (prealloc_block) {
+               int     prealloc_goal;
+
+               prealloc_goal = es->s_prealloc_blocks ?
+                       es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS;
+
                *prealloc_count = 0;
                *prealloc_block = tmp + 1;
                for (k = 1;
-                    k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) {
+                    k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);
+                    k++) {
                        if (sb->dq_op)
                                if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)))
                                        break;
@@ -516,6 +622,12 @@ got_block:
        unlock_super (sb);
        *err = 0;
        return j;
+       
+io_error:
+       *err = -EIO;
+       unlock_super (sb);
+       return 0;
+       
 }
 
 unsigned long ext2_count_free_blocks (struct super_block * sb)
@@ -533,9 +645,14 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
        bitmap_count = 0;
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-               gdp = get_group_desc (sb, i, NULL);
+               gdp = ext2_get_group_desc (sb, i, NULL);
+               if (!gdp)
+                       continue;
                desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
                                     sb->s_blocksize);
                printk ("group %d: stored = %d, counted = %lu\n",
@@ -590,12 +707,17 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
        desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
                      EXT2_DESC_PER_BLOCK(sb);
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-               gdp = get_group_desc (sb, i, NULL);
+               gdp = ext2_get_group_desc (sb, i, NULL);
+               if (!gdp)
+                       continue;
                desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
-               if (!(sb->u.ext2_sb.s_feature_ro_compat &
+               if (!(le32_to_cpu(sb->u.ext2_sb.s_feature_ro_compat) &
                     EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
                    (test_root(i, 3) || test_root(i, 5) || test_root(i, 7))) {
                        if (!ext2_test_bit (0, bh->b_data))
index 6560d511dfc396043d858a3f8f4703d1b784609d..19241876de07079431bfcdf0385f9acde53e4e4b 100644 (file)
@@ -75,7 +75,8 @@ struct inode_operations ext2_dir_inode_operations = {
 };
 
 int ext2_check_dir_entry (const char * function, struct inode * dir,
-                         struct ext2_dir_entry * de, struct buffer_head * bh,
+                         struct ext2_dir_entry_2 * de,
+                         struct buffer_head * bh,
                          unsigned long offset)
 {
        const char * error_msg = NULL;
@@ -84,7 +85,7 @@ int ext2_check_dir_entry (const char * function, struct inode * dir,
                error_msg = "rec_len is smaller than minimal";
        else if (le16_to_cpu(de->rec_len) % 4 != 0)
                error_msg = "rec_len % 4 != 0";
-       else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)))
+       else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len))
                error_msg = "rec_len is too small for name_len";
        else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) >
                 dir->i_sb->s_blocksize)
@@ -97,7 +98,7 @@ int ext2_check_dir_entry (const char * function, struct inode * dir,
                            "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
                            dir->i_ino, error_msg, offset,
                            (unsigned long) le32_to_cpu(de->inode),
-                           le16_to_cpu(de->rec_len), le16_to_cpu(de->name_len));
+                           le16_to_cpu(de->rec_len), de->name_len);
        return error_msg == NULL ? 1 : 0;
 }
 
@@ -108,7 +109,7 @@ static int ext2_readdir(struct file * filp,
        unsigned long offset, blk;
        int i, num, stored;
        struct buffer_head * bh, * tmp, * bha[16];
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        struct super_block * sb;
        int err;
        struct inode *inode = filp->f_dentry->d_inode;
@@ -158,7 +159,7 @@ revalidate:
                 * to make sure. */
                if (filp->f_version != inode->i_version) {
                        for (i = 0; i < sb->s_blocksize && i < offset; ) {
-                               de = (struct ext2_dir_entry *) 
+                               de = (struct ext2_dir_entry_2 *) 
                                        (bh->b_data + i);
                                /* It's too expensive to do a full
                                 * dirent test each time round this
@@ -178,7 +179,7 @@ revalidate:
                
                while (!error && filp->f_pos < inode->i_size 
                       && offset < sb->s_blocksize) {
-                       de = (struct ext2_dir_entry *) (bh->b_data + offset);
+                       de = (struct ext2_dir_entry_2 *) (bh->b_data + offset);
                        if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
                                                   bh, offset)) {
                                /* On error, skip the f_pos to the
@@ -200,7 +201,7 @@ revalidate:
                                unsigned long version = inode->i_version;
 
                                error = filldir(dirent, de->name,
-                                               le16_to_cpu(de->name_len),
+                                               de->name_len,
                                                filp->f_pos, le32_to_cpu(de->inode));
                                if (error)
                                        break;
index db9e4808c6d4ff920f8c398dd5e57ff1f7a723bc..ae3c84667d12e36cb1f775e4f5f62cbb77805d33 100644 (file)
@@ -13,6 +13,9 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  ext2 fs regular file handling primitives
+ *
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ *     (jj@sunsite.ms.mff.cuni.cz)
  */
 
 #include <asm/uaccess.h>
 static long long ext2_file_lseek(struct file *, long long, int);
 static ssize_t ext2_file_write (struct file *, const char *, size_t, loff_t *);
 static int ext2_release_file (struct inode *, struct file *);
+#if BITS_PER_LONG < 64
+static int ext2_open_file (struct inode *, struct file *);
+
+#else
+
+#define EXT2_MAX_SIZE(bits)                                                    \
+       (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) +                             \
+          (1LL << (bits - 2)) * (1LL << (bits - 2)) +                          \
+          (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) *   \
+         (1LL << bits)) - 1)
+
+static long long ext2_max_sizes[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
+};
+
+#endif
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -49,7 +69,11 @@ static struct file_operations ext2_file_operations = {
        NULL,                   /* poll - default */
        ext2_ioctl,             /* ioctl */
        generic_file_mmap,      /* mmap */
+#if BITS_PER_LONG == 64        
        NULL,                   /* no special open is needed */
+#else
+       ext2_open_file,
+#endif
        ext2_release_file,      /* release */
        ext2_sync_file,         /* fsync */
        NULL,                   /* fasync */
@@ -86,7 +110,6 @@ static long long ext2_file_lseek(
        long long offset,
        int origin)
 {
-       long long retval;
        struct inode *inode = file->f_dentry->d_inode;
 
        switch (origin) {
@@ -96,17 +119,20 @@ static long long ext2_file_lseek(
                case 1:
                        offset += file->f_pos;
        }
-       retval = -EINVAL;
-       /* make sure the offset fits in 32 bits */
-       if (((unsigned long long) offset >> 32) == 0) {
-               if (offset != file->f_pos) {
-                       file->f_pos = offset;
-                       file->f_reada = 0;
-                       file->f_version = ++event;
-               }
-               retval = offset;
+       if (((unsigned long long) offset >> 32) != 0) {
+#if BITS_PER_LONG < 64
+               return -EINVAL;
+#else
+               if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
+                       return -EINVAL;
+#endif
+       } 
+       if (offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_reada = 0;
+               file->f_version = ++event;
        }
-       return retval;
+       return offset;
 }
 
 static inline void remove_suid(struct inode *inode)
@@ -128,7 +154,7 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf,
                                size_t count, loff_t *ppos)
 {
        struct inode * inode = filp->f_dentry->d_inode;
-       __u32 pos;
+       off_t pos;
        long block;
        int offset;
        int written, c;
@@ -165,14 +191,37 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf,
                pos = *ppos;
                if (pos != *ppos)
                        return -EINVAL;
+#if BITS_PER_LONG >= 64
+               if (pos > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)])
+                       return -EINVAL;
+#endif
        }
 
        /* Check for overflow.. */
+#if BITS_PER_LONG < 64
        if (pos > (__u32) (pos + count)) {
                count = ~pos; /* == 0xFFFFFFFF - pos */
                if (!count)
                        return -EFBIG;
        }
+#else
+       off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
+
+       if (pos + count > max) {
+               count = max - pos;
+               if (!count)
+                       return -EFBIG;
+       }
+       if (((pos + count) >> 32) && 
+           !(sb->u.ext2_sb.s_es->s_feature_ro_compat &
+             cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+               /* If this is the first large file created, add a flag
+                  to the superblock */
+               sb->u.ext2_sb.s_es->s_feature_ro_compat |=
+                       cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+       }
+#endif
 
        /*
         * If a file has been opened in synchronous mode, we have to ensure
@@ -265,12 +314,25 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf,
 
 /*
  * Called when an inode is released. Note that this is different
- * from ext2_open: open gets called at every open, but release
+ * from ext2_file_open: open gets called at every open, but release
  * gets called only when /all/ the files are closed.
  */
 static int ext2_release_file (struct inode * inode, struct file * filp)
 {
-       if (filp->f_mode & 2)
+       if (filp->f_mode & FMODE_WRITE)
                ext2_discard_prealloc (inode);
        return 0;
 }
+
+#if BITS_PER_LONG < 64
+/*
+ * Called when an inode is about to be open.
+ * We use this to disallow opening RW large files on 32bit systems.
+ */
+static int ext2_open_file (struct inode * inode, struct file * filp)
+{
+       if (inode->u.ext2_i.i_high_size && (filp->f_mode & FMODE_WRITE))
+               return -EFBIG;
+       return 0;
+}
+#endif
index 19b38753bae4d65ac08b9008354708e382c129d9..a4a067dcb37809195ac5d5e2bf349df35f416fb4 100644 (file)
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 
-static struct ext2_group_desc * get_group_desc (struct super_block * sb,
-                                               unsigned int block_group,
-                                               struct buffer_head ** bh)
-{
-       unsigned long group_desc;
-       unsigned long desc;
-       struct ext2_group_desc * gdp;
-
-       if (block_group >= sb->u.ext2_sb.s_groups_count)
-               ext2_panic (sb, "get_group_desc",
-                           "block_group >= groups_count - "
-                           "block_group = %d, groups_count = %lu",
-                           block_group, sb->u.ext2_sb.s_groups_count);
-
-       group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
-       desc = block_group % EXT2_DESC_PER_BLOCK(sb);
-       if (!sb->u.ext2_sb.s_group_desc[group_desc])
-               ext2_panic (sb, "get_group_desc",
-                           "Group descriptor not loaded - "
-                           "block_group = %d, group_desc = %lu, desc = %lu",
-                            block_group, group_desc, desc);
-       gdp = (struct ext2_group_desc *) 
-               sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
-       if (bh)
-               *bh = sb->u.ext2_sb.s_group_desc[group_desc];
-       return gdp + desc;
-}
-
-static void read_inode_bitmap (struct super_block * sb,
+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+static int read_inode_bitmap (struct super_block * sb,
                               unsigned long block_group,
                               unsigned int bitmap_nr)
 {
        struct ext2_group_desc * gdp;
-       struct buffer_head * bh;
+       struct buffer_head * bh = NULL;
+       int retval = 0;
 
-       gdp = get_group_desc (sb, block_group, NULL);
+       gdp = ext2_get_group_desc (sb, block_group, NULL);
+       if (!gdp) {
+               retval = -EIO;
+               goto error_out;
+       }
        bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
-       if (!bh)
-               ext2_panic (sb, "read_inode_bitmap",
+       if (!bh) {
+               ext2_error (sb, "read_inode_bitmap",
                            "Cannot read inode bitmap - "
                            "block_group = %lu, inode_bitmap = %lu",
-                           block_group, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
+                           block_group, (unsigned long) gdp->bg_inode_bitmap);
+               retval = -EIO;
+       }
+       /*
+        * On IO error, just leave a zero in the superblock's block pointer for
+        * this group.  The IO will be retried next time.
+        */
+error_out:
        sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
+       return retval;
 }
 
 /*
@@ -93,11 +84,13 @@ static void read_inode_bitmap (struct super_block * sb,
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ * 
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load_inode_bitmap (struct super_block * sb,
                              unsigned int block_group)
 {
-       int i, j;
+       int i, j, retval = 0;
        unsigned long inode_bitmap_number;
        struct buffer_head * inode_bitmap;
 
@@ -117,7 +110,10 @@ static int load_inode_bitmap (struct super_block * sb,
                        else
                                return block_group;
                } else {
-                       read_inode_bitmap (sb, block_group, block_group);
+                       retval = read_inode_bitmap (sb, block_group,
+                                                   block_group);
+                       if (retval < 0)
+                               return retval;
                        return block_group;
                }
        }
@@ -138,6 +134,15 @@ static int load_inode_bitmap (struct super_block * sb,
                }
                sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
                sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
+
+               /*
+                * There's still one special case here --- if inode_bitmap == 0
+                * then our last attempt to read the bitmap failed and we have
+                * just ended up caching that failure.  Try again to read it.
+                */
+               if (!inode_bitmap)
+                       retval = read_inode_bitmap (sb, block_group, 0);
+               
        } else {
                if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
                        sb->u.ext2_sb.s_loaded_inode_bitmaps++;
@@ -149,9 +154,9 @@ static int load_inode_bitmap (struct super_block * sb,
                        sb->u.ext2_sb.s_inode_bitmap[j] =
                                sb->u.ext2_sb.s_inode_bitmap[j - 1];
                }
-               read_inode_bitmap (sb, block_group, 0);
+               retval = read_inode_bitmap (sb, block_group, 0);
        }
-       return 0;
+       return retval;
 }
 
 /*
@@ -212,13 +217,15 @@ void ext2_free_inode (struct inode * inode)
            ino > le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (sb, "free_inode",
                            "reserved inode or nonexistent inode");
-               unlock_super (sb);
-               return;
+               goto error_return;
        }
        es = sb->u.ext2_sb.s_es;
        block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
        bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
        bitmap_nr = load_inode_bitmap (sb, block_group);
+       if (bitmap_nr < 0)
+               goto error_return;
+       
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
 
        is_directory = S_ISDIR(inode->i_mode);
@@ -233,12 +240,14 @@ void ext2_free_inode (struct inode * inode)
                ext2_warning (sb, "ext2_free_inode",
                              "bit already cleared for inode %lu", ino);
        else {
-               gdp = get_group_desc (sb, block_group, &bh2);
-               gdp->bg_free_inodes_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
-               if (is_directory)
-                       gdp->bg_used_dirs_count =
-                               cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+               gdp = ext2_get_group_desc (sb, block_group, &bh2);
+               if (gdp) {
+                       gdp->bg_free_inodes_count =
+                               cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+                       if (is_directory)
+                               gdp->bg_used_dirs_count =
+                                       cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+               }
                mark_buffer_dirty(bh2, 1);
                es->s_free_inodes_count =
                        cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
@@ -250,6 +259,7 @@ void ext2_free_inode (struct inode * inode)
                wait_on_buffer (bh);
        }
        sb->s_dirt = 1;
+error_return:
        unlock_super (sb);
 }
 
@@ -317,9 +327,10 @@ repeat:
 /* I am not yet convinced that this next bit is necessary.
                i = dir->u.ext2_i.i_block_group;
                for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
-                       tmp = get_group_desc (sb, i, &bh2);
-                       if ((le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
-                           le16_to_cpu(tmp->bg_free_inodes_count)) {
+                       tmp = ext2_get_group_desc (sb, i, &bh2);
+                       if (tmp &&
+                           (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
+                            le16_to_cpu(tmp->bg_free_inodes_count)) {
                                gdp = tmp;
                                break;
                        }
@@ -329,9 +340,10 @@ repeat:
 */
                if (!gdp) {
                        for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
-                               tmp = get_group_desc (sb, j, &bh2);
-                               if (le16_to_cpu(tmp->bg_free_inodes_count) &&
-                                       le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
+                               tmp = ext2_get_group_desc (sb, j, &bh2);
+                               if (tmp &&
+                                   le16_to_cpu(tmp->bg_free_inodes_count) &&
+                                   le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
                                        if (!gdp || 
                                            (le16_to_cpu(tmp->bg_free_blocks_count) >
                                             le16_to_cpu(gdp->bg_free_blocks_count))) {
@@ -348,8 +360,8 @@ repeat:
                 * Try to place the inode in its parent directory
                 */
                i = dir->u.ext2_i.i_block_group;
-               tmp = get_group_desc (sb, i, &bh2);
-               if (le16_to_cpu(tmp->bg_free_inodes_count))
+               tmp = ext2_get_group_desc (sb, i, &bh2);
+               if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
                        gdp = tmp;
                else
                {
@@ -361,8 +373,9 @@ repeat:
                                i += j;
                                if (i >= sb->u.ext2_sb.s_groups_count)
                                        i -= sb->u.ext2_sb.s_groups_count;
-                               tmp = get_group_desc (sb, i, &bh2);
-                               if (le16_to_cpu(tmp->bg_free_inodes_count)) {
+                               tmp = ext2_get_group_desc (sb, i, &bh2);
+                               if (tmp &&
+                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
                                        gdp = tmp;
                                        break;
                                }
@@ -376,8 +389,9 @@ repeat:
                        for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
                                if (++i >= sb->u.ext2_sb.s_groups_count)
                                        i = 0;
-                               tmp = get_group_desc (sb, i, &bh2);
-                               if (le16_to_cpu(tmp->bg_free_inodes_count)) {
+                               tmp = ext2_get_group_desc (sb, i, &bh2);
+                               if (tmp &&
+                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
                                        gdp = tmp;
                                        break;
                                }
@@ -391,6 +405,13 @@ repeat:
                return NULL;
        }
        bitmap_nr = load_inode_bitmap (sb, i);
+               if (bitmap_nr < 0) {
+               unlock_super (sb);
+               iput(inode);
+               *err = -EIO;
+               return NULL;
+       }
+
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
        if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
                                      EXT2_INODES_PER_GROUP(sb))) <
@@ -504,9 +525,14 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
        bitmap_count = 0;
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-               gdp = get_group_desc (sb, i, NULL);
+               gdp = ext2_get_group_desc (sb, i, NULL);
+               if (!gdp)
+                       continue;
                desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
                bitmap_nr = load_inode_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
                printk ("group %d: stored = %d, counted = %lu\n",
@@ -536,9 +562,14 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
        bitmap_count = 0;
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-               gdp = get_group_desc (sb, i, NULL);
+               gdp = ext2_get_group_desc (sb, i, NULL);
+               if (!gdp)
+                       continue;
                desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
                bitmap_nr = load_inode_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
                if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
index 8280d07365089292eb6acb9ae81b66a12988be39..a48723031b6eec365e99fe27828812c19ec8f059 100644 (file)
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ *  Goal-directed block allocation by Stephen Tweedie
+ *     (sct@dcs.ed.ac.uk), 1993, 1998
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ *     (jj@sunsite.ms.mff.cuni.cz)
  */
 
 #include <asm/uaccess.h>
@@ -417,9 +420,44 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
                                 int create, int *err)
 {
        struct buffer_head * bh;
-
+       int prev_blocks;
+       
+       prev_blocks = inode->i_blocks;
+       
        bh = ext2_getblk (inode, block, create, err);
-       if (!bh || buffer_uptodate(bh))
+       if (!bh)
+               return bh;
+       
+       /*
+        * If the inode has grown, and this is a directory, then perform
+        * preallocation of a few more blocks to try to keep directory
+        * fragmentation down.
+        */
+       if (create && 
+           S_ISDIR(inode->i_mode) && 
+           inode->i_blocks > prev_blocks &&
+           EXT2_HAS_COMPAT_FEATURE(inode->i_sb,
+                                   EXT2_FEATURE_COMPAT_DIR_PREALLOC)) {
+               int i;
+               struct buffer_head *tmp_bh;
+               
+               for (i = 1;
+                    i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
+                    i++) {
+                       /* 
+                        * ext2_getblk will zero out the contents of the
+                        * directory for us
+                        */
+                       tmp_bh = ext2_getblk(inode, block+i, create, err);
+                       if (!tmp_bh) {
+                               brelse (bh);
+                               return 0;
+                       }
+                       brelse (tmp_bh);
+               }
+       }
+       
+       if (buffer_uptodate(bh))
                return bh;
        ll_rw_block (READ, 1, &bh);
        wait_on_buffer (bh);
@@ -447,18 +485,23 @@ void ext2_read_inode (struct inode * inode)
            inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (inode->i_sb, "ext2_read_inode",
                            "bad inode number: %lu", inode->i_ino);
-               return;
+               goto bad_inode;
        }
        block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
-       if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
-               ext2_panic (inode->i_sb, "ext2_read_inode",
+       if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+               ext2_error (inode->i_sb, "ext2_read_inode",
                            "group >= groups count");
+               goto bad_inode;
+       }
        group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
        desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
        bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-       if (!bh)
-               ext2_panic (inode->i_sb, "ext2_read_inode",
+       if (!bh) {
+               ext2_error (inode->i_sb, "ext2_read_inode",
                            "Descriptor not loaded");
+               goto bad_inode;
+       }
+
        gdp = (struct ext2_group_desc *) bh->b_data;
        /*
         * Figure out the offset within the block group inode table
@@ -467,10 +510,12 @@ void ext2_read_inode (struct inode * inode)
                EXT2_INODE_SIZE(inode->i_sb);
        block = le32_to_cpu(gdp[desc].bg_inode_table) +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-               ext2_panic (inode->i_sb, "ext2_read_inode",
-                           "unable to read i-node block - "
+       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+               ext2_error (inode->i_sb, "ext2_read_inode",
+                           "unable to read inode block - "
                            "inode=%lu, block=%lu", inode->i_ino, block);
+               goto bad_inode;
+       }
        offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -493,7 +538,20 @@ void ext2_read_inode (struct inode * inode)
        inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
        inode->u.ext2_i.i_osync = 0;
        inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-       inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+       if (S_ISDIR(inode->i_mode))
+               inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+       else {
+               inode->u.ext2_i.i_dir_acl = 0;
+               inode->u.ext2_i.i_high_size =
+                       le32_to_cpu(raw_inode->i_size_high);
+#if BITS_PER_LONG < 64
+               if (raw_inode->i_size_high)
+                       inode->i_size = (__u32)-1;
+#else
+               inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high))
+                       << 32;
+#endif
+       }
        inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
        inode->u.ext2_i.i_block_group = block_group;
        inode->u.ext2_i.i_next_alloc_block = 0;
@@ -542,6 +600,11 @@ void ext2_read_inode (struct inode * inode)
                inode->i_attr_flags |= ATTR_FLAG_NOATIME;
                inode->i_flags |= MS_NOATIME;
        }
+       return;
+       
+bad_inode:
+       make_bad_inode(inode);
+       return;
 }
 
 static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -561,18 +624,22 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
            inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (inode->i_sb, "ext2_write_inode",
                            "bad inode number: %lu", inode->i_ino);
-               return 0;
+               return -EIO;
        }
        block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
-       if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
-               ext2_panic (inode->i_sb, "ext2_write_inode",
+       if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+               ext2_error (inode->i_sb, "ext2_write_inode",
                            "group >= groups count");
+               return -EIO;
+       }
        group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
        desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
        bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-       if (!bh)
-               ext2_panic (inode->i_sb, "ext2_write_inode",
+       if (!bh) {
+               ext2_error (inode->i_sb, "ext2_write_inode",
                            "Descriptor not loaded");
+               return -EIO;
+       }
        gdp = (struct ext2_group_desc *) bh->b_data;
        /*
         * Figure out the offset within the block group inode table
@@ -581,10 +648,12 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
                EXT2_INODE_SIZE(inode->i_sb);
        block = le32_to_cpu(gdp[desc].bg_inode_table) +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-               ext2_panic (inode->i_sb, "ext2_write_inode",
-                           "unable to read i-node block - "
+       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+               ext2_error (inode->i_sb, "ext2_write_inode",
+                           "unable to read inode block - "
                            "inode=%lu, block=%lu", inode->i_ino, block);
+               return -EIO;
+       }
        offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -603,7 +672,16 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
        raw_inode->i_frag = inode->u.ext2_i.i_frag_no;
        raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;
        raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
-       raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+       if (S_ISDIR(inode->i_mode))
+               raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+       else { 
+#if BITS_PER_LONG < 64
+               raw_inode->i_size_high =
+                       cpu_to_le32(inode->u.ext2_i.i_high_size);
+#else
+               raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
+#endif
+       }
        raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
                raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
@@ -620,7 +698,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
                        printk ("IO error syncing ext2 inode ["
                                "%s:%08lx]\n",
                                kdevname(inode->i_dev), inode->i_ino);
-                       err = -1;
+                       err = -EIO;
                }
        }
        brelse (bh);
index 4ba722b8540bd84925708aedbceefc1c3f98f777..70d4fc5634732b1bcf4e999c0f452cc29dce1a8a 100644 (file)
 int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned long arg)
 {
-       unsigned long flags;
+       unsigned int flags;
 
        ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
 
        switch (cmd) {
        case EXT2_IOC_GETFLAGS:
+               flags = inode->u.ext2_i.i_flags & EXT2_FL_USER_VISIBLE;
                return put_user(inode->u.ext2_i.i_flags, (int *) arg);
        case EXT2_IOC_SETFLAGS:
                if (get_user(flags, (int *) arg))
-                       return -EFAULT; 
+                       return -EFAULT;
+               flags = flags & EXT2_FL_USER_MODIFIABLE;
                /*
                 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
                 * the super user when the security level is zero.
@@ -44,7 +46,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                                return -EPERM;
                if (IS_RDONLY(inode))
                        return -EROFS;
-               inode->u.ext2_i.i_flags = flags;
+               inode->u.ext2_i.i_flags = (inode->u.ext2_i.i_flags &
+                                          ~EXT2_FL_USER_MODIFIABLE) | flags;
                if (flags & EXT2_SYNC_FL)
                        inode->i_flags |= MS_SYNCHRONOUS;
                else
index aeeb6553408a93d9628a862fc67ca0b2a5c7ad0c..d4ddd14102fd8fef949de071eccb4cd036f08870 100644 (file)
@@ -14,6 +14,8 @@
  *
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  Directory entry file type support and forward compatibility hooks
+ *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  */
 
 #include <asm/uaccess.h>
 /*
  * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
  */
-static int ext2_match (int len, const char * const name,
-                      struct ext2_dir_entry * de)
+static inline int ext2_match (int len, const char * const name,
+                      struct ext2_dir_entry_2 * de)
 {
        if (!de || !le32_to_cpu(de->inode) || len > EXT2_NAME_LEN)
                return 0;
-       /*
-        * "" means "." ---> so paths like "/usr/lib//libc.a" work
-        */
-       if (!len && le16_to_cpu(de->name_len) == 1 && (de->name[0] == '.') &&
-          (de->name[1] == '\0'))
-               return 1;
-       if (len != le16_to_cpu(de->name_len))
+       if (len != de->name_len)
                return 0;
        return !memcmp(name, de->name, len);
 }
@@ -65,7 +61,7 @@ static int ext2_match (int len, const char * const name,
  */
 static struct buffer_head * ext2_find_entry (struct inode * dir,
                                             const char * const name, int namelen,
-                                            struct ext2_dir_entry ** res_dir)
+                                            struct ext2_dir_entry_2 ** res_dir)
 {
        struct super_block * sb;
        struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -96,7 +92,7 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
 
        for (block = 0, offset = 0; offset < dir->i_size; block++) {
                struct buffer_head * bh;
-               struct ext2_dir_entry * de;
+               struct ext2_dir_entry_2 * de;
                char * dlimit;
 
                if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
@@ -105,9 +101,11 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
                }
                bh = bh_use[block % NAMEI_RA_SIZE];
                if (!bh) {
+#if 0
                        ext2_error (sb, "ext2_find_entry",
                                    "directory #%lu contains a hole at offset %lu",
                                    dir->i_ino, offset);
+#endif
                        offset += sb->s_blocksize;
                        continue;
                }
@@ -119,13 +117,13 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
                        break;
                }
 
-               de = (struct ext2_dir_entry *) bh->b_data;
+               de = (struct ext2_dir_entry_2 *) bh->b_data;
                dlimit = bh->b_data + sb->s_blocksize;
                while ((char *) de < dlimit) {
                        if (!ext2_check_dir_entry ("ext2_find_entry", dir,
                                                   de, bh, offset))
                                goto failure;
-                       if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
+                       if (ext2_match (namelen, name, de)) {
                                for (i = 0; i < NAMEI_RA_SIZE; ++i) {
                                        if (bh_use[i] != bh)
                                                brelse (bh_use[i]);
@@ -134,7 +132,7 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
                                return bh;
                        }
                        offset += le16_to_cpu(de->rec_len);
-                       de = (struct ext2_dir_entry *)
+                       de = (struct ext2_dir_entry_2 *)
                                ((char *) de + le16_to_cpu(de->rec_len));
                }
 
@@ -158,7 +156,7 @@ failure:
 int ext2_lookup(struct inode * dir, struct dentry *dentry)
 {
        struct inode * inode;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        struct buffer_head * bh;
 
        if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -190,13 +188,13 @@ int ext2_lookup(struct inode * dir, struct dentry *dentry)
  */
 static struct buffer_head * ext2_add_entry (struct inode * dir,
                                            const char * name, int namelen,
-                                           struct ext2_dir_entry ** res_dir,
+                                           struct ext2_dir_entry_2 ** res_dir,
                                            int *err)
 {
        unsigned long offset;
        unsigned short rec_len;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de, * de1;
+       struct ext2_dir_entry_2 * de, * de1;
        struct super_block * sb;
 
        *err = -EINVAL;
@@ -226,7 +224,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                return NULL;
        rec_len = EXT2_DIR_REC_LEN(namelen);
        offset = 0;
-       de = (struct ext2_dir_entry *) bh->b_data;
+       de = (struct ext2_dir_entry_2 *) bh->b_data;
        *err = -ENOSPC;
        while (1) {
                if ((char *)de >= sb->s_blocksize + bh->b_data) {
@@ -243,16 +241,17 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
 
                                ext2_debug ("creating next block\n");
 
-                               de = (struct ext2_dir_entry *) bh->b_data;
+                               de = (struct ext2_dir_entry_2 *) bh->b_data;
                                de->inode = le32_to_cpu(0);
                                de->rec_len = le16_to_cpu(sb->s_blocksize);
                                dir->i_size = offset + sb->s_blocksize;
+                               dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                                mark_inode_dirty(dir);
                        } else {
 
                                ext2_debug ("skipping to next block\n");
 
-                               de = (struct ext2_dir_entry *) bh->b_data;
+                               de = (struct ext2_dir_entry_2 *) bh->b_data;
                        }
                }
                if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
@@ -261,24 +260,25 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                        brelse (bh);
                        return NULL;
                }
-               if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
+               if (ext2_match (namelen, name, de)) {
                                *err = -EEXIST;
                                brelse (bh);
                                return NULL;
                }
                if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
-                   (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)) + rec_len)) {
+                   (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
                        offset += le16_to_cpu(de->rec_len);
                        if (le32_to_cpu(de->inode)) {
-                               de1 = (struct ext2_dir_entry *) ((char *) de +
-                                       EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+                               de1 = (struct ext2_dir_entry_2 *) ((char *) de +
+                                       EXT2_DIR_REC_LEN(de->name_len));
                                de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
-                                       EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
-                               de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+                                       EXT2_DIR_REC_LEN(de->name_len));
+                               de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
                                de = de1;
                        }
                        de->inode = cpu_to_le32(0);
-                       de->name_len = cpu_to_le16(namelen);
+                       de->name_len = namelen;
+                       de->file_type = 0;
                        memcpy (de->name, name, namelen);
                        /*
                         * XXX shouldn't update any times until successful
@@ -292,6 +292,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                         * and/or different from the directory change time.
                         */
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+                       dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                        mark_inode_dirty(dir);
                        dir->i_version = ++event;
                        mark_buffer_dirty(bh, 1);
@@ -300,7 +301,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                        return bh;
                }
                offset += le16_to_cpu(de->rec_len);
-               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+               de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        brelse (bh);
        return NULL;
@@ -310,15 +311,15 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
  * ext2_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
-static int ext2_delete_entry (struct ext2_dir_entry * dir,
+static int ext2_delete_entry (struct ext2_dir_entry_2 * dir,
                              struct buffer_head * bh)
 {
-       struct ext2_dir_entry * de, * pde;
+       struct ext2_dir_entry_2 * de, * pde;
        int i;
 
        i = 0;
        pde = NULL;
-       de = (struct ext2_dir_entry *) bh->b_data;
+       de = (struct ext2_dir_entry_2 *) bh->b_data;
        while (i < bh->b_size) {
                if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, 
                                           de, bh, i))
@@ -333,7 +334,7 @@ static int ext2_delete_entry (struct ext2_dir_entry * dir,
                }
                i += le16_to_cpu(de->rec_len);
                pde = de;
-               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+               de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        return -ENOENT;
 }
@@ -350,7 +351,7 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
 {
        struct inode * inode;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        int err = -EIO;
 
        /*
@@ -371,6 +372,9 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
                return err;
        }
        de->inode = cpu_to_le32(inode->i_ino);
+       if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               de->file_type = EXT2_FT_REG_FILE;
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -386,7 +390,7 @@ int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 {
        struct inode * inode;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        int err = -EIO;
 
        err = -ENAMETOOLONG;
@@ -400,29 +404,48 @@ int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        inode->i_uid = current->fsuid;
        inode->i_mode = mode;
        inode->i_op = NULL;
-       if (S_ISREG(inode->i_mode))
+       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!bh)
+               goto out_no_entry;
+       de->inode = cpu_to_le32(inode->i_ino);
+       dir->i_version = ++event;
+       if (S_ISREG(inode->i_mode)) {
                inode->i_op = &ext2_file_inode_operations;
-       else if (S_ISDIR(inode->i_mode)) {
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_REG_FILE;
+       } else if (S_ISDIR(inode->i_mode)) {
                inode->i_op = &ext2_dir_inode_operations;
                if (dir->i_mode & S_ISGID)
                        inode->i_mode |= S_ISGID;
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_DIR;
        }
-       else if (S_ISLNK(inode->i_mode))
+       else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &ext2_symlink_inode_operations;
-       else if (S_ISCHR(inode->i_mode))
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_SYMLINK;
+       } else if (S_ISCHR(inode->i_mode)) {
                inode->i_op = &chrdev_inode_operations;
-       else if (S_ISBLK(inode->i_mode))
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_CHRDEV;
+       } else if (S_ISBLK(inode->i_mode)) {
                inode->i_op = &blkdev_inode_operations;
-       else if (S_ISFIFO(inode->i_mode)) 
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_BLKDEV;
+       } else if (S_ISFIFO(inode->i_mode))  {
                init_fifo(inode);
+               if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                             EXT2_FEATURE_INCOMPAT_FILETYPE))
+                       de->file_type = EXT2_FT_FIFO;
+       }
        if (S_ISBLK(mode) || S_ISCHR(mode))
                inode->i_rdev = to_kdev_t(rdev);
        mark_inode_dirty(inode);
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh)
-               goto out_no_entry;
-       de->inode = cpu_to_le32(inode->i_ino);
-       dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -445,7 +468,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
        struct inode * inode;
        struct buffer_head * bh, * dir_block;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        int err;
 
        err = -ENAMETOOLONG;
@@ -463,6 +486,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 
        inode->i_op = &ext2_dir_inode_operations;
        inode->i_size = inode->i_sb->s_blocksize;
+       inode->i_blocks = 0;    
        dir_block = ext2_bread (inode, 0, 1, &err);
        if (!dir_block) {
                inode->i_nlink--; /* is this nlink == 0? */
@@ -470,17 +494,22 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                iput (inode);
                return err;
        }
-       inode->i_blocks = inode->i_sb->s_blocksize / 512;
-       de = (struct ext2_dir_entry *) dir_block->b_data;
+       de = (struct ext2_dir_entry_2 *) dir_block->b_data;
        de->inode = cpu_to_le32(inode->i_ino);
-       de->name_len = cpu_to_le16(1);
-       de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+       de->name_len = 1;
+       de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
        strcpy (de->name, ".");
-       de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+       if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               de->file_type = EXT2_FT_DIR;
+       de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        de->inode = cpu_to_le32(dir->i_ino);
        de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
-       de->name_len = cpu_to_le16(2);
+       de->name_len = 2;
        strcpy (de->name, "..");
+       if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               de->file_type = EXT2_FT_DIR;
        inode->i_nlink = 2;
        mark_buffer_dirty(dir_block, 1);
        brelse (dir_block);
@@ -492,6 +521,9 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        if (!bh)
                goto out_no_entry;
        de->inode = cpu_to_le32(inode->i_ino);
+       if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               de->file_type = EXT2_FT_DIR;
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -499,6 +531,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                wait_on_buffer (bh);
        }
        dir->i_nlink++;
+       dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
        d_instantiate(dentry, inode);
        brelse (bh);
@@ -520,7 +553,7 @@ static int empty_dir (struct inode * inode)
 {
        unsigned long offset;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de, * de1;
+       struct ext2_dir_entry_2 * de, * de1;
        struct super_block * sb;
        int err;
 
@@ -532,8 +565,8 @@ static int empty_dir (struct inode * inode)
                              inode->i_ino);
                return 1;
        }
-       de = (struct ext2_dir_entry *) bh->b_data;
-       de1 = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+       de = (struct ext2_dir_entry_2 *) bh->b_data;
+       de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || 
            strcmp (".", de->name) || strcmp ("..", de1->name)) {
                ext2_warning (inode->i_sb, "empty_dir",
@@ -542,19 +575,21 @@ static int empty_dir (struct inode * inode)
                return 1;
        }
        offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
-       de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len));
+       de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));
        while (offset < inode->i_size ) {
                if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
                        brelse (bh);
                        bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err);
                        if (!bh) {
+#if 0
                                ext2_error (sb, "empty_dir",
                                            "directory #%lu contains a hole at offset %lu",
                                            inode->i_ino, offset);
+#endif
                                offset += sb->s_blocksize;
                                continue;
                        }
-                       de = (struct ext2_dir_entry *) bh->b_data;
+                       de = (struct ext2_dir_entry_2 *) bh->b_data;
                }
                if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
                                           offset)) {
@@ -566,7 +601,7 @@ static int empty_dir (struct inode * inode)
                        return 0;
                }
                offset += le16_to_cpu(de->rec_len);
-               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+               de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        brelse (bh);
        return 1;
@@ -577,7 +612,7 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        int retval;
        struct inode * inode;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
 
        retval = -ENAMETOOLONG;
        if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -652,6 +687,7 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        mark_inode_dirty(inode);
        dir->i_nlink--;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
        d_delete(dentry);
 
@@ -666,7 +702,7 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
        int retval;
        struct inode * inode;
        struct buffer_head * bh;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
 
        retval = -ENAMETOOLONG;
        if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -711,6 +747,7 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
                wait_on_buffer (bh);
        }
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
        inode->i_nlink--;
        mark_inode_dirty(inode);
@@ -726,7 +763,7 @@ out:
 
 int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
 {
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        struct inode * inode;
        struct buffer_head * bh = NULL, * name_block = NULL;
        char * link;
@@ -774,6 +811,9 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
        if (!bh)
                goto out_no_entry;
        de->inode = cpu_to_le32(inode->i_ino);
+       if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               de->file_type = EXT2_FT_SYMLINK;
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -797,7 +837,7 @@ int ext2_link (struct dentry * old_dentry,
                struct inode * dir, struct dentry *dentry)
 {
        struct inode *inode = old_dentry->d_inode;
-       struct ext2_dir_entry * de;
+       struct ext2_dir_entry_2 * de;
        struct buffer_head * bh;
        int err;
 
@@ -815,6 +855,21 @@ int ext2_link (struct dentry * old_dentry,
                return err;
 
        de->inode = cpu_to_le32(inode->i_ino);
+       if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+               if (S_ISREG(inode->i_mode))
+                       de->file_type = EXT2_FT_REG_FILE;
+               else if (S_ISDIR(inode->i_mode))
+                       de->file_type = EXT2_FT_DIR;
+               else if (S_ISLNK(inode->i_mode))
+                       de->file_type = EXT2_FT_SYMLINK;
+               else if (S_ISCHR(inode->i_mode))
+                       de->file_type = EXT2_FT_CHRDEV;
+               else if (S_ISBLK(inode->i_mode))
+                       de->file_type = EXT2_FT_BLKDEV;
+               else if (S_ISFIFO(inode->i_mode))  
+                       de->file_type = EXT2_FT_FIFO;
+       }
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -831,8 +886,8 @@ int ext2_link (struct dentry * old_dentry,
 }
 
 #define PARENT_INO(buffer) \
-       ((struct ext2_dir_entry *) ((char *) buffer + \
-       le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
+       ((struct ext2_dir_entry_2 *) ((char *) buffer + \
+       le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode
 
 /*
  * rename uses retrying to avoid race-conditions: at least they should be
@@ -850,7 +905,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
 {
        struct inode * old_inode, * new_inode;
        struct buffer_head * old_bh, * new_bh, * dir_bh;
-       struct ext2_dir_entry * old_de, * new_de;
+       struct ext2_dir_entry_2 * old_de, * new_de;
        int retval;
 
        old_bh = new_bh = dir_bh = NULL;
@@ -942,6 +997,10 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
         * ok, that's it
         */
        new_de->inode = le32_to_cpu(old_inode->i_ino);
+       if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
+                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+               new_de->file_type = old_de->file_type;
+       
        ext2_delete_entry (old_de, old_bh);
 
        old_dir->i_version = ++event;
@@ -951,6 +1010,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
                mark_inode_dirty(new_inode);
        }
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+       old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(old_dir);
        if (dir_bh) {
                PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
@@ -962,6 +1022,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
                        mark_inode_dirty(new_inode);
                } else {
                        new_dir->i_nlink++;
+                       new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                        mark_inode_dirty(new_dir);
                }
        }
index 1adc8218567acf43534f6503a76c6373007249c6..fa84e498fe3e368df1f0c71462c334732269a543 100644 (file)
@@ -107,12 +107,10 @@ void ext2_put_super (struct super_block * sb)
        int db_count;
        int i;
 
-       lock_super (sb);
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        }
-       sb->s_dev = 0;
        db_count = sb->u.ext2_sb.s_db_per_group;
        for (i = 0; i < db_count; i++)
                if (sb->u.ext2_sb.s_group_desc[i])
@@ -126,7 +124,7 @@ void ext2_put_super (struct super_block * sb)
                if (sb->u.ext2_sb.s_block_bitmap[i])
                        brelse (sb->u.ext2_sb.s_block_bitmap[i]);
        brelse (sb->u.ext2_sb.s_sbh);
-       unlock_super (sb);
+
        MOD_DEC_USE_COUNT;
        return;
 }
@@ -516,11 +514,11 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                        goto failed_mount;
                }
        }
-       sb->u.ext2_sb.s_feature_compat = es->s_feature_compat;
-       sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat;
-       sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat;
+       sb->u.ext2_sb.s_feature_compat = le32_to_cpu(es->s_feature_compat);
+       sb->u.ext2_sb.s_feature_incompat = le32_to_cpu(es->s_feature_incompat);
+       sb->u.ext2_sb.s_feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
        sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
-                                  (__s32) le32_to_cpu(es->s_log_frag_size);
+                                  le32_to_cpu(es->s_log_frag_size);
        if (sb->u.ext2_sb.s_frag_size)
                sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
                                                  sb->u.ext2_sb.s_frag_size;
index 184a4d19b71f4f96798a1b4afc6b4c06cbec004e..25194e9a399b4e8a2d4624c48517e09f7b1acfcf 100644 (file)
@@ -72,7 +72,6 @@ void fat_delete_inode(struct inode *inode)
 
 void fat_put_super(struct super_block *sb)
 {
-       lock_super(sb);
        if (MSDOS_SB(sb)->cvf_format) {
                dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
                MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
@@ -99,8 +98,7 @@ void fat_put_super(struct super_block *sb)
                kfree(MSDOS_SB(sb)->options.iocharset);
                MSDOS_SB(sb)->options.iocharset = NULL;
        }
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        MOD_DEC_USE_COUNT;
        return;
 }
index 602a077ebecd554138a02ce2dd4e6db7d5314952..7aec9d62db35b10de5a126cf64753c5a92802217 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/auto_fs.h>
 #include <linux/ntfs_fs.h>
 #include <linux/hfs_fs.h>
+#include <linux/devpts_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -139,6 +140,10 @@ __initfunc(static void do_sys_setup(void))
        init_adfs_fs();
 #endif
 
+#ifdef CONFIG_DEVPTS_FS
+       init_devpts_fs();
+#endif
+
 #ifdef CONFIG_NLS
        init_nls();
 #endif
index 9e278d383b947a1c4d90e1169e246d866c45c5d9..81a1c256273862b01844daa06347db04429325a7 100644 (file)
@@ -122,8 +122,6 @@ static void hfs_put_super(struct super_block *sb)
 {
        struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
  
-       lock_super(sb);
-
        if (!(sb->s_flags & MS_RDONLY)) {
                hfs_mdb_commit(mdb, 0);
                sb->s_dirt = 0;
@@ -135,12 +133,8 @@ static void hfs_put_super(struct super_block *sb)
        /* restore default blocksize for the device */
        set_blocksize(sb->s_dev, BLOCK_SIZE);
 
-       /* invalidate the superblock */
-       sb->s_dev = 0;
-
        MOD_DEC_USE_COUNT;
 
-       unlock_super(sb);
        return;
 }
 
index 667492fcdcfe09be3a42ede0b0deaff6fdc65c8c..5cc01646b8f269c3b30da5d75ab20e1376ac732a 100644 (file)
@@ -731,9 +731,6 @@ static void hpfs_read_inode(struct inode *inode)
 
 static void hpfs_put_super(struct super_block *s)
 {
-       lock_super(s);
-       s->s_dev = 0;
-       unlock_super(s);
        MOD_DEC_USE_COUNT;
 }
 
index 5e2802365dd614fbf2cc5f0c2fe9203a261b7771..03900d80a7a2eeb6a7770b085c043a3a2b4fcb8e 100644 (file)
@@ -49,14 +49,12 @@ void isofs_put_super(struct super_block *sb)
                sb->u.isofs_sb.s_nls_iocharset = NULL;
        }
 #endif
-       lock_super(sb);
 
 #ifdef LEAK_CHECK
        printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
               check_malloc, check_bread);
 #endif
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        MOD_DEC_USE_COUNT;
        return;
 }
index 05bf6706d8a0be79eb378f168cd968a6135b1e94..8934dc01269ea513a443caa906e0ce6d368641b1 100644 (file)
@@ -59,7 +59,6 @@ void minix_put_super(struct super_block *sb)
 {
        int i;
 
-       lock_super(sb);
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
                mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
@@ -70,8 +69,7 @@ void minix_put_super(struct super_block *sb)
                brelse(sb->u.minix_sb.s_zmap[i]);
        brelse (sb->u.minix_sb.s_sbh);
        kfree(sb->u.minix_sb.s_imap);
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        MOD_DEC_USE_COUNT;
        return;
 }
index c872c2b84dc9f7a050d2cd9213be507a3d3e120e..99488fca14505870ba35fd9a8e368b4eb1c75f89 100644 (file)
@@ -407,8 +407,6 @@ static void ncp_put_super(struct super_block *sb)
 {
        struct ncp_server *server = NCP_SBP(sb);
 
-       lock_super(sb);
-
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
@@ -424,9 +422,6 @@ static void ncp_put_super(struct super_block *sb)
 
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
 
-       sb->s_dev = 0;
-       unlock_super(sb);
-
        MOD_DEC_USE_COUNT;
 }
 
index 2de790e42fcc489080e73b981722efd72b5365b4..d56e4e7e61c843c7c64acc8156ff6148ce49a105 100644 (file)
@@ -126,10 +126,6 @@ nfs_put_super(struct super_block *sb)
        struct nfs_server *server = &sb->u.nfs_sb.s_server;
        struct rpc_clnt *rpc;
 
-       /*
-        * Lock the super block while we bring down the daemons.
-        */
-       lock_super(sb);
        if ((rpc = server->client) != NULL)
                rpc_shutdown_client(rpc);
 
@@ -142,8 +138,7 @@ nfs_put_super(struct super_block *sb)
        nfs_invalidate_dircache_sb(sb);
 
        kfree(server->hostname);
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        MOD_DEC_USE_COUNT;
 }
 
index d190b21e4a7c80bbb09558c7c031d480127a1680..8a8fc563f40655272dab15a9adc573fd0919fb13 100644 (file)
@@ -693,12 +693,9 @@ static void ntfs_put_super(struct super_block *sb)
        ntfs_volume *vol;
 
        ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
-       /* Ensure that nobody uses the super block anymore */
-       lock_super(sb);
+
        vol=NTFS_SB2VOL(sb);
-       /* Tell the kernel that the super block is no more used */
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        ntfs_release_volume(vol);
        if(vol->nls_map)
                unload_nls(vol->nls_map);
index 53ac522cb93552c5acb54af28e452227a7eeb7a9..ad4fa992ac299314499160ff282d2ae3f4b842a0 100644 (file)
@@ -80,20 +80,13 @@ static void proc_delete_inode(struct inode *inode)
        }
 }
 
-static void proc_put_super(struct super_block *sb)
-{
-       lock_super(sb);
-       sb->s_dev = 0;
-       unlock_super(sb);
-}
-
 static struct super_operations proc_sops = { 
        proc_read_inode,
        proc_write_inode,
        proc_put_inode,
        proc_delete_inode,      /* delete_inode(struct inode *) */
        NULL,
-       proc_put_super,
+       NULL,
        NULL,
        proc_statfs,
        NULL
@@ -198,9 +191,9 @@ int proc_permission(struct inode *inode, int mask)
        read_lock(&tasklist_lock);
        p = find_task_by_pid(pid);
 
-       if (p != NULL)
+       if (p && p->fs)
                de = p->fs->root;
-       read_unlock(&tasklist_lock);
+       read_unlock(&tasklist_lock);    /* FIXME! */
 
        if (p == NULL)
                return -EACCES;         /* ENOENT? */
index 5ee0fd30a36c3d38ea2a07695fdf0ebe5c0e7600..28bb81a937bca5ae88d073319e6f23d8513f5359 100644 (file)
 static int proc_readlink(struct dentry *, char *, int);
 static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
 
-/*
- * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
- * when the files[] array was updated only after the open code
- */
-#undef PLAN9_SEMANTICS
-
 /*
  * links can't do much...
  */
index bc3a116b497bafdc23e4db920c5c4d0fa4a5030a..0e17b3e1d58927c2e1592561453d102490edece5 100644 (file)
@@ -157,9 +157,6 @@ outnobh:
 static void
 romfs_put_super(struct super_block *sb)
 {
-       lock_super(sb);
-       sb->s_dev = 0;
-       unlock_super(sb);
        MOD_DEC_USE_COUNT;
        return;
 }
index 0264ceeb2a35552e2d5e8ca2fff57e5705949fdb..e850b7f82b4f0955adbafca1f7187497b3ecc71b 100644 (file)
@@ -322,8 +322,6 @@ smb_put_super(struct super_block *sb)
 {
        struct smb_sb_info *server = &(sb->u.smbfs_sb);
 
-       lock_super(sb);
-
        if (server->sock_file) {
                smb_proc_disconnect(server);
                smb_dont_catch_keepalive(server);
@@ -337,9 +335,6 @@ smb_put_super(struct super_block *sb)
        kfree(sb->u.smbfs_sb.temp_buf);
        if (server->packet)
                smb_vfree(server->packet);
-       sb->s_dev = 0;
-
-       unlock_super(sb);
 
        MOD_DEC_USE_COUNT;
 }
index 50a6cb9a6270d5e541a1f533f61c25f077e7213e..0433dd251d2d1692cba8e18340a63b644d2cf9f9 100644 (file)
@@ -668,18 +668,26 @@ static int do_umount(kdev_t dev, int unmount_root)
        if (retval)
                goto out;
 
-       /* Forget any inodes */
-       if (invalidate_inodes(sb)) {
-               printk("VFS: Busy inodes after unmount. "
-                       "Self-destruct in 5 seconds. Bye-bye..\n");
-       }
-
        if (sb->s_op) {
                if (sb->s_op->write_super && sb->s_dirt)
                        sb->s_op->write_super(sb);
+       }
+
+       lock_super(sb);
+       if (sb->s_op) {
                if (sb->s_op->put_super)
                        sb->s_op->put_super(sb);
        }
+
+       /* Forget any remaining inodes */
+       if (invalidate_inodes(sb)) {
+               printk("VFS: Busy inodes after unmount. "
+                       "Self-destruct in 5 seconds.  Have a nice day...\n");
+       }
+
+       sb->s_dev = 0;          /* Free the superblock */
+       unlock_super(sb);
+
        remove_vfsmnt(dev);
 out:
        return retval;
index 25dbe55df6428fe7998ce75ba31ff12ad81ffd05..ae7851a10e48ca84d321396815cd3213524c2a63 100644 (file)
@@ -492,12 +492,14 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
        sb->s_op = &sysv_sops;
        root_inode = iget(sb,SYSV_ROOT_INO);
        sb->s_root = d_alloc_root(root_inode, NULL);
-       unlock_super(sb);
        if (!sb->s_root) {
                printk("SysV FS: get root inode failed\n");
                sysv_put_super(sb);
+               sb->sb_dev = 0;
+               unlock_super(sb);
                return NULL;
        }
+       unlock_super(sb);
        sb->s_dirt = 1;
        /* brelse(bh);  resp.  brelse(bh1); brelse(bh2);
           occurs when the disk is unmounted. */
@@ -530,15 +532,14 @@ void sysv_write_super (struct super_block *sb)
 
 void sysv_put_super(struct super_block *sb)
 {
-       /* we can assume sysv_write_super() has already been called */
-       lock_super(sb);
+       /* we can assume sysv_write_super() has already been called, and
+          and that the superblock is locked */
        brelse(sb->sv_bh1);
        if (sb->sv_bh1 != sb->sv_bh2) brelse(sb->sv_bh2);
        /* switch back to default block size */
        if (sb->s_blocksize != BLOCK_SIZE)
                set_blocksize(sb->s_dev,BLOCK_SIZE);
-       sb->s_dev = 0;
-       unlock_super(sb);
+
        MOD_DEC_USE_COUNT;
 }
 
index 6a378fb138412d8870935ef4baabe1089ac27959..7fdac8dd62689765dcf449cbcc4c1c85169d731a 100644 (file)
@@ -335,15 +335,13 @@ void ufs_put_super (struct super_block * sb)
                printk("ufs_put_super\n"); /* XXX */
         }
 
-       lock_super (sb);
+
        /* XXX - sync fs data, set state to ok, and flush buffers */
        set_blocksize (sb->s_dev, BLOCK_SIZE);
-       sb->s_dev = 0;
 
        /* XXX - free allocated kernel memory */
        /* includes freeing usb page */
 
-       unlock_super (sb);
        MOD_DEC_USE_COUNT;
 
        return;
index 6fb2e2541d228cba6d610b3a8e89439fa2c11978..e73d3b1c18099c48e0dc506999ed3c4c0d5735c3 100644 (file)
@@ -155,7 +155,6 @@ struct mpc_config_intlocal
 extern int smp_found_config;
 extern int smp_scan_config(unsigned long, unsigned long);
 extern unsigned long smp_alloc_memory(unsigned long mem_base);
-extern unsigned char *apic_reg;
 extern unsigned char boot_cpu_id;
 extern unsigned long cpu_present_map;
 extern volatile int cpu_number_map[NR_CPUS];
@@ -192,24 +191,25 @@ extern volatile int smp_process_available;
  *     APIC handlers: Note according to the Intel specification update
  *     you should put reads between APIC writes.
  *     Intel Pentium processor specification update [11AP, pg 64]
- *             "Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
+ *     "Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
  */
 
+#define APIC_BASE ((char *)0xFEE00000)
+
 extern __inline void apic_write(unsigned long reg, unsigned long v)
 {
-       *((volatile unsigned long *)(apic_reg+reg))=v;
+       *((volatile unsigned long *)(APIC_BASE+reg))=v;
 }
 
 extern __inline unsigned long apic_read(unsigned long reg)
 {
-       return *((volatile unsigned long *)(apic_reg+reg));
+       return *((volatile unsigned long *)(APIC_BASE+reg));
 }
 
 /*
- *     This function is needed by all SMP systems. It must _always_ be valid from the initial
- *     startup. This may require magic on some systems (in the i86 case we dig out the boot 
- *     cpu id from the config and set up a fake apic_reg pointer so that before we activate
- *     the apic we get the right answer). Hopefully other processors are more sensible 8)
+ * This function is needed by all SMP systems. It must _always_ be valid
+ * from the initial startup. We map APIC_BASE very early in page_setup(),
+ * so this is correct in the x86 case.
  */
 
 #define smp_processor_id() (current->processor)
@@ -217,7 +217,7 @@ extern __inline unsigned long apic_read(unsigned long reg)
 extern __inline int hard_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
-       return GET_APIC_ID(*(unsigned long *)(apic_reg+APIC_ID));
+       return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
 
 #endif /* !ASSEMBLY */
index 5370dbb6a7866010967284fb6f0517726635e03f..df02f7809d2e3999641d316e2b7380c75faf2e15 100644 (file)
@@ -442,7 +442,7 @@ __asm__("cld\n\t" \
                case 0: COMMON(""); return to;
                case 1: COMMON("\n\tmovsb"); return to;
                case 2: COMMON("\n\tmovsw"); return to;
-               case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
+               default: COMMON("\n\tmovsw\n\tmovsb"); return to;
        }
 #undef COMMON
 }
@@ -593,7 +593,7 @@ __asm__("cld\n\t" \
                case 0: COMMON(""); return s;
                case 1: COMMON("\n\tstosb"); return s;
                case 2: COMMON("\n\tstosw"); return s;
-               case 3: COMMON("\n\tstosw\n\tstosb"); return s;
+               default: COMMON("\n\tstosw\n\tstosb"); return s;
        }
 #undef COMMON
 }
index 7944a53fe40c28bfad7c8ea1cc9d75c579ea4a8b..2f2c14b7c78177ec377e989a1f95dde1871ce15e 100644 (file)
@@ -1,61 +1,34 @@
 /*
- * BIOS32, PCI BIOS functions and defines
- * Copyright 1994, Drew Eckhardt
- * 
- * For more information, please consult 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * P.O. Box 14070
- * Portland, OR 97214
- * U. S. A.
- * Phone: 800-433-5177 / +1-503-797-4207
- * Fax: +1-503-234-6762 
- * 
- * Manuals are $25 each or $50 for all three, plus $7 shipping 
- * within the United States, $35 abroad.
+ *     This is only a stub file to make drivers not yet converted to the new
+ *     PCI probing mechanism work. [mj]
  */
 
 #ifndef BIOS32_H
 #define BIOS32_H
 
-/*
- * Error values that may be returned by the PCI bios.  Use
- * pcibios_strerror() to convert to a printable string.
- */
-#define PCIBIOS_SUCCESSFUL             0x00
-#define PCIBIOS_FUNC_NOT_SUPPORTED     0x81
-#define PCIBIOS_BAD_VENDOR_ID          0x83
-#define PCIBIOS_DEVICE_NOT_FOUND       0x86
-#define PCIBIOS_BAD_REGISTER_NUMBER    0x87
-#define PCIBIOS_SET_FAILED             0x88
-#define PCIBIOS_BUFFER_TOO_SMALL       0x89
+#include <linux/pci.h>
+
+#warning This driver uses the old PCI interface, please fix it (see Documentation/pci.txt)
+
+extern inline int __pcibios_read_irq(unsigned char bus, unsigned char dev_fn, unsigned char *to)
+{
+       struct pci_dev *pdev = pci_find_slot(bus, dev_fn);
+       if (!pdev) {
+               *to = 0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       } else {
+               *to = pdev->irq;
+               return PCIBIOS_SUCCESSFUL;
+       }
+}
+
+extern inline int __pcibios_read_config_byte(unsigned char bus,
+       unsigned char dev_fn, unsigned char where, unsigned char *to)
+{
+       return pcibios_read_config_byte(bus, dev_fn, where, to);
+}
 
-extern int pcibios_present (void);
-extern unsigned long pcibios_init (unsigned long memory_start,
-                                  unsigned long memory_end);
-extern unsigned long pcibios_fixup (unsigned long memory_start,
-                                   unsigned long memory_end);
-extern int pcibios_find_class (unsigned int class_code, unsigned short index, 
-                              unsigned char *bus, unsigned char *dev_fn);
-extern int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
-                               unsigned short index, unsigned char *bus,
-                               unsigned char *dev_fn);
-extern int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
-                                    unsigned char where, unsigned char *val);
-extern int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
-                                    unsigned char where, unsigned short *val);
-extern int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
-                                     unsigned char where, unsigned int *val);
-extern int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
-                                     unsigned char where, unsigned char val);
-extern int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
-                                     unsigned char where, unsigned short val);
-extern int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
-                                      unsigned char where, unsigned int val);
-extern const char *pcibios_strerror (int error);
+#define pcibios_read_config_byte(b,d,w,p) \
+       (((w) == PCI_INTERRUPT_LINE) ? __pcibios_read_irq(b,d,p) : __pcibios_read_config_byte(b,d,w,p))
 
-#endif /* BIOS32_H */
+#endif
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
new file mode 100644 (file)
index 0000000..9f07c96
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/include/linux/devpts_fs.h
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * Prototypes for the pty driver <-> devpts filesystem interface.  Most
+ * of this is really just a hack so we can exclude it or build it as a
+ * module, and probably should go away eventually.
+ */
+
+#ifndef _LINUX_DEVPTS_FS_H
+#define _LINUX_DEVPTS_FS_H 1
+
+#include <linux/config.h>
+#include <linux/kdev_t.h>
+
+#ifdef CONFIG_DEVPTS_FS
+
+void devpts_pty_new(int, kdev_t);
+void devpts_pty_kill(int);
+
+#elif defined(CONFIG_DEVPTS_FS_MODULE)
+
+#ifdef BUILDING_PTY_C
+void (*devpts_upcall_new)(int,kdev_t) = NULL;
+void (*devpts_upcall_kill)(int)       = NULL;
+
+EXPORT_SYMBOL(devpts_upcall_new);
+EXPORT_SYMBOL(devpts_upcall_kill);
+#else
+extern void (*devpts_upcall_new)(int,kdev_t);
+extern void (*devpts_upcall_kill)(int);
+#endif
+
+#ifndef BUILDING_DEVPTS
+extern inline void
+devpts_pty_new(int line, kdev_t device)
+{
+       if ( devpts_upcall_new )
+               return devpts_upcall_new(line,device);
+}
+
+extern inline void
+devpts_pty_kill(int line)
+{
+       if ( devpts_upcall_kill )
+               return devpts_upcall_kill(line);
+}
+#endif
+
+#else  /* No /dev/pts filesystem at all */
+
+extern inline void
+devpts_pty_new(int line, kdev_t device) { }
+
+extern inline void
+devpts_pty_kill(int line) { }
+
+#endif
+
+#endif /* _LINUX_DEVPTS_FS_H */
index 49cdbe2f5ffe33ad2e6d4df591aa4aa2cea379b8..6d4205c9764f79553b24d8d9de0006380255b207 100644 (file)
@@ -31,6 +31,7 @@
  * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
  */
 #define EXT2_PREALLOCATE
+#define EXT2_DEFAULT_PREALLOC_BLOCKS   8
 
 /*
  * The second extended file system version
@@ -190,8 +191,18 @@ struct ext2_group_desc
 #define EXT2_APPEND_FL                 0x00000020 /* writes to file may only append */
 #define EXT2_NODUMP_FL                 0x00000040 /* do not dump file */
 #define EXT2_NOATIME_FL                        0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL                  0x00000100
+#define EXT2_COMPRBLK_FL               0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL                 0x00000400 /* Don't compress */
+#define EXT2_ECOMPR_FL                 0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */     
+#define EXT2_BTREE_FL                  0x00001000 /* btree format dir */
 #define EXT2_RESERVED_FL               0x80000000 /* reserved for ext2 lib */
-       
+
+#define EXT2_FL_USER_VISIBLE           0x00001FFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE                0x000000FF /* User modifiable flags */
+
 /*
  * ioctl commands
  */
@@ -255,6 +266,8 @@ struct ext2_inode {
        } osd2;                         /* OS dependent 2 */
 };
 
+#define i_size_high    i_dir_acl
+
 #if defined(__KERNEL__) || defined(__linux__)
 #define i_reserved1    osd1.linux1.l_i_reserved1
 #define i_frag         osd2.linux2.l_i_frag
@@ -367,9 +380,26 @@ struct ext2_super_block {
        __u8    s_uuid[16];             /* 128-bit uuid for volume */
        char    s_volume_name[16];      /* volume name */
        char    s_last_mounted[64];     /* directory where last mounted */
-       __u32   s_reserved[206];        /* Padding to the end of the block */
+       __u32   s_algorithm_usage_bitmap; /* For compression */
+       /*
+        * Performance hints.  Directory preallocation should only
+        * happen if the EXT2_COMPAT_PREALLOC flag is on.
+        */
+       __u8    s_prealloc_blocks;      /* Nr of blocks to try to preallocate*/
+       __u8    s_prealloc_dir_blocks;  /* Nr to preallocate for dirs */
+       __u16   s_padding1;
+       __u32   s_reserved[204];        /* Padding to the end of the block */
 };
 
+#ifdef __KERNEL__
+#define EXT2_SB(sb)    (&((sb)->u.ext2_sb))
+#else
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block.  This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb)    (sb)
+#endif
+
 /*
  * Codes for operating systems
  */
@@ -394,11 +424,27 @@ struct ext2_super_block {
  * Feature set definitions
  */
 
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask)                       \
+       ( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)                    \
+       ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)                     \
+       ( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC       0x0001
+
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE      0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR       0x0004
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION      0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE         0x0002
 
 #define EXT2_FEATURE_COMPAT_SUPP       0
-#define EXT2_FEATURE_INCOMPAT_SUPP     0
-#define EXT2_FEATURE_RO_COMPAT_SUPP    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+#define EXT2_FEATURE_INCOMPAT_SUPP     EXT2_FEATURE_INCOMPAT_FILETYPE
+#define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+                                        EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+                                        EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
 
 /*
  * Default values for user and/or group using reserved blocks
@@ -418,6 +464,35 @@ struct ext2_dir_entry {
        char    name[EXT2_NAME_LEN];    /* File name */
 };
 
+/*
+ * The new version of the directory entry.  Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+       __u32   inode;                  /* Inode number */
+       __u16   rec_len;                /* Directory entry length */
+       __u8    name_len;               /* Name length */
+       __u8    file_type;
+       char    name[EXT2_NAME_LEN];    /* File name */
+};
+
+/*
+ * Ext2 directory file types.  Only the low 3 bits are used.  The
+ * other bits are reserved for now.
+ */
+#define EXT2_FT_UNKNOWN                0
+#define EXT2_FT_REG_FILE       1
+#define EXT2_FT_DIR            2
+#define EXT2_FT_CHRDEV         3
+#define EXT2_FT_BLKDEV                 4
+#define EXT2_FT_FIFO           5
+#define EXT2_FT_SOCK           6
+#define EXT2_FT_SYMLINK                7
+
+#define EXT2_FT_MAX            8
+
 /*
  * EXT2_DIR_PAD defines the directory entries boundaries
  *
@@ -451,13 +526,16 @@ extern void ext2_free_blocks (const struct inode *, unsigned long,
                              unsigned long);
 extern unsigned long ext2_count_free_blocks (struct super_block *);
 extern void ext2_check_blocks_bitmap (struct super_block *);
+extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+                                                   unsigned int block_group,
+                                                   struct buffer_head ** bh);
 
 /* bitmap.c */
 extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
 
 /* dir.c */
 extern int ext2_check_dir_entry (const char *, struct inode *,
-                                struct ext2_dir_entry *, struct buffer_head *,
+                                struct ext2_dir_entry_2 *, struct buffer_head *,
                                 unsigned long);
 
 /* file.c */
index 7df902135323d84664d6298623449fd641a5073c..8f01f8ad9ed6c8d75e7d44f36c7d65b9a03343af 100644 (file)
@@ -35,6 +35,7 @@ struct ext2_inode_info {
        __u32   i_next_alloc_goal;
        __u32   i_prealloc_block;
        __u32   i_prealloc_count;
+       __u32   i_high_size;
        int     i_new_inode:1;  /* Is a freshly allocated inode */
 };
 
index b70e74ee7d44370c82d7b1847238050078590c30..ba411531c09c0ca388fce4e194e1195891270062 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: pci.h,v 1.51 1997/12/27 13:55:23 mj Exp $
+ *     $Id: pci.h,v 1.62 1998/03/15 13:50:05 ecd Exp $
  *
  *     PCI defines and function prototypes
  *     Copyright 1994, Drew Eckhardt
 #define PCI_CACHE_LINE_SIZE    0x0c    /* 8 bits */
 #define PCI_LATENCY_TIMER      0x0d    /* 8 bits */
 #define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL        0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
 #define PCI_BIST               0x0f    /* 8 bits */
 #define PCI_BIST_CODE_MASK     0x0f    /* Return result */
 #define PCI_BIST_START         0x40    /* 1 to start BIST, 2 secs or less */
 
 /* Header type 0 (normal devices) */
 #define PCI_CARDBUS_CIS                0x28
-#define PCI_SUBSYSTEM_ID       0x2c
-#define PCI_SUBSYSTEM_VENDOR_ID        0x2e  
+#define PCI_SUBSYSTEM_VENDOR_ID        0x2c
+#define PCI_SUBSYSTEM_ID       0x2e  
 #define PCI_ROM_ADDRESS                0x30    /* 32 bits */
 #define  PCI_ROM_ADDRESS_ENABLE        0x01    /* Write 1 to enable ROM,
                                           bits 31..11 are address,
 #define  PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
 #define  PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
 
+/* Header type 2 (CardBus bridges) -- detailed info welcome */
+#define PCI_CB_CARDBUS_BASE    0x10    /* CardBus Socket/ExCa base address */
+#define  PCI_CB_CARDBUS_BASE_TYPE_MASK 0xfff
+#define  PCI_CB_CARDBUS_BASE_MASK ~0xfff
+#define PCI_CB_CAPABILITIES    0x14    /* Offset of list of capabilities in cfg space */
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS      0x16    /* Secondary status */
+#define PCI_CB_BUS_NUMBER      0x18    /* PCI bus number */
+#define PCI_CB_CARDBUS_NUMBER  0x19    /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a    /* Subordinate bus number */
+#define PCI_CB_CARDBUS_LATENCY 0x1b    /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0   0x1c
+#define PCI_CB_MEMORY_LIMIT_0  0x20
+#define PCI_CB_MEMORY_BASE_1   0x24
+#define PCI_CB_MEMORY_LIMIT_1  0x28
+#define PCI_CB_IO_BASE_0       0x2c
+#define PCI_CB_IO_BASE_0_HI    0x2e
+#define PCI_CB_IO_LIMIT_0      0x30
+#define PCI_CB_IO_LIMIT_0_HI   0x32
+#define PCI_CB_IO_BASE_1       0x34
+#define PCI_CB_IO_BASE_1_HI    0x36
+#define PCI_CB_IO_LIMIT_1      0x38
+#define PCI_CB_IO_LIMIT_1_HI   0x3a
+/* 0x3c-0x3d are same as for htype 0 */
+/* 0x3e-0x3f are same as for htype 1 */
+#define PCI_CB_SUBSYSTEM_ID    0x40
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE        0x44    /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
 /* Device classes and subclasses */
 
 #define PCI_CLASS_NOT_DEFINED          0x0000
 
 /*
  * Vendor and card ID's: sort these numerically according to vendor
- * (and according to card ID within vendor)
+ * (and according to card ID within vendor). Send all updates to
+ * <linux-pcisupport@cck.uni-kl.de>.
  */
 #define PCI_VENDOR_ID_COMPAQ           0x0e11
 #define PCI_DEVICE_ID_COMPAQ_1280      0x3033
 #define PCI_VENDOR_ID_SUN              0x108e
 #define PCI_DEVICE_ID_SUN_EBUS         0x1000
 #define PCI_DEVICE_ID_SUN_HAPPYMEAL    0x1001
+#define PCI_DEVICE_ID_SUN_SIMBA                0x5000
 #define PCI_DEVICE_ID_SUN_PBM          0x8000
+#define PCI_DEVICE_ID_SUN_SABRE                0xa000
 
 #define PCI_VENDOR_ID_CMD              0x1095
 #define PCI_DEVICE_ID_CMD_640          0x0640
 #define PCI_VENDOR_ID_CERN             0x10dc
 #define PCI_DEVICE_ID_CERN_SPSB_PMC    0x0001
 #define PCI_DEVICE_ID_CERN_SPSB_PCI    0x0002
+#define PCI_DEVICE_ID_CERN_HIPPI_DST   0x0021
+#define PCI_DEVICE_ID_CERN_HIPPI_SRC   0x0022
 
 #define PCI_VENDOR_ID_NVIDIA           0x10de
 
 #define PCI_DEVICE_ID_CYCLOM_Z_Lo      0x0200
 #define PCI_DEVICE_ID_CYCLOM_Z_Hi      0x0201
 
+#define PCI_VENDOR_ID_ESSENTIAL                0x120f
+#define PCI_DEVICE_ID_ROADRUNNER       0x0001
+
 #define PCI_VENDOR_ID_O2               0x1217
 #define PCI_DEVICE_ID_O2_6832          0x6832
 
 #define PCI_SLOT(devfn)                (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)                ((devfn) & 0x07)
 
-/* create an index into the pci_dev base_address[] array from an offset */
-#define PCI_BASE_INDEX(o) (((o)-PCI_BASE_ADDRESS_0)>>2)
-
 #ifdef __KERNEL__
+
+/*
+ * Error values that may be returned by the PCI bios.  Use
+ * pcibios_strerror() to convert to a printable string.
+ */
+#define PCIBIOS_SUCCESSFUL             0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED     0x81
+#define PCIBIOS_BAD_VENDOR_ID          0x83
+#define PCIBIOS_DEVICE_NOT_FOUND       0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER    0x87
+#define PCIBIOS_SET_FAILED             0x88
+#define PCIBIOS_BUFFER_TOO_SMALL       0x89
+
+/* Direct configuration space access */
+
+int pcibios_present (void);
+void pcibios_init(void);
+void pcibios_fixup(void);
+char *pcibios_setup (char *str);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+                             unsigned char where, unsigned char *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+                             unsigned char where, unsigned short *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned int *val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned char val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned short val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned int val);
+const char *pcibios_strerror (int error);
+
+/* Don't use these in new code, use pci_find_... instead */
+
+int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
+int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
+                        unsigned short index, unsigned char *bus,
+                        unsigned char *dev_fn);
+
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
@@ -952,6 +1031,7 @@ struct pci_dev {
        unsigned short  vendor;
        unsigned short  device;
        unsigned int    class;          /* 3 bytes: (base,sub,prog-if) */
+       unsigned int    hdr_type;       /* PCI header type */
        unsigned int    master : 1;     /* set if device is master capable */
        /*
         * In theory, the irq level can be read from configuration
@@ -990,15 +1070,25 @@ struct pci_bus {
 
 extern struct pci_bus  pci_root;       /* root bus */
 extern struct pci_dev  *pci_devices;   /* list of all devices */
-extern struct pci_dev   *pci_find_dev (unsigned char bus, unsigned char devfn);
 
-extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
+void pci_init(void);
+void pci_setup(char *str, int *ints);
+void pci_quirks_init(void);
+unsigned int pci_scan_bus(struct pci_bus *bus);
 
-extern unsigned int pci_scan_bus (struct pci_bus *bus, unsigned long *mem_startp);
+struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
+struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 
-extern int get_pci_list (char *buf);
+#define pci_present pcibios_present
+#define pci_read_config_byte(dev, where, val) pcibios_read_config_byte(dev->bus->number, dev->devfn, where, val)
+#define pci_read_config_word(dev, where, val) pcibios_read_config_word(dev->bus->number, dev->devfn, where, val)
+#define pci_read_config_dword(dev, where, val) pcibios_read_config_dword(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_byte(dev, where, val) pcibios_write_config_byte(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_word(dev, where, val) pcibios_write_config_word(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_dword(dev, where, val) pcibios_write_config_dword(dev->bus->number, dev->devfn, where, val)
 
-extern void pci_quirks_init (void);
+int get_pci_list (char *buf);
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index e72a3df89e906ff760924e991480257ccaf2c077..1c81c23dedda54e2d149e1887b0305e5bce85623 100644 (file)
@@ -134,6 +134,7 @@ enum net_directory_inos {
        PROC_NET_DN_L1,
        PROC_NET_DN_L2,
        PROC_NET_DN_SKT,
+       PROC_NET_NETSTAT,
        PROC_NET_LAST
 };
 
index 79a7faf2a016cffcd60f4f013585087c860bc3bf..9e9b338b659a5bdf96a626a3de9fce49ef3c2a9d 100644 (file)
@@ -75,13 +75,7 @@ struct sk_buff {
 
        struct  dst_entry *dst;
 
-#if (defined(__alpha__) || defined(__sparc_v9__)) && (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
-       char            cb[48];    /* sorry. 64bit pointers have a price */
-#elif (defined(__alpha__) || defined(__sparc_v9__))
-       char            cb[40];
-#else
-       char            cb[36];
-#endif
+       char            cb[48];  
 
        unsigned int    len;                    /* Length of actual data                        */
        unsigned int    csum;                   /* Checksum                                     */
index 3b4ccf0945104f561412156b1d48c74ec2ec6ad9..8f47d3c125866e656b5a2cbdd0d352334e42f79c 100644 (file)
@@ -27,7 +27,7 @@
 /*
  * We time out our entries in the FDB after this many seconds.
  */
-#define FDB_TIMEOUT    300
+#define FDB_TIMEOUT    20 /* JRP: 20s as NSC bridge code, was 300 for Linux */
 
 /*
  * the following defines are the initial values used when the 
 #define BRIDGE_FORWARD_DELAY   15
 #define HOLD_TIME              1
 
+/* broacast/multicast storm limitation. This per source. */
+#define MAX_MCAST_PER_PERIOD    4
+#define MCAST_HOLD_TIME                10      /* in jiffies unit (10ms increment) */
+
 #define Default_path_cost 10
 
 /*
@@ -71,13 +75,25 @@ typedef struct {
 #define BRIDGE_ID_ULA  bi.p_u.ula
 #define BRIDGE_ID      bi.id
 
+/* JRP: on the network the flags field is between "type" and "root_id"
+ * this is unfortunated! To make the code portable to a RISC machine
+ * the pdus are now massaged a little bit for processing
+ */ 
+#define TOPOLOGY_CHANGE                0x01
+#define TOPOLOGY_CHANGE_ACK    0x80
+#define BRIDGE_BPDU_8021_CONFIG_SIZE            35     /* real size */
+#define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET     4
+#define BRIDGE_BPDU_8021_PROTOCOL_ID 0
+#define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0
+#define BRIDGE_LLC1_HS 3
+#define BRIDGE_LLC1_DSAP 0x42
+#define BRIDGE_LLC1_SSAP 0x42
+#define BRIDGE_LLC1_CTRL 0x03
+
 typedef struct {
        unsigned short  protocol_id;    
        unsigned char   protocol_version_id;
        unsigned char   type;
-       unsigned char   flags;
-#define TOPOLOGY_CHANGE                0x01
-#define TOPOLOGY_CHANGE_ACK    0x80
        bridge_id_t      root_id;                 /* (4.5.1.1)   */
        unsigned int     root_path_cost;          /* (4.5.1.2)   */
        bridge_id_t      bridge_id;               /* (4.5.1.3)   */
@@ -86,8 +102,23 @@ typedef struct {
        unsigned short   max_age;                 /* (4.5.1.6)   */
        unsigned short   hello_time;              /* (4.5.1.7)   */
        unsigned short   forward_delay;           /* (4.5.1.8)   */
+       unsigned char   top_change_ack;
+       unsigned char   top_change;
 } Config_bpdu;
 
+#ifdef __LITTLE_ENDIAN
+#define config_bpdu_hton(config_bpdu) \
+        (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \
+        (config_bpdu)->port_id = htons((config_bpdu)->port_id); \
+        (config_bpdu)->message_age = htons((config_bpdu)->message_age); \
+        (config_bpdu)->max_age = htons((config_bpdu)->max_age); \
+        (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \
+        (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay);
+#else
+#define config_bpdu_hton(config_bpdu)
+#endif
+#define config_bpdu_ntoh config_bpdu_hton
+
 
 /** Topology Change Notification BPDU Parameters (4.5.2) **/
 
@@ -112,12 +143,10 @@ typedef struct {
        unsigned short   bridge_max_age;          /* (4.5.3.8)   */
        unsigned short   bridge_hello_time;       /* (4.5.3.9)   */
        unsigned short   bridge_forward_delay;    /* (4.5.3.10)  */
-       unsigned int     topology_change_detected; /* (4.5.3.11) */
-       unsigned int     topology_change;         /* (4.5.3.12)  */
+       unsigned int     top_change_detected;     /* (4.5.3.11) */
+       unsigned int     top_change;              /* (4.5.3.12)  */
        unsigned short   topology_change_time;    /* (4.5.3.13)  */
        unsigned short   hold_time;               /* (4.5.3.14)  */
-       unsigned int     top_change;
-       unsigned int     top_change_detected;
 } Bridge_data;
 
 /** Port Parameters (4.5.5) **/
@@ -149,8 +178,11 @@ struct fdb {
        unsigned char pad[2];
        unsigned short port;
        unsigned int timer;
-       unsigned int flags;
+       unsigned short flags;
 #define FDB_ENT_VALID  0x01
+       unsigned short mcast_count;
+       unsigned int   mcast_timer;             /* oldest xxxxxcast */
+       
 /* AVL tree of all addresses, sorted by address */
        short fdb_avl_height;
        struct fdb *fdb_avl_left;
@@ -159,6 +191,19 @@ struct fdb {
        struct fdb *fdb_next;
 };
 
+/* data returned on BRCMD_DISPLAY_FDB */
+struct fdb_info {
+       unsigned char ula[6];
+       unsigned char port;
+        unsigned char flags;
+        unsigned int timer;
+};
+struct fdb_info_hdr {
+       int     copied;                 /* nb of entries copied to user */
+       int     not_copied;             /* when user buffer is too small */
+       int     cmd_time;
+};     
+
 #define IS_BRIDGED     0x2e
 
 
@@ -169,6 +214,34 @@ struct fdb {
 #define BR_ACCEPT 1
 #define BR_REJECT 0
 
+/* JRP: extra statistics for debug */
+typedef struct {
+       /* br_receive_frame counters */
+       int port_disable_up_stack;
+       int rcv_bpdu;
+       int notForwarding;
+       int forwarding_up_stack;
+       int unknown_state;
+
+       /* br_tx_frame counters */
+       int port_disable;
+       int port_not_disable;
+
+       /* br_forward counters */
+       int local_multicast;
+       int forwarded_multicast;        /* up stack as well */
+       int flood_unicast;
+       int aged_flood_unicast;
+       int forwarded_unicast;
+       int forwarded_unicast_up_stack;
+       int forwarded_ip_up_stack;
+       int forwarded_ip_up_stack_lie;  /* received on alternate device */
+       int arp_for_local_mac;
+       int drop_same_port;
+       int drop_same_port_aged;
+       int drop_multicast;
+} br_stats_counter;
+
 struct br_stat {
        unsigned int flags;
        Bridge_data bridge_data;
@@ -178,6 +251,7 @@ struct br_stat {
        unsigned short protocols[BR_MAX_PROTOCOLS];
        unsigned short prot_id[BR_MAX_PROT_STATS];      /* Protocol encountered */
        unsigned int prot_counter[BR_MAX_PROT_STATS];   /* How many packets ? */
+       br_stats_counter packet_cnts;
 };
 
 /* defined flags for br_stat.flags */
@@ -215,9 +289,10 @@ int br_receive_frame(struct sk_buff *skb); /* 3.5 */
 int br_tx_frame(struct sk_buff *skb);
 int br_ioctl(unsigned int cmd, void *arg);
 int br_protocol_ok(unsigned short protocol);
+void requeue_fdb(struct fdb *node, int new_port);
 
 struct fdb *br_avl_find_addr(unsigned char addr[6]);
-int br_avl_insert (struct fdb * new_node);
+struct fdb *br_avl_insert (struct fdb * new_node);
 
 /* externs */
 
index 9b536ddf71f8e83179b2b9fb9fe7721ed0bc9b51..35801b7c5e0f075d6eb8562f8bf5557d893ddd6c 100644 (file)
@@ -128,6 +128,7 @@ struct ipv4_config
 
 extern struct ipv4_config ipv4_config;
 extern struct ip_mib   ip_statistics;
+extern struct linux_mib        net_statistics;
 
 extern int sysctl_local_port_range[2];
 
index ee3bf0e205655082525a649d8f84312e97b5e61a..9cd239bf8e6a307c169e78f6a2dd9339052b4465 100644 (file)
@@ -124,5 +124,12 @@ struct udp_mib
        unsigned long   UdpInErrors;
        unsigned long   UdpOutDatagrams;
 };
+
+struct linux_mib 
+{
+       unsigned long   SyncookiesSent;
+       unsigned long   SyncookiesRecv;
+       unsigned long   SyncookiesFailed;
+};
        
 #endif
index 6b6f782eacb3192065aa7cbb16692af8aebdbcfc..271018a77ba89ef31bf390ac0819c01a82235de5 100644 (file)
@@ -274,7 +274,8 @@ struct tcp_opt {
 
        struct open_request     *syn_wait_queue;
        struct open_request     **syn_wait_last;
-       int syn_backlog;
+
+       int syn_backlog;        /* Backlog of received SYNs */
 };
 
        
index 01a95b5789ba6d1b8fafe308b2d1e6b9436ec736..88d3b2901e15381e4bac9d276c2f16182a191800 100644 (file)
@@ -941,6 +941,9 @@ extern __inline__ void tcp_select_initial_window(__u32 space, __u16 mss,
        (*window_clamp) = min(65535<<(*rcv_wscale),*window_clamp);
 }
 
+/* Do new listen semantics */
+#define TCP_NEW_LISTEN
+
 extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req, struct open_request *prev)
 {
        if(!req->dl_next)
@@ -961,20 +964,6 @@ extern __inline__ void tcp_synq_init(struct tcp_opt *tp)
        tp->syn_wait_last = &tp->syn_wait_queue;
 }
 
-extern __inline__ struct open_request *tcp_synq_unlink_tail(struct tcp_opt *tp)
-{
-       struct open_request *head = tp->syn_wait_queue;
-#if 0
-       /* Should be a net-ratelimit'd thing, not all the time. */
-       printk(KERN_DEBUG "synq tail drop with expire=%ld\n", 
-              head->expires-jiffies);
-#endif
-       if (head->dl_next == NULL)
-               tp->syn_wait_last = &tp->syn_wait_queue;
-       tp->syn_wait_queue = head->dl_next;
-       return head;
-}
-
 extern void __tcp_inc_slow_timer(struct tcp_sl_timer *slt);
 extern __inline__ void tcp_inc_slow_timer(int timer)
 {
index c9e0fff8d13ec24bdda5a35e19dc4dd8d5a7057f..88d56c0a7b2882e48405c829779097776a455069 100644 (file)
@@ -40,6 +40,9 @@
 
 #include <stdarg.h>
 
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
 
 /*
  * Versions of gcc older than that listed below may actually compile
@@ -61,23 +64,25 @@ extern int bdflush(void *);
 extern int kswapd(void *);
 extern void kswapd_setup(void);
 
+extern void dquot_init(void);
 extern void init_IRQ(void);
 extern void init_modules(void);
 extern long console_init(long, long);
 extern void sock_init(void);
 extern void uidcache_init(void);
-extern unsigned long pci_init(unsigned long, unsigned long);
 extern long mca_init(long, long);
 extern long sbus_init(long, long);
 extern long powermac_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
-extern void dquot_init(void);
 
 extern void smp_setup(char *str, int *ints);
+#ifdef __i386__
 extern void ioapic_pirq_setup(char *str, int *ints);
+#endif
 extern void no_scroll(char *str, int *ints);
+extern void kbd_reset_setup(char *str, int *ints);
 extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
 extern void msmouse_setup(char *str, int *ints);
@@ -473,8 +478,10 @@ static struct kernel_param cooked_params[] __initdata = {
 #ifdef __SMP__
        { "nosmp", smp_setup },
        { "maxcpus=", smp_setup },
+#ifdef __i386__
        { "pirq=", ioapic_pirq_setup },
 #endif
+#endif
 #ifdef CONFIG_BLK_DEV_RAM
        { "ramdisk_start=", ramdisk_start_setup },
        { "load_ramdisk=", load_ramdisk },
@@ -492,6 +499,7 @@ static struct kernel_param cooked_params[] __initdata = {
        { "console=", console_setup },
 #ifdef CONFIG_VT
        { "no-scroll", no_scroll },
+       { "kbd-reset", kbd_reset_setup },
 #endif
 #ifdef CONFIG_BUGi386
        { "no-hlt", no_halt },
@@ -737,6 +745,9 @@ static struct kernel_param raw_params[] __initdata = {
 #ifdef CONFIG_IP_PNP
        { "ip=", ip_auto_config_setup },
 #endif
+#ifdef CONFIG_PCI
+       { "pci=", pci_setup },
+#endif
 #ifdef CONFIG_PARIDE_PD
        { "pd.", pd_setup },
 #endif
@@ -1015,23 +1026,14 @@ __initfunc(asmlinkage void start_kernel(void))
                memset(prof_buffer, 0, prof_len * sizeof(unsigned int));
        }
 #endif
-#ifdef CONFIG_SBUS
-       memory_start = sbus_init(memory_start,memory_end);
-#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
-       memory_start = powermac_init(memory_start, memory_end);
-#endif
-#if defined(CONFIG_PCI) && defined(CONFIG_PCI_CONSOLE)
-       memory_start = pci_init(memory_start,memory_end);
-#endif
+
+/*
+ * HACK ALERT! This is early. We're enabling the console before
+ * we've done PCI setups etc, and console_init() must be aware of
+ * this. But we do want output early, in case something goes wrong.
+ */
 #if HACK
        memory_start = console_init(memory_start,memory_end);
-#endif
-#if defined(CONFIG_PCI) && !defined(CONFIG_PCI_CONSOLE)
-       memory_start = pci_init(memory_start,memory_end);
-#endif
-#ifdef CONFIG_MCA
-       memory_start = mca_init(memory_start,memory_end);
 #endif
        memory_start = kmem_cache_init(memory_start, memory_end);
        sti();
@@ -1070,6 +1072,24 @@ __initfunc(asmlinkage void start_kernel(void))
 #ifdef CONFIG_SYSCTL
        sysctl_init();
 #endif
+
+       /*
+        * Ok, at this point all CPU's should be initialized, so
+        * we can start looking into devices..
+        */
+#ifdef CONFIG_PCI
+       pci_init();
+#endif
+#ifdef CONFIG_SBUS
+       sbus_init();
+#endif
+#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+       powermac_init();
+#endif
+#ifdef CONFIG_MCA
+       mca_init();
+#endif
+
        /* 
         *      We count on the initial thread going ok 
         *      Like idlers init is an unlocked kernel thread, which will
index 6f1101319f082277e03eb6c449f743c356926071..61201da1602bc2e6884dc399ac119605fa023dc9 100644 (file)
 
 extern unsigned char aux_device_present, kbd_read_mask;
 
-#ifdef CONFIG_PCI
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#endif
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
 #endif
@@ -100,19 +96,6 @@ EXPORT_SYMBOL(get_module_symbol);
 #endif
 EXPORT_SYMBOL(get_options);
 
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pcibios_present);
-EXPORT_SYMBOL(pcibios_find_class);
-EXPORT_SYMBOL(pcibios_find_device);
-EXPORT_SYMBOL(pcibios_read_config_byte);
-EXPORT_SYMBOL(pcibios_read_config_word);
-EXPORT_SYMBOL(pcibios_read_config_dword);
-EXPORT_SYMBOL(pcibios_write_config_byte);
-EXPORT_SYMBOL(pcibios_write_config_word);
-EXPORT_SYMBOL(pcibios_write_config_dword);
-EXPORT_SYMBOL(pcibios_strerror);
-#endif
-
 /* process memory management */
 EXPORT_SYMBOL(do_mmap);
 EXPORT_SYMBOL(do_munmap);
@@ -265,6 +248,7 @@ EXPORT_SYMBOL(register_binfmt);
 EXPORT_SYMBOL(unregister_binfmt);
 EXPORT_SYMBOL(search_binary_handler);
 EXPORT_SYMBOL(prepare_binprm);
+EXPORT_SYMBOL(compute_creds);
 EXPORT_SYMBOL(remove_arg_zero);
 
 /* execution environment registration */
@@ -354,6 +338,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
 EXPORT_SYMBOL(_ctype);
 EXPORT_SYMBOL(secure_tcp_sequence_number);
 EXPORT_SYMBOL(get_random_bytes);
+EXPORT_SYMBOL(securebits);
 
 /* Program loader interfaces */
 EXPORT_SYMBOL(setup_arg_pages);
index 006026d64b1553ffd810b891c30fcaad39d1c6a9..7c7e5bc3282e0cd1d962c010f4ce1a552080c384 100644 (file)
@@ -292,8 +292,12 @@ repeat:
        spin_lock_irqsave(&page_alloc_lock, flags);
        RMQUEUE(order, maxorder, (gfp_mask & GFP_DMA));
        spin_unlock_irqrestore(&page_alloc_lock, flags);
-       if ((gfp_mask & __GFP_WAIT) && try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX))
-               goto repeat;
+       if (gfp_mask & __GFP_WAIT) {
+               int freed = try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX);
+               gfp_mask &= ~__GFP_WAIT;        /* go through this only once */
+               if (freed)
+                       goto repeat;
+       }
 nopage:
        return 0;
 }
index 36efa363b8f45e57519b768e665444e468c98c46..f2c62fab6a231969f65a71665d129814477f0b39 100644 (file)
@@ -1342,10 +1342,7 @@ int dev_change_flags(struct device *dev, unsigned flags)
        ret = 0;
        if ((old_flags^flags)&IFF_UP)   /* Bit is different  ? */
        {
-               if(old_flags&IFF_UP)            /* Gone down */
-                       ret=dev_close(dev);             
-               else                            /* Come up */
-                       ret=dev_open(dev);
+               ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
 
                if (ret == 0) 
                        dev_mc_upload(dev);
index 6997e8d06ee342b092de7fd68beafac1e4561477..2c5220e0fc4909799874e8828d48560b7c49e0d4 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             AF_INET protocol family socket handler.
  *
- * Version:    $Id: af_inet.c,v 1.68 1998/03/27 07:02:42 davem Exp $
+ * Version:    $Id: af_inet.c,v 1.69 1998/04/03 09:49:42 freitag Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 
 #define min(a,b)       ((a)<(b)?(a):(b))
 
+struct linux_mib net_statistics;
+
 extern int sysctl_core_destroy_delay;
 
 extern int raw_get_info(char *, char **, off_t, int, int);
 extern int snmp_get_info(char *, char **, off_t, int, int);
+extern int netstat_get_info(char *, char **, off_t, int, int);
 extern int afinet_get_info(char *, char **, off_t, int, int);
 extern int tcp_get_info(char *, char **, off_t, int, int);
 extern int udp_get_info(char *, char **, off_t, int, int);
@@ -1016,6 +1019,12 @@ static struct proc_dir_entry proc_net_raw = {
        0, &proc_net_inode_operations,
        raw_get_info
 };
+static struct proc_dir_entry proc_net_netstat = {
+       PROC_NET_NETSTAT, 7, "netstat",
+       S_IFREG | S_IRUGO, 1, 0, 0,
+       0, &proc_net_inode_operations,
+       netstat_get_info
+};
 static struct proc_dir_entry proc_net_snmp = {
        PROC_NET_SNMP, 4, "snmp",
        S_IFREG | S_IRUGO, 1, 0, 0,
@@ -1141,6 +1150,7 @@ __initfunc(void inet_proto_init(struct net_proto *pro))
 #endif         /* RARP */
        proc_net_register(&proc_net_raw);
        proc_net_register(&proc_net_snmp);
+       proc_net_register(&proc_net_netstat);
        proc_net_register(&proc_net_sockstat);
        proc_net_register(&proc_net_tcp);
        proc_net_register(&proc_net_udp);
index 28dee6bd0b9cc501ddd0047f6f85861ef4e78789..a993919c56353199921a29a5dd2956c2a887d03c 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) module.
  *
- * Version:    $Id: ip_input.c,v 1.27 1998/03/08 05:56:24 davem Exp $
+ * Version:    $Id: ip_input.c,v 1.29 1998/04/03 10:52:06 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index ded186675d1894bb18669a1bf0aca531f24df506..e930ad39aaec28575dd0ccea394f4380ac251801 100644 (file)
@@ -7,7 +7,7 @@
  *             PROC file system.  It is mainly used for debugging and
  *             statistics.
  *
- * Version:    $Id: proc.c,v 1.27 1998/03/18 07:51:59 davem Exp $
+ * Version:    $Id: proc.c,v 1.28 1998/04/03 09:49:45 freitag Exp $
  *
  * Authors:    Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -25,6 +25,7 @@
  *             Alan Cox        :       Allow inode to be NULL (kernel socket)
  *     Andi Kleen              :       Add support for open_requests and 
  *                                     split functions for more readibility.
+ *     Andi Kleen              :       Add support for /proc/net/netstat
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -337,3 +338,31 @@ int snmp_get_info(char *buffer, char **start, off_t offset, int length, int dumm
                len = length;
        return len;
 }
+
+/* 
+ *     Output /proc/net/netstat
+ */
+int netstat_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+       extern struct linux_mib net_statistics;
+       int len;
+
+       len = sprintf(buffer,
+                     "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed\n"
+                     "TcpExt: %lu %lu %lu\n",
+                     net_statistics.SyncookiesSent,
+                     net_statistics.SyncookiesRecv,
+                     net_statistics.SyncookiesFailed);
+
+       if (offset >= len)
+       {
+               *start = buffer;
+               return 0;
+       }
+       *start = buffer + offset;
+       len -= offset;
+       if (len > length)
+               len = length;
+       return len;
+}
index 00dd0a8efae6fd63f01675b8f17f0a44f18f253c..a3e3be0f16ff369df09a8db26d4a259568fb0186 100644 (file)
@@ -9,11 +9,9 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.4 1998/03/08 05:56:34 davem Exp $
+ *  $Id: syncookies.c,v 1.5 1998/04/03 09:49:46 freitag Exp $
  *
  *  Missing: IPv6 support. 
- *           Some counter so that the Administrator can see when the machine
- *           is under a syn flood attack.
  */
 
 #include <linux/config.h>
@@ -88,6 +86,8 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
 found:
        *mssp = w[-1]; 
 
+       net_statistics.SyncookiesSent++;
+
        isn |= i; 
        return isn; 
 }
@@ -110,8 +110,9 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
        __u32 seq; 
 
        if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT
-           && tcp_lastsynq_overflow) 
+           && tcp_lastsynq_overflow) {
                return 0; 
+       }
 
        mssind = cookie & 7;
        cookie &= ~7;
@@ -157,8 +158,12 @@ cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
                return sk; 
 
        mss = cookie_check(skb, cookie);
-       if (mss == 0) 
+       if (mss == 0) {
+               net_statistics.SyncookiesFailed++;
                return sk;
+       }
+
+       net_statistics.SyncookiesRecv++;
 
        req = tcp_openreq_alloc();
        if (req == NULL)
index 1d7315481d41ad38eafc5736aef19dad4490aa9d..3e282a54b86c762bb1f205cc2e3dc20d82859053 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.31 1998/03/30 08:41:41 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.32 1998/04/03 09:49:47 freitag Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -155,8 +155,6 @@ ctl_table ipv4_table[] = {
         sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_TCP_RFC1337, "tcp_rfc1337", &sysctl_tcp_rfc1337,
         sizeof(int), 0644, NULL, &proc_dointvec},
-       {NET_TCP_SYN_TAILDROP, "tcp_syn_taildrop", &sysctl_tcp_syn_taildrop,
-        sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog", &sysctl_max_syn_backlog,
         sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range",
index e9fcec0476e9831f57e9c3138252aca383a7ecd2..12e0362474d678a8308196e80109f43ccb169d72 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.108 1998/03/29 08:43:51 davem Exp $
+ * Version:    $Id: tcp.c,v 1.110 1998/04/03 09:49:51 freitag Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1160,6 +1160,11 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                        break;
                }
 
+               if (sk->shutdown & RCV_SHUTDOWN) {
+                       sk->done = 1;
+                       break;
+               }
+
                if (sk->state == TCP_CLOSE) {
                        if (!sk->done) {
                                sk->done = 1;
@@ -1169,11 +1174,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                        break;
                }
 
-               if (sk->shutdown & RCV_SHUTDOWN) {
-                       sk->done = 1;
-                       break;
-               }
-
                if (nonblock) {
                        copied = -EAGAIN;
                        break;
@@ -1529,7 +1529,7 @@ struct sock *tcp_accept(struct sock *sk, int flags)
        tcp_synq_unlink(tp, req, prev);
        newsk = req->sk;
        tcp_openreq_free(req);
-       sk->ack_backlog--;  /* XXX */
+       sk->ack_backlog--; 
 
        /* FIXME: need to check here if newsk has already
         * an soft_err or err set.
index 7dab8ff8874d9a3b759f4cb2fc47ca7d6c4554d0..deffa0667a16a13987c3ba732e69707e360a2c6f 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.103 1998/03/30 08:41:12 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.104 1998/04/01 07:41:24 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1906,7 +1906,10 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                        tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1;
                        tp->rcv_wup = TCP_SKB_CB(skb)->seq+1;
 
-                       tp->snd_wnd = htons(th->window) << tp->snd_wscale;
+                       /* RFC1323: The window in SYN & SYN/ACK segments is
+                        * never scaled.
+                        */
+                       tp->snd_wnd = htons(th->window);
                        tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
                        tp->snd_wl2 = TCP_SKB_CB(skb)->ack_seq;
                        tp->fin_seq = TCP_SKB_CB(skb)->seq;
@@ -1918,6 +1921,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                tp->snd_wscale = tp->rcv_wscale = 0;
                                tp->window_clamp = min(tp->window_clamp,65535);
                        }
+
                        if (tp->tstamp_ok) {
                                tp->tcp_header_len =
                                        sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
@@ -1980,6 +1984,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
                                tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
 
+                               /* RFC1323: The window in SYN & SYN/ACK segments is
+                                * never scaled.
+                                */
                                tp->snd_wnd = htons(th->window);
                                tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
                                
index 408fa3e8735ef4071883ef619b812a70beb499bf..f1601e4919684bd8f0ff87ae1b380e0dad28a766 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.127 1998/03/30 08:41:25 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.131 1998/04/03 10:52:04 davem Exp $
  *
  *             IPv4 specific functions
  *
  *                                     most of it into the af independent code.
  *                                     Added tail drop and some other bugfixes.
  *                                     Added new listen sematics (ifdefed by
- *                                     NEW_LISTEN for now)
+ *                                     TCP_NEW_LISTEN for now)
  *             Mike McLagan    :       Routing by source
  *     Juan Jose Ciarlante:            ip_dynaddr bits
  *             Andi Kleen:             various fixes.
  *     Vitaly E. Lavrov        :       Transparent proxy revived after year coma.
+ *     Andi Kleen              :       Fix TCP_NEW_LISTEN and make it the default.
  */
 
 #include <linux/config.h>
@@ -812,6 +813,11 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
                if (req->sk) {  /* not yet accept()ed */
                        sk = req->sk; /* report error in accept */
                } else {
+#ifdef TCP_NEW_LISTEN
+                       tp->syn_backlog--;
+#else
+                       sk->ack_backlog--;
+#endif
                        tcp_synq_unlink(tp, req, prev);
                        req->class->destructor(req);
                        tcp_openreq_free(req);
@@ -1017,7 +1023,6 @@ tcp_v4_save_options(struct sock *sk, struct sk_buff *skb,
 }
 
 int sysctl_max_syn_backlog = 1024; 
-int sysctl_tcp_syn_taildrop = 1;
 
 struct or_calltable or_ipv4 = {
        tcp_v4_send_synack,
@@ -1025,7 +1030,7 @@ struct or_calltable or_ipv4 = {
        tcp_v4_send_reset
 };
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
 #define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */
 #define BACKLOGMAX(sk) sysctl_max_syn_backlog
 #else
@@ -1057,27 +1062,19 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
                if (sysctl_tcp_syncookies) {
                        syn_flood_warning(skb);
                        want_cookie = 1; 
-               } else 
+               } else
 #endif
-               if (sysctl_tcp_syn_taildrop) {
-                       struct open_request *req;
-
-                       req = tcp_synq_unlink_tail(&sk->tp_pinfo.af_tcp);
-                       tcp_openreq_free(req);
-                       tcp_statistics.TcpAttemptFails++;
-               } else {
-                       goto error;
-               }
+               goto drop;
        } else { 
                if (isn == 0)
                        isn = tcp_v4_init_sequence(sk, skb);
-               BACKLOG(sk)++;
        }
 
+       BACKLOG(sk)++;
+
        req = tcp_openreq_alloc();
        if (req == NULL) {
-               if (!want_cookie) BACKLOG(sk)--;
-               goto error;
+               goto dropbacklog;
        }
 
        req->rcv_wnd = 0;               /* So that tcp_send_synack() knows! */
@@ -1137,7 +1134,10 @@ dead:
        tcp_statistics.TcpAttemptFails++;
        return -ENOTCONN; /* send reset */
 
-error:
+dropbacklog:
+       if (!want_cookie) 
+               BACKLOG(sk)--;
+drop:
        tcp_statistics.TcpAttemptFails++;
        return 0;
 }
@@ -1184,7 +1184,12 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
                newtp->ato = 0;
                newtp->snd_wl1 = req->rcv_isn;
                newtp->snd_wl2 = req->snt_isn;
+
+               /* RFC1323: The window in SYN & SYN/ACK segments
+                * is never scaled.
+                */
                newtp->snd_wnd = ntohs(skb->h.th->window);
+
                newtp->max_window = newtp->snd_wnd;
                newtp->pending = 0;
                newtp->retransmits = 0;
@@ -1270,6 +1275,10 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
        return newsk;
 }
 
+/* 
+ * The three way handshake has completed - we got a valid synack - 
+ * now create the new socket. 
+ */
 struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                                   struct open_request *req,
                                   struct dst_entry *dst)
@@ -1280,7 +1289,7 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        int snd_mss;
        int mtu;
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
        if (sk->ack_backlog > sk->max_ack_backlog)
                goto exit; /* head drop */
 #endif
@@ -1288,13 +1297,14 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                struct rtable *rt;
                
                if (ip_route_output(&rt,
-                                   opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
-                                   req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0))
+                       opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
+                       req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0))
                        return NULL;
                dst = &rt->u.dst;
        }
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
+       sk->tp_pinfo.af_tcp.syn_backlog--;
        sk->ack_backlog++;
 #endif
 
@@ -1343,6 +1353,11 @@ static void tcp_v4_rst_req(struct sock *sk, struct sk_buff *skb)
            after(TCP_SKB_CB(skb)->seq, req->snt_isn+1))
                return;
        tcp_synq_unlink(tp, req, prev);
+#ifdef TCP_NEW_LISTEN
+       (req->sk ? sk->ack_backlog : tp->syn_backlog)--;
+#else
+       sk->ack_backlog--;
+#endif
        req->class->destructor(req);
        tcp_openreq_free(req); 
 }
@@ -1468,9 +1483,14 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
                skb->csum = csum_partial((char *)th, len, 0);
        case CHECKSUM_HW:
                if (tcp_v4_check(th,len,skb->nh.iph->saddr,skb->nh.iph->daddr,skb->csum)) {
-                       printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n",
-                              NIPQUAD(skb->nh.iph->saddr), ntohs(th->source), NIPQUAD(skb->nh.iph->daddr),
-                              ntohs(th->dest), len, skb->len, ntohs(skb->nh.iph->tot_len));
+                       printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, "
+                              "len=%d/%d/%d\n",
+                              NIPQUAD(ntohl(skb->nh.iph->saddr)),
+                              ntohs(th->source), 
+                              NIPQUAD(ntohl(skb->nh.iph->daddr)),
+                              ntohs(th->dest),
+                              len, skb->len,
+                              ntohs(skb->nh.iph->tot_len));
                        tcp_statistics.TcpInErrs++;
                        goto discard_it;
                }
@@ -1642,7 +1662,7 @@ static int tcp_v4_init_sock(struct sock *sk)
        tp->rto  = TCP_TIMEOUT_INIT;            /*TCP_WRITE_TIME*/
        tp->mdev = TCP_TIMEOUT_INIT;
        tp->in_mss = 536;
-
+      
        /* See draft-stevens-tcpca-spec-01 for discussion of the
         * initialization of these values.
         */
index 664231f23e9f9a31a92f81cba28aeca29c546f48..7f0853cf1227c253cf6b6e7680cd3b7d20f40104 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_output.c,v 1.81 1998/03/30 08:41:36 davem Exp $
+ * Version:    $Id: tcp_output.c,v 1.83 1998/04/03 08:10:45 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -109,6 +109,9 @@ void tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
                th->check               = 0;
                th->urg_ptr             = ntohs(tcb->urg_ptr);
                if(tcb->flags & TCPCB_FLAG_SYN) {
+                       /* RFC1323: The window in SYN & SYN/ACK segments
+                        * is never scaled.
+                        */
                        th->window      = htons(tp->rcv_wnd);
                        tcp_syn_build_options((__u32 *)(th + 1), sk->mss,
                                              sysctl_tcp_timestamps,
@@ -610,6 +613,24 @@ void tcp_send_fin(struct sock *sk)
                TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
                TCP_SKB_CB(skb)->end_seq++;
                tp->write_seq++;
+
+               /* Special case to avoid Nagle bogosity.  If this
+                * segment is the last segment, and it was queued
+                * due to Nagle/SWS-avoidance, send it out now.
+                */
+               if(tp->send_head == skb &&
+                  !sk->nonagle &&
+                  skb->len < (sk->mss >> 1) &&
+                  tp->packets_out &&
+                  !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) {
+                       update_send_head(sk);
+                       TCP_SKB_CB(skb)->when = jiffies;
+                       tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+                       tp->packets_out++;
+                       tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+                       if(!tcp_timer_is_set(sk, TIME_RETRANS))
+                               tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+               }
        } else {
                /* Socket is locked, keep trying until memory is available. */
                do {
@@ -755,6 +776,8 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
                        &rcv_wscale);
                req->rcv_wscale = rcv_wscale; 
        }
+
+       /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
        th->window = htons(req->rcv_wnd);
 
        TCP_SKB_CB(skb)->when = jiffies;
index 78fcad3fefa5c3668bc9ef5b30e0d353d295df37..f57f678b4f3d2450fc0b500584e668b5e619fb0f 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_timer.c,v 1.45 1998/03/30 08:41:31 davem Exp $
+ * Version:    $Id: tcp_timer.c,v 1.47 1998/04/03 10:52:05 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -451,6 +451,7 @@ static void tcp_syn_recv_timer(unsigned long data)
                                        if ((long)(now - conn->expires) <= 0)
                                                break;
 
+
                                        tcp_synq_unlink(tp, conn, prev);
                                        if (conn->retrans >= sysctl_tcp_retries1) {
 #ifdef TCP_DEBUG
@@ -459,7 +460,11 @@ static void tcp_syn_recv_timer(unsigned long data)
 #endif
                                                (*conn->class->destructor)(conn);
                                                tcp_dec_slow_timer(TCP_SLT_SYNACK);
-                                               sk->ack_backlog--;
+#ifdef TCP_NEW_LISTEN
+                                       tp->syn_backlog--;
+#else
+                                       sk->ack_backlog--;
+#endif
                                                tcp_openreq_free(conn);
 
                                                if (!tp->syn_wait_queue)
index e4162fac9a4b8de825e9e6245deea810c9d25de2..c2f811d7b36b326cf2d9fa45ace5d10bc97ace5c 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: tcp_ipv6.c,v 1.72 1998/03/30 08:41:52 davem Exp $
+ *     $Id: tcp_ipv6.c,v 1.74 1998/04/03 09:50:01 freitag Exp $
  *
  *     Based on: 
  *     linux/net/ipv4/tcp.c
@@ -42,9 +42,6 @@
 
 #include <asm/uaccess.h>
 
-extern int sysctl_tcp_timestamps;
-extern int sysctl_tcp_window_scaling;
-
 static void    tcp_v6_send_reset(struct sk_buff *skb);
 static void    tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
                                  struct sk_buff *skb);
@@ -748,12 +745,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
        if (sk->ack_backlog >= sk->max_ack_backlog) {
                printk(KERN_DEBUG "droping syn ack:%d max:%d\n",
                       sk->ack_backlog, sk->max_ack_backlog);
-               tcp_statistics.TcpAttemptFails++;
-               goto exit;
+               goto drop;              
        }
 
        req = tcp_openreq_alloc();
        if (req == NULL) {
+               goto drop;
        }
 
        sk->ack_backlog++;
@@ -796,8 +793,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
 
        sk->data_ready(sk, 0);
 
-exit:
        return 0;
+
+drop:
+       tcp_statistics.TcpAttemptFails++;
+       return 0; /* don't send reset */
 }
 
 static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,