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
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
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
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
--- /dev/null
+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>
*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:
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)
--- /dev/null
+ 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).
--- /dev/null
+ 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
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 92
+SUBLEVEL = 93
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
#else /* CONFIG_PCI */
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/malloc.h>
#include <linux/mm.h>
#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;
}
#endif /* CONFIG_ALPHA_MIATA */
+__initfunc(char *pcibios_setup(char *str))
+{
+ return str;
+}
+
#ifdef CONFIG_ALPHA_SRM_SETUP
void reset_for_srm(void)
{
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <asm/ptrace.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/sched.h>
#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>
*/
#include <linux/kernel.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
#include <linux/malloc.h>
#include <linux/mm.h>
#include <linux/init.h>
#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>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/sched.h>
/*
- * 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>
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 *);
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,
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)
{
#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;
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
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,
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,
__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
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;
}
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),
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)
{
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)
{
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,
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);
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;
}
#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>
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);
EXPORT_SYMBOL(mca_isenabled);
EXPORT_SYMBOL(mca_isadapter);
#endif
-
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
-#endif
#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:
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)
/*
* 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);
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");
}
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 *)®_00 = io_apic_read(0);
+ printk("... changing IO-APIC physical APIC ID to 2 ...\n");
+ reg_00.ID = 0x2;
+ io_apic_write(0, *(int *)®_00);
+
+ /*
+ * Sanity check
+ */
+ *(int *)®_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();
{
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:
*
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 ()) {
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();
}
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 */
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;
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.
*/
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));
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)
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;
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;
/*
* 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.
* 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;
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);
}
*
* 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>
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
return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
}
+__initfunc(char *pcibios_setup(char *str))
+{
+ return str;
+}
+
#endif /* defined(CONFIG_PCI) */
* 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>
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
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
--- /dev/null
+/* $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
+}
#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>
*/
const char *good_dma_drives[] = {"Micropolis 2112A",
"CONNER CTMA 4000",
+ "ST34342A",
NULL};
/*
{
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
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);
}
}
-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;
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) {
}
return dma_base;
}
-
#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>
#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
{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}} },
* 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;
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 */
}
}
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;
/*
* 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;
}
*/
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;
}
* 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
* 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;
}
/*
* 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)
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;
}
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 */
}
/*
- * 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);
}
}
}
#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"
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;
}
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');
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/malloc.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/delay.h>
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
} 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
*/
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)
__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);
}
__initfunc(static void probe_for_hwifs (void))
{
#ifdef CONFIG_PCI
- if (pcibios_present())
+ if (pci_present())
{
#ifdef CONFIG_BLK_DEV_IDEPCI
ide_scan_pcibus();
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))
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 */
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
/*
* 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;
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);
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)();
}
/*
* 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)
{
/*
* 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)
{
{
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);
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);
/*
* 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.
{
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:
}
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) ||
/* 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;
* 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)
{
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);
}
{
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.
*
* 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 */
}
#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
#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, ®)
- && !pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, 0x40, reg & 0xdfff))
+ if (!pci_read_config_word (dev, 0x40, ®)
+ && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
{
printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name);
} else {
#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 & 1)) {
+ if (!pci_read_config_word (dev, PCI_COMMAND, ®) && !(reg & PCI_COMMAND_IO)) {
printk("%s: buggy IDE controller disabled (BIOS)\n", name);
return;
}
- if (!pcibios_read_config_word (bus, fn, 0x40, ®)
- && !pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))
+ if (!pci_read_config_word (dev, 0x40, ®)
+ && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
{
printk("IDE: disabled chipset read-ahead (buggy %s)\n", name);
} else {
__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
--- /dev/null
+#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;
+}
+
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/delay.h>
#include <asm/io.h>
{
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;
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++;
}
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;
}
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
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/version.h>
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;
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 */
}
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",
}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",
}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,
#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(
#ifdef ENABLE_PCI
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/digiPCI.h>
#endif /* ENABLE_PCI */
--------------------------------------------------------------------- */
pci_boards_found = 0;
- if (pcibios_present())
+ if (pci_present())
{
if(num_cards < MAXBOARDS)
pci_boards_found += init_PCI(num_cards);
#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
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 */
} /* End init_PCI */
#endif /* ENABLE_PCI */
-
-
#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... */
* 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;
printk(KERN_WARNING "initialize_kbd: %s\n", msg);
}
-#endif /* INIT_KBD */
+
unsigned char kbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */
{
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;
}
* -- 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>
#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;
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);
}
}
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;
}
#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 */
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;
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) {
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 {
#ifdef CONFIG_PCI
#include <linux/pci.h>
-#include <linux/bios32.h>
#endif
/*****************************************************************************/
#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
/*
* 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));
* 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__,
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...
* 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);
}
#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>
#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;
__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;
/*
* 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;
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 */
#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>
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)
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;
}
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;
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);
#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>
#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");
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;
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. */
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
#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>
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);
#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;
/*
{
u_long iobase = dev->base_addr;
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
eisa_probe(dev, iobase);
#endif
pci_probe(dev, 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]);
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)) {
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.
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! */
}
(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);
}
}
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);
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 */
/* 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);
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++;
}
#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>
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 */
/* 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
}
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) */
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) */
#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>
#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)
/*
* 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;
&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,
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;
#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>
#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
{
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
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)
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <asm/bitops.h>
#include <asm/io.h>
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
/* at first - scan PCI bus(es) */
#ifdef CONFIG_PCI
- if ( pcibios_present() )
+ if ( pci_present() )
{
int pci_index;
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. */
#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>
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. */
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);
#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>
#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);
#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
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);
#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>
* 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
*/
__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)
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))
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;
#ifdef CONFIG_PCI
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <asm/pbm.h>
#endif
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
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)
{
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
/* 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++;
}
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;
/* 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++;
/* 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++;
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;
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;
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;
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)
{
}
}
#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
#include "tlan.h"
-#include <linux/bios32.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>
};
-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 *);
int failed;
int found;
u32 io_base;
- u8 irq;
+ int irq;
u8 rev;
printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n",
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 );
*
**************************************************************/
-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;
int reg;
- if ( ! pcibios_present() ) {
+ if ( ! pci_present() ) {
printk( "TLAN: PCI Bios not present.\n" );
return 0;
}
);
if ( ! not_found ) {
+ struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn);
TLAN_DBG(
TLAN_DEBUG_GNRL,
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);
#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>
#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
#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. */
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;
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;
# 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
L_OBJS += quirks.o
endif
+L_OBJS += compat.o
+
include $(TOPDIR)/Rules.make
--- /dev/null
+/*
+ * $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;
+}
/*
- * $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.
*
#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>
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"),
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"),
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"),
/*
- * $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];
}
-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;
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;
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
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++) {
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",
* 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
/*
* 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;
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
{
/*
* 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:
}
-__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);
}
--- /dev/null
+/*
+ * $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);
/*
- * $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>
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))
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;
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);
+}
/*
- * $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
*
#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/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>
__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;
}
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
}
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;
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",
}
}
- 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,
#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>
return h;
}
+#if 0
/*
* Function : request_synchronous (int host, int target)
*
restore_flags(flags);
return 0;
}
+#endif
/*
* Function : request_disconnect (int host, int on_or_off)
/*
* 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
*
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
#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>
* 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 */
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);
#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;
#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
*
*
* 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)
*
**************************************************************************/
__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,
*
* 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;
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);
+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
#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>
*/
#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
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;
};
/*
*/
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
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
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
*/
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 */
/****************************************************************************
{
if (p->maddr != NULL)
{
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__powerpc__)
int i;
for (i=0; i < size; i++)
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)
{
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);
outb(inb(p->base + SIMODE1) | ENSCSIRST, p->base + SIMODE1);
udelay(1000);
+
+ restore_flags(processor_flags);
}
/*+F*************************************************************************
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
{
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]);
/*
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;
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
*
* 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
}
}
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
/*+F*************************************************************************
* Function:
* aic7xxx_probe
return (AIC_NONE);
}
+#endif /* __sparc_v9__ or __powerpc__ */
/*+F*************************************************************************
* Function:
{
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;
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);
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);
}
/*
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. */
*/
unpause_sequencer(p, /* unpause_always */ TRUE);
+ /*
+ * Add it to our list of adapters.
+ */
+ p->next = first_aic7xxx;
+ first_aic7xxx = p;
+
return (found);
}
* 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;
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.
*/
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.
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");
/*
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
{
};
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.
/*
* 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)
}
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;
}
index++;
- /*
- * Disable spurious interrupts.
- */
- aic7xxx_spurious_count = 0;
- } /* Found an Adaptec PCI device. */
- }
- }
+ } /* Found an Adaptec PCI device. */
}
#endif CONFIG_PCI
/*
* 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)
{
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
{
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
{
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);
}
}
}
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))
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
{
* 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;
{
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;
#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.
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 */\
{
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)
return (length);
}
}
+ HBAptr = p->host;
if (inout == TRUE) /* Has data been written to the file? */
{
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);
/*
* 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
#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
#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
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 */
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 */
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 */
/* 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 */
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 */
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 */
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,
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);
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;
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;
while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {
udelay(1L);
- if (--loop == 0) return TRUE;
+ if (--loop == 0) return TRUE;
}
loop = MAXLOOP;
}
__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;
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;
}
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)
}
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;
}
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];
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;
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;
}
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);
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;
}
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",
unsigned char bus, devfn;
unsigned int addr, k;
- if (!pcibios_present()) return;
+ if (!pci_present()) return;
for (k = 0; k < MAX_PCI; k++) {
}
#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();
}
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;
}
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 */
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;
SCpnt->pid);
restore_flags(flags);
done(SCpnt);
- return 0;
+ return 1;
}
HD(j)->cp_stat[i] = IN_USE;
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));
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);
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;
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)
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;
}
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;
}
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) {
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
}
-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;
}
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);
/*
- * 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
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
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))
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))
* 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>
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
#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
}
* 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
*
* 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
#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>
#include <linux/timer.h>
#if LINUX_VERSION_CODE >= 0x020100
#include <linux/reboot.h>
+#else
+#include <linux/bios32.h>
#endif
#include <asm/dma.h>
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,
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
pcibios_strerror(error));
return -1;
}
+#endif
pcistr->device_id = device_id;
if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */
#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':
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) {
* 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
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 */ \
}
#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
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))
** 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)
#endif
}
#endif /* !NCR_IOMAPPED */
+#endif /* __sparc__ */
#else /* linux-1.2.13 */
** 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.
/*
** irq level
*/
- u_short irq;
+ u_int irq;
};
#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl))
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;
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
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));
** 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;
*/
#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
** 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) {
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;
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);
#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;
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;
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;
** the order they are detected.
*/
- if (!pcibios_present())
+ if (!pci_present())
return 0;
chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]);
{
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;
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
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);
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,
}
#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
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;
}
/*
* 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)
#define SCSI_NCR_IOMAPPED
#elif defined(__alpha__) || defined(__powerpc__)
#define SCSI_NCR_IOMAPPED
+#elif defined(__sparc__)
+#undef SCSI_NCR_IOMAPPED
#endif
/*
#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 */
#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>
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;
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
{
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
#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>
****************************************************************/
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};
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));
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;
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
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;
scsi_unregister (pshost);
NumAdapters++;
}
- }
return NumAdapters;
}
/****************************************************************
#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>
#define DEFAULT_LOOP_COUNT 1000000
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
/* End Configuration section *************************************************/
#include <linux/module.h>
#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 */
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 *);
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
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);
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);
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);
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");
{
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));
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;
}
*/
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
/*
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))
* 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 *
***********************************************************************/
#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>
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,
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;
*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;
{
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
USHORT
-EEpromGetData1( USHORT mechnum )
+EEpromGetData1( struct pci_dev *pdev )
{
UCHAR i;
UCHAR carryFlag;
for(i=0; i<16; i++)
{
wval <<= 1;
- carryFlag = DC390_EEpromInDO(mechnum);
+ carryFlag = DC390_EEpromInDO(pdev);
wval |= carryFlag;
}
return(wval);
void
-DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
+DC390_Prepare( struct pci_dev *pdev, PUCHAR regval, UCHAR EEpromCmd )
{
UCHAR i,j;
USHORT carryFlag;
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;
}
void
-DC390_ReadEEprom( USHORT mechnum, USHORT index )
+DC390_ReadEEprom( struct pci_dev *pdev, int index )
{
UCHAR regval,cmd;
PUSHORT ptr;
cmd = EEPROM_READ;
for(i=0; i<0x40; i++)
{
- DC390_EnDisableCE(ENABLE_CE, mechnum, ®val);
- DC390_Prepare(mechnum, ®val, cmd);
- *ptr = EEpromGetData1(mechnum);
+ DC390_EnDisableCE(ENABLE_CE, pdev, ®val);
+ DC390_Prepare(pdev, ®val, cmd);
+ *ptr = EEpromGetData1(pdev);
ptr++;
cmd++;
- DC390_EnDisableCE(DISABLE_CE,mechnum,®val);
+ DC390_EnDisableCE(DISABLE_CE, pdev, ®val);
}
}
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++)
}
-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)
*
***********************************************************************/
__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 )
__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;
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;
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 */
/*
* 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
#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
#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
#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
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 */
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,
#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)
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);
}
__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];
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;
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;
}
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;
}
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);
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;
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");
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",
}
#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++) {
}
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;
}
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 */
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++)
SCpnt->pid);
restore_flags(flags);
done(SCpnt);
- return 0;
+ return 1;
}
/* Store pointer in OGM address bytes */
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));
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);
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;
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)
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;
}
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;
}
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) {
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
}
}
-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;
}
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);
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
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
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
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
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
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;
}
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)) {
*/
set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
- sb->s_dev = 0;
- unlock_super(sb);
MOD_DEC_USE_COUNT;
return;
}
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"));
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;
}
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;
}
/* 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;
}
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;
printk("Coda: Bye bye.\n");
memset(sb_info, 0, sizeof(* sb_info));
- unlock_super(sb);
MOD_DEC_USE_COUNT;
EXIT;
}
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;
}
--- /dev/null
+#
+# 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
--- /dev/null
+/* -*- 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;
--- /dev/null
+/* -*- 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
--- /dev/null
+/* -*- 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;
+}
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 ||
#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)
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;
}
/*
* 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;
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 &&
}
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++;
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,
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);
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) ||
goto do_more;
}
sb->s_dirt = 1;
+error_return:
unlock_super (sb);
return;
}
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
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);
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;
}
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;
*/
#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;
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)
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",
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))
};
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;
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)
"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;
}
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;
* 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
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
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;
* 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
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 */
long long offset,
int origin)
{
- long long retval;
struct inode *inode = file->f_dentry->d_inode;
switch (origin) {
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)
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;
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
/*
* 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
#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;
}
/*
* 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;
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;
}
}
}
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++;
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;
}
/*
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);
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);
wait_on_buffer (bh);
}
sb->s_dirt = 1;
+error_return:
unlock_super (sb);
}
/* 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;
}
*/
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))) {
* 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
{
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;
}
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;
}
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))) <
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",
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)
*
* 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>
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);
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
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);
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;
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)
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
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);
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));
printk ("IO error syncing ext2 inode ["
"%s:%08lx]\n",
kdevname(inode->i_dev), inode->i_ino);
- err = -1;
+ err = -EIO;
}
}
brelse (bh);
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.
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
*
* 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);
}
*/
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];
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) {
}
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;
}
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]);
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));
}
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)
*/
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;
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) {
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,
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
* 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);
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;
* 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))
}
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;
}
{
struct inode * inode;
struct buffer_head * bh;
- struct ext2_dir_entry * de;
+ struct ext2_dir_entry_2 * de;
int err = -EIO;
/*
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)) {
{
struct inode * inode;
struct buffer_head * bh;
- struct ext2_dir_entry * de;
+ struct ext2_dir_entry_2 * de;
int err = -EIO;
err = -ENAMETOOLONG;
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);
{
struct inode * inode;
struct buffer_head * bh, * dir_block;
- struct ext2_dir_entry * de;
+ struct ext2_dir_entry_2 * de;
int err;
err = -ENAMETOOLONG;
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? */
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);
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)) {
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);
{
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;
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",
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)) {
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;
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)
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);
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)
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);
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;
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)) {
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;
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)) {
}
#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
{
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;
* 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;
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);
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);
}
}
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])
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;
}
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;
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);
kfree(MSDOS_SB(sb)->options.iocharset);
MSDOS_SB(sb)->options.iocharset = NULL;
}
- sb->s_dev = 0;
- unlock_super(sb);
+
MOD_DEC_USE_COUNT;
return;
}
#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>
init_adfs_fs();
#endif
+#ifdef CONFIG_DEVPTS_FS
+ init_devpts_fs();
+#endif
+
#ifdef CONFIG_NLS
init_nls();
#endif
{
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;
/* 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;
}
static void hpfs_put_super(struct super_block *s)
{
- lock_super(s);
- s->s_dev = 0;
- unlock_super(s);
MOD_DEC_USE_COUNT;
}
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;
}
{
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);
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;
}
{
struct ncp_server *server = NCP_SBP(sb);
- lock_super(sb);
-
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
- sb->s_dev = 0;
- unlock_super(sb);
-
MOD_DEC_USE_COUNT;
}
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);
nfs_invalidate_dircache_sb(sb);
kfree(server->hostname);
- sb->s_dev = 0;
- unlock_super(sb);
+
MOD_DEC_USE_COUNT;
}
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);
}
}
-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
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? */
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...
*/
static void
romfs_put_super(struct super_block *sb)
{
- lock_super(sb);
- sb->s_dev = 0;
- unlock_super(sb);
MOD_DEC_USE_COUNT;
return;
}
{
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);
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;
}
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;
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. */
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;
}
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;
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];
* 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)
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 */
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
}
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
}
/*
- * 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
--- /dev/null
+/* -*- 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 */
* 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
#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
*/
} 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
__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
*/
* 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
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
*
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 */
__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 */
};
/*
- * $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:
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
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 */
PROC_NET_DN_L1,
PROC_NET_DN_L2,
PROC_NET_DN_SKT,
+ PROC_NET_NETSTAT,
PROC_NET_LAST
};
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 */
/*
* 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
/*
#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) */
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) **/
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) **/
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;
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
#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;
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 */
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 */
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];
unsigned long UdpInErrors;
unsigned long UdpOutDatagrams;
};
+
+struct linux_mib
+{
+ unsigned long SyncookiesSent;
+ unsigned long SyncookiesRecv;
+ unsigned long SyncookiesFailed;
+};
#endif
struct open_request *syn_wait_queue;
struct open_request **syn_wait_last;
- int syn_backlog;
+
+ int syn_backlog; /* Backlog of received SYNs */
};
(*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)
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)
{
#include <stdarg.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
/*
* Versions of gcc older than that listed below may actually compile
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);
#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 },
{ "console=", console_setup },
#ifdef CONFIG_VT
{ "no-scroll", no_scroll },
+ { "kbd-reset", kbd_reset_setup },
#endif
#ifdef CONFIG_BUGi386
{ "no-hlt", no_halt },
#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
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();
#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
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
#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);
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 */
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);
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;
}
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);
*
* 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);
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,
#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);
*
* 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>
* 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>
* 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
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;
+}
* 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>
found:
*mssp = w[-1];
+ net_statistics.SyncookiesSent++;
+
isn |= i;
return isn;
}
__u32 seq;
if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT
- && tcp_lastsynq_overflow)
+ && tcp_lastsynq_overflow) {
return 0;
+ }
mssind = cookie & 7;
cookie &= ~7;
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)
/*
* 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]
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",
*
* 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>
break;
}
+ if (sk->shutdown & RCV_SHUTDOWN) {
+ sk->done = 1;
+ break;
+ }
+
if (sk->state == TCP_CLOSE) {
if (!sk->done) {
sk->done = 1;
break;
}
- if (sk->shutdown & RCV_SHUTDOWN) {
- sk->done = 1;
- break;
- }
-
if (nonblock) {
copied = -EAGAIN;
break;
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.
*
* 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>
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;
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;
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;
*
* 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>
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);
}
int sysctl_max_syn_backlog = 1024;
-int sysctl_tcp_syn_taildrop = 1;
struct or_calltable or_ipv4 = {
tcp_v4_send_synack,
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
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! */
tcp_statistics.TcpAttemptFails++;
return -ENOTCONN; /* send reset */
-error:
+dropbacklog:
+ if (!want_cookie)
+ BACKLOG(sk)--;
+drop:
tcp_statistics.TcpAttemptFails++;
return 0;
}
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;
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)
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
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
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);
}
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;
}
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.
*/
*
* 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>
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,
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 {
&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;
*
* 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>
if ((long)(now - conn->expires) <= 0)
break;
+
tcp_synq_unlink(tp, conn, prev);
if (conn->retrans >= sysctl_tcp_retries1) {
#ifdef TCP_DEBUG
#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)
* 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
#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);
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++;
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,