diff -u --recursive --new-file v2.1.92/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.92/linux/Documentation/Configure.help Wed Apr 1 20:11:46 1998 +++ linux/Documentation/Configure.help Sat Apr 4 09:45:13 1998 @@ -974,8 +974,7 @@ that implements the TGA interface (much like the VGA standard, but older TGA adapters are *not* VGA compatible). On such systems, you should say Y here so that the TGA driver rather than the standard - VGA driver is used. Note that, at this time, there is no X server - for these systems. If unsure, try N. + VGA driver is used. PCI support CONFIG_PCI @@ -1019,9 +1018,13 @@ Backward-compatible /proc/pci CONFIG_PCI_OLD_PROC - If you say Y here and to the "/proc filesystem support" below, you - will get a directory /proc/pci with information about your PCI - hardware. If unsure, say Y. + Older kernels supported a /proc/pci file containing brief textual + description of all PCI devices in the system. Several programs tried + to parse this file, so it became almost impossible to add new + fields without breaking compatibility. So a new /proc interface to + PCI (/proc/bus/pci) has been implemented and the old one is supported + for compatibility reasons only (you can disable it here, gaining + some memory). If unsure, say Y. MCA support CONFIG_MCA @@ -5343,7 +5346,7 @@ 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 @@ -5421,6 +5424,13 @@ inserted in and removed from the running kernel whenever you want). 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 diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/ip_dynaddr.txt linux/Documentation/networking/ip_dynaddr.txt --- v2.1.92/linux/Documentation/networking/ip_dynaddr.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/networking/ip_dynaddr.txt Fri Apr 3 17:48:11 1998 @@ -0,0 +1,29 @@ +IP dynamic address hack-port v0.03 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This stuff allows diald ONESHOT connections to get established by +dynamically changing packet source address (and socket's if local procs). +It is implemented for TCP diald-box connections(1) and IP_MASQuerading(2). + +If enabled[*] and forwarding interface has changed: + 1) Socket (and packet) source address is rewritten ON RETRANSMISSIONS + while in SYN_SENT state (diald-box processes). + 2) Out-bounded MASQueraded source address changes ON OUTPUT (when + internal host does retransmission) until a packet from outside is + received by the tunnel. + +This is specially helpful for auto dialup links (diald), where the +``actual'' outgoing address is unknown at the moment the link is +going up. So, the *same* (local AND masqueraded) connections requests that +bring the link up will be able to get established. + +[*] At boot, by default no address rewriting is attempted. + To enable: + # echo 1 > /proc/sys/net/ipv4/ip_dynaddr + To enable verbose mode: + # echo 2 > /proc/sys/net/ipv4/ip_dynaddr + To disable (default) + # echo 0 > /proc/sys/net/ipv4/ip_dynaddr + +Enjoy! + +-- Juanjo diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/ppp.txt linux/Documentation/networking/ppp.txt --- v2.1.92/linux/Documentation/networking/ppp.txt Sun Nov 30 12:23:16 1997 +++ linux/Documentation/networking/ppp.txt Fri Apr 3 17:48:11 1998 @@ -1,11 +1,7 @@ *NEWSFLASH* This kernel release needs a minor bug fix for pppd to run properly with the new routing code. When your pppd doesn't work apply the following -patch to pppd-2.2.0f or install updated RPMs. - -Updated RPMs for libc5 machines (build on RedHat 4.0): -ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.src.rpm -ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.i386.rpm +patch to pppd-2.2.0f or update to the newest pppd version. Patch: diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/routing.txt linux/Documentation/networking/routing.txt --- v2.1.92/linux/Documentation/networking/routing.txt Thu Dec 19 00:31:52 1996 +++ linux/Documentation/networking/routing.txt Mon Apr 6 11:38:56 1998 @@ -35,10 +35,10 @@ NEWS for hacker. -- New destination cache. Flexible, robust and just beatiful. +- New destination cache. Flexible, robust and just beautiful. - Network stack is reordered, simplified, optimized, a lot of bugs fixed. - (well, and new bugs are intoduced, but I've yet not seen them 8)) - It is difficult to descibe all the changes, look into source. + (well, and new bugs are introduced, but I haven't seen them yet 8)) + It is difficult to describe all the changes, look into source. If you see this file, then this patch works 8) diff -u --recursive --new-file v2.1.92/linux/Documentation/pci.txt linux/Documentation/pci.txt --- v2.1.92/linux/Documentation/pci.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/pci.txt Thu Apr 2 09:12:22 1998 @@ -0,0 +1,60 @@ + Few Notes About The PCI Subsystem + + or + + "What should you avoid when writing PCI drivers" + + by Martin Mares 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 . + +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 +~~~~~~~~~~~~~~~~~~~~~ + + is obsolete and should not be included in new code. + +pcibios_find_(device|class) are also obsolete and should be replaced by +pci_find_(device|class). diff -u --recursive --new-file v2.1.92/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- v2.1.92/linux/Documentation/sysrq.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sysrq.txt Fri Apr 3 17:50:32 1998 @@ -0,0 +1,89 @@ + MAGIC SYSRQ KEY DOCUMENTATION v1.0 + ------------------------------------ + [Fri Apr 3 08:27:12 EST 1998] + +1. What is the magic SysRQ key? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is a 'magical' key combo you can hit, and the kernel will respond to +regardless of anything else, unless it is hard-locked. + +2. How do I enable the magic SysRQ key? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when +configuring the kernel. This option is only available it 2.1.x or later +kernels. + +3. How do I use the magic SysRQ key? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You press the key combo 'ALT-SysRQ-'. + +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 diff -u --recursive --new-file v2.1.92/linux/Makefile linux/Makefile --- v2.1.92/linux/Makefile Wed Apr 1 20:11:47 1998 +++ linux/Makefile Thu Apr 2 21:23:00 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 92 +SUBLEVEL = 93 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.92/linux/arch/alpha/kernel/bios32.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/bios32.c Thu Apr 2 09:12:22 1998 @@ -56,7 +56,6 @@ #else /* CONFIG_PCI */ -#include #include #include #include @@ -555,55 +554,6 @@ #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; @@ -2247,6 +2197,11 @@ return 0; } #endif /* CONFIG_ALPHA_MIATA */ + +__initfunc(char *pcibios_setup(char *str)) +{ + return str; +} #ifdef CONFIG_ALPHA_SRM_SETUP void reset_for_srm(void) diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/cia.c linux/arch/alpha/kernel/cia.c --- v2.1.92/linux/arch/alpha/kernel/cia.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/cia.c Thu Apr 2 09:12:22 1998 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c --- v2.1.92/linux/arch/alpha/kernel/lca.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/lca.c Thu Apr 2 09:12:22 1998 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/mcpcia.c linux/arch/alpha/kernel/mcpcia.c --- v2.1.92/linux/arch/alpha/kernel/mcpcia.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/mcpcia.c Thu Apr 2 09:12:22 1998 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/pyxis.c linux/arch/alpha/kernel/pyxis.c --- v2.1.92/linux/arch/alpha/kernel/pyxis.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/pyxis.c Thu Apr 2 09:12:22 1998 @@ -7,7 +7,6 @@ #include /* CONFIG_ALPHA_RUFFIAN. */ #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c --- v2.1.92/linux/arch/alpha/kernel/smc37c669.c Tue Mar 10 10:03:30 1998 +++ linux/arch/alpha/kernel/smc37c669.c Thu Apr 2 09:12:22 1998 @@ -3,8 +3,6 @@ */ #include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/smc37c93x.c linux/arch/alpha/kernel/smc37c93x.c --- v2.1.92/linux/arch/alpha/kernel/smc37c93x.c Tue Mar 10 10:03:30 1998 +++ linux/arch/alpha/kernel/smc37c93x.c Thu Apr 2 09:12:22 1998 @@ -5,8 +5,6 @@ #include #include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/t2.c linux/arch/alpha/kernel/t2.c --- v2.1.92/linux/arch/alpha/kernel/t2.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/t2.c Thu Apr 2 09:12:22 1998 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/tsunami.c linux/arch/alpha/kernel/tsunami.c --- v2.1.92/linux/arch/alpha/kernel/tsunami.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/tsunami.c Thu Apr 2 09:12:22 1998 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.1.92/linux/arch/i386/kernel/bios32.c Wed Feb 4 11:36:00 1998 +++ linux/arch/i386/kernel/bios32.c Mon Apr 6 13:58:39 1998 @@ -1,7 +1,7 @@ /* - * bios32.c - BIOS32, PCI BIOS functions. + * bios32.c - Low-Level PCI Access * - * $Id: bios32.c,v 1.17 1997/11/16 11:03:41 mj Exp $ + * $Id: bios32.c,v 1.26 1998/02/18 15:21:09 mj Exp $ * * Sponsored by * iX Multiuser Multitasking Magazine @@ -64,12 +64,13 @@ * * Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts * and cleaned it up... Martin Mares + * + * Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj] */ #include #include #include -#include #include #include @@ -91,8 +92,6 @@ struct pci_access { int pci_present; - int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *); - int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *); int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *); int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *); int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *); @@ -108,8 +107,6 @@ static struct pci_access pci_access_none = { 0, /* No PCI present */ - (void *) pci_stub, /* No functions implemented */ - (void *) pci_stub, (void *) pci_stub, (void *) pci_stub, (void *) pci_stub, @@ -125,18 +122,6 @@ return access_pci->pci_present; } -int pcibios_find_class (unsigned int class_code, unsigned short index, - unsigned char *bus, unsigned char *device_fn) -{ - return access_pci->find_class(class_code, index, bus, device_fn); -} - -int pcibios_find_device (unsigned short vendor, unsigned short device_id, - unsigned short index, unsigned char *bus, unsigned char *device_fn) -{ - return access_pci->find_device(vendor, device_id, index, bus, device_fn); -} - int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value) { @@ -147,6 +132,9 @@ #ifdef __SMP__ /* * IOAPICs can take PCI IRQs directly, lets first check the mptable: + * + * This can go away once nobody probes the irq this way, + * but uses the PCI tables instead. */ if (where == PCI_INTERRUPT_LINE) { int irq; @@ -205,60 +193,17 @@ return access_pci->write_config_dword(bus, device_fn, where, value); } -/* - * Direct access to PCI hardware... - */ +static unsigned int pci_probe = ~0; -/* - * Given the vendor and device ids, find the n'th instance of that device - * in the system. - */ - -#ifdef CONFIG_PCI_DIRECT - -static int pci_direct_find_device (unsigned short vendor, unsigned short device_id, - unsigned short index, unsigned char *bus, - unsigned char *devfn) -{ - unsigned int curr = 0; - struct pci_dev *dev; - - for (dev = pci_devices; dev; dev = dev->next) { - if (dev->vendor == vendor && dev->device == device_id) { - if (curr == index) { - *devfn = dev->devfn; - *bus = dev->bus->number; - return PCIBIOS_SUCCESSFUL; - } - ++curr; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} +#define PCI_PROBE_BIOS 1 +#define PCI_PROBE_CONF1 2 +#define PCI_PROBE_CONF2 4 /* - * Given the class, find the n'th instance of that device - * in the system. + * Direct access to PCI hardware... */ -static int pci_direct_find_class (unsigned int class_code, unsigned short index, - unsigned char *bus, unsigned char *devfn) -{ - unsigned int curr = 0; - struct pci_dev *dev; - - for (dev = pci_devices; dev; dev = dev->next) { - if (dev->class == class_code) { - if (curr == index) { - *devfn = dev->devfn; - *bus = dev->bus->number; - return PCIBIOS_SUCCESSFUL; - } - ++curr; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} +#ifdef CONFIG_PCI_DIRECT /* * Functions for accessing PCI configuration space with type 1 accesses @@ -346,8 +291,6 @@ static struct pci_access pci_direct_conf1 = { 1, - pci_direct_find_device, - pci_direct_find_class, pci_conf1_read_config_byte, pci_conf1_read_config_word, pci_conf1_read_config_dword, @@ -458,8 +401,6 @@ static struct pci_access pci_direct_conf2 = { 1, - pci_direct_find_device, - pci_direct_find_class, pci_conf2_read_config_byte, pci_conf2_read_config_word, pci_conf2_read_config_dword, @@ -470,39 +411,43 @@ __initfunc(static struct pci_access *pci_check_direct(void)) { - unsigned int tmp; - unsigned long flags; + unsigned int tmp; + unsigned long flags; - save_flags(flags); cli(); + save_flags(flags); cli(); + + /* + * Check if configuration type 1 works. + */ + if (pci_probe & PCI_PROBE_CONF1) { + outb (0x01, 0xCFB); + tmp = inl (0xCF8); + outl (0x80000000, 0xCF8); + if (inl (0xCF8) == 0x80000000) { + outl (tmp, 0xCF8); + restore_flags(flags); + printk("PCI: Using configuration type 1\n"); + return &pci_direct_conf1; + } + outl (tmp, 0xCF8); + } + + /* + * Check if configuration type 2 works. + */ + if (pci_probe & PCI_PROBE_CONF2) { + outb (0x00, 0xCFB); + outb (0x00, 0xCF8); + outb (0x00, 0xCFA); + if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) { + restore_flags(flags); + printk("PCI: Using configuration type 2\n"); + return &pci_direct_conf2; + } + } - /* - * Check if configuration type 1 works. - */ - outb (0x01, 0xCFB); - tmp = inl (0xCF8); - outl (0x80000000, 0xCF8); - if (inl (0xCF8) == 0x80000000) { - outl (tmp, 0xCF8); - restore_flags(flags); - printk("PCI: Using configuration type 1\n"); - return &pci_direct_conf1; - } - outl (tmp, 0xCF8); - - /* - * Check if configuration type 2 works. - */ - outb (0x00, 0xCFB); - outb (0x00, 0xCF8); - outb (0x00, 0xCFA); - if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) { restore_flags(flags); - printk("PCI: Using configuration type 2\n"); - return &pci_direct_conf2; - } - restore_flags(flags); - printk("PCI: PCI hardware not found (i.e., not present or not supported).\n"); - return NULL; + return NULL; } #endif @@ -599,7 +544,7 @@ 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 .\n", service, return_code); return 0; } @@ -642,7 +587,7 @@ 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 .\n", (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR", present_status, signature, (char) (signature >> 0), (char) (signature >> 8), @@ -660,6 +605,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) { @@ -709,6 +656,8 @@ return (int) (ret & 0xff00) >> 8; } +#endif + static int pci_bios_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value) { @@ -847,8 +796,6 @@ static struct pci_access pci_bios_access = { 1, - pci_bios_find_device, - pci_bios_find_class, pci_bios_read_config_byte, pci_bios_read_config_word, pci_bios_read_config_dword, @@ -887,18 +834,14 @@ 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 \n", check->fields.revision, check); continue; } printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check); if (check->fields.entry >= 0x100000) { -#ifdef CONFIG_PCI_DIRECT - printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n"); - return pci_check_direct(); -#else printk("PCI: BIOS32 entry in high memory, cannot use.\n"); -#endif + return NULL; } else { bios32_entry = check->fields.entry; printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); @@ -909,39 +852,128 @@ 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 \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 \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; +} - return memory_start; +#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT) +#error PCI configured with neither PCI BIOS or PCI direct access support. +#endif + +__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; } diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.1.92/linux/arch/i386/kernel/i386_ksyms.c Tue Mar 17 22:18:13 1998 +++ linux/arch/i386/kernel/i386_ksyms.c Sun Apr 5 12:08:41 1998 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -64,13 +63,14 @@ 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); @@ -96,8 +96,4 @@ EXPORT_SYMBOL(mca_set_adapter_procfn); EXPORT_SYMBOL(mca_isenabled); EXPORT_SYMBOL(mca_isadapter); -#endif - -#if CONFIG_PCI -EXPORT_SYMBOL(pci_devices); #endif diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.1.92/linux/arch/i386/kernel/io_apic.c Tue Mar 17 22:18:13 1998 +++ linux/arch/i386/kernel/io_apic.c Mon Apr 6 14:03:45 1998 @@ -28,13 +28,11 @@ #include "irq.h" -#define IO_APIC_BASE 0xfec00000 - /* * volatile is justified in this case, it might change * spontaneously, GCC should not cache it */ -volatile unsigned int * io_apic_reg = NULL; +#define IO_APIC_BASE ((volatile int *)0xfec00000) /* * The structure of the IO-APIC: @@ -96,17 +94,19 @@ int mp_irq_entries = 0; /* # of MP IRQ source entries */ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* MP IRQ source entries */ +int mpc_default_type = 0; /* non-0 if default (table-less) + MP configuration */ unsigned int io_apic_read (unsigned int reg) { - *io_apic_reg = reg; - return *(io_apic_reg+4); + *IO_APIC_BASE = reg; + return *(IO_APIC_BASE+4); } void io_apic_write (unsigned int reg, unsigned int value) { - *io_apic_reg = reg; - *(io_apic_reg+4) = value; + *IO_APIC_BASE = reg; + *(IO_APIC_BASE+4) = value; } void enable_IO_APIC_irq (unsigned int irq) @@ -256,7 +256,7 @@ /* * PCI IRQ redirection. Yes, limits are hardcoded. */ - if ((i>=16) && (i<=19)) { + if ((i>=16) && (i<=23)) { if (pirq_entries[i-16] != -1) { if (!pirq_entries[i-16]) { printk("disabling PIRQ%d\n", i-16); @@ -516,16 +516,16 @@ static void init_sym_mode (void) { printk("enabling Symmetric IO mode ... "); - outb (0x70, 0x22); - outb (0x01, 0x23); + outb_p (0x70, 0x22); + outb_p (0x01, 0x23); printk("...done.\n"); } void init_pic_mode (void) { printk("disabling Symmetric IO mode ... "); - outb (0x70, 0x22); - outb (0x00, 0x23); + outb_p (0x70, 0x22); + outb_p (0x00, 0x23); printk("...done.\n"); } @@ -579,17 +579,85 @@ 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; impc_lapic); - /* set the local APIC address */ - apic_addr = (unsigned long)phys_to_virt((unsigned long)mpc->mpc_lapic); + /* check the local APIC address */ + if ((char *)phys_to_virt((unsigned long)mpc->mpc_lapic) != APIC_BASE) + panic("unexpected APIC address"); /* * Now process the configuration blocks. @@ -454,7 +453,7 @@ */ cfg=pg0[0]; - pg0[0] = (apic_addr | 7); + pg0[0] = ((unsigned long)APIC_BASE | 7); local_flush_tlb(); boot_cpu_id = GET_APIC_ID(*((volatile unsigned long *) APIC_ID)); @@ -477,6 +476,14 @@ cpu_present_map=3; num_processors=2; printk("I/O APIC at 0xFEC00000.\n"); + + /* + * Save the default type number, we + * need it later to set the IO-APIC + * up properly: + */ + mpc_default_type = mpf->mpf_feature1; + printk("Bus #0 is "); } switch(mpf->mpf_feature1) @@ -525,11 +532,6 @@ if(mpf->mpf_physptr) smp_read_mpc((void *)mpf->mpf_physptr); - /* - * Now that the boot CPU id is known, - * set some other information about it. - */ - nlong = boot_cpu_id<<24; /* Dummy 'self' for bootup */ __cpu_logical_map[0] = boot_cpu_id; global_irq_holder = boot_cpu_id; current->processor = boot_cpu_id; @@ -951,15 +953,6 @@ printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); } - /* - * Map the local APIC into kernel space - */ - - apic_reg = ioremap(apic_addr,4096); - - if(apic_reg == NULL) - panic("Unable to map local apic."); - #ifdef SMP_DEBUG { int reg; @@ -1497,7 +1490,7 @@ /* * 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. diff -u --recursive --new-file v2.1.92/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.92/linux/arch/i386/mm/init.c Tue Mar 17 22:18:14 1998 +++ linux/arch/i386/mm/init.c Sun Apr 5 12:08:41 1998 @@ -174,29 +174,29 @@ * It may also hold the MP configuration table when we are booting SMP. */ #ifdef __SMP__ - if (!smp_scan_config(0x0,0x400)) /* Scan the bottom 1K for a signature */ - { + /* + * FIXME: Linux assumes you have 640K of base ram.. + * this continues the error... + * + * 1) Scan the bottom 1K for a signature + * 2) Scan the top 1K of base RAM + * 3) Scan the 64K of bios + */ + if (!smp_scan_config(0x0,0x400) && + !smp_scan_config(639*0x400,0x400) && + !smp_scan_config(0xF0000,0x10000)) { /* - * FIXME: Linux assumes you have 640K of base ram.. this continues - * the error... + * If it is an SMP machine we should know now, unless the + * configuration is in an EISA/MCA bus machine with an + * extended bios data area. + * + * there is a real-mode segmented pointer pointing to the + * 4K EBDA area at 0x40E, calculate and scan it here: */ - if (!smp_scan_config(639*0x400,0x400)) /* Scan the top 1K of base RAM */ - { - if(!smp_scan_config(0xF0000,0x10000)) /* Scan the 64K of bios */ - { - /* - * If it is an SMP machine we should know now, unless the configuration - * is in an EISA/MCA bus machine with an extended bios data area. - */ - - address = *(unsigned short *)phys_to_virt(0x40E); /* EBDA */ - address<<=4; /* Real mode segments to physical */ - smp_scan_config(address, 0x1000); /* Scan the EBDA */ - } - } + address = *(unsigned short *)phys_to_virt(0x40E); + address<<=4; + smp_scan_config(address, 0x1000); } - -/* smp_alloc_memory(8192); */ #endif start_mem = PAGE_ALIGN(start_mem); address = PAGE_OFFSET; @@ -255,7 +255,50 @@ 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); } diff -u --recursive --new-file v2.1.92/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c --- v2.1.92/linux/arch/mips/kernel/pci.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/kernel/pci.c Thu Apr 2 09:12:22 1998 @@ -5,7 +5,6 @@ * * MIPS implementation of PCI BIOS services for PCI support. */ -#include #include #include #include @@ -36,53 +35,6 @@ } /* - * 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 * specific implementation. @@ -127,6 +79,11 @@ unsigned char where, unsigned int val) { return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val); +} + +__initfunc(char *pcibios_setup(char *str)) +{ + return str; } #endif /* defined(CONFIG_PCI) */ diff -u --recursive --new-file v2.1.92/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.1.92/linux/arch/mips/sni/pci.c Wed Dec 10 10:31:10 1997 +++ linux/arch/mips/sni/pci.c Thu Apr 2 09:12:22 1998 @@ -6,7 +6,6 @@ * SNI specific PCI support for RM200/RM300. */ #include -#include #include #include #include diff -u --recursive --new-file v2.1.92/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.1.92/linux/drivers/block/Config.in Wed Feb 4 11:36:00 1998 +++ linux/drivers/block/Config.in Thu Apr 2 09:12:22 1998 @@ -34,6 +34,9 @@ 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 diff -u --recursive --new-file v2.1.92/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.1.92/linux/drivers/block/Makefile Tue Mar 10 10:03:31 1998 +++ linux/drivers/block/Makefile Thu Apr 2 09:12:22 1998 @@ -155,6 +155,14 @@ L_OBJS += ns87415.o endif +ifeq ($(CONFIG_BLK_DEV_CMD646),y) +L_OBJS += cmd646.o +endif + +ifeq ($(CONFIG_BLK_DEV_SL82C105),y) +L_OBJS += sl82c105.o +endif + ifeq ($(CONFIG_BLK_DEV_IDEDISK),y) L_OBJS += ide-disk.o else diff -u --recursive --new-file v2.1.92/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c --- v2.1.92/linux/drivers/block/cmd646.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/cmd646.c Thu Apr 2 09:12:22 1998 @@ -0,0 +1,20 @@ +/* $Id: cmd646.c,v 1.1 1998/03/15 13:29:10 ecd Exp $ + * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines + * + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + */ + +#include +#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 +} diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c --- v2.1.92/linux/drivers/block/ide-dma.c Thu Jan 15 20:51:04 1998 +++ linux/drivers/block/ide-dma.c Thu Apr 2 09:12:22 1998 @@ -70,7 +70,7 @@ #include #include #include -#include +#include #include #include @@ -84,6 +84,7 @@ */ const char *good_dma_drives[] = {"Micropolis 2112A", "CONNER CTMA 4000", + "ST34342A", NULL}; /* @@ -140,7 +141,7 @@ { struct request *rq = HWGROUP(drive)->rq; struct buffer_head *bh = rq->bh; - unsigned long size, addr, *table = HWIF(drive)->dmatable; + unsigned int size, addr, *table = (unsigned int *)HWIF(drive)->dmatable; #ifdef CONFIG_BLK_DEV_TRM290 unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290); #else @@ -183,7 +184,7 @@ printk("%s: DMA table too small\n", drive->name); return 0; /* revert to PIO for this request */ } else { - unsigned long xcount, bcount = 0x10000 - (addr & 0xffff); + unsigned int xcount, bcount = 0x10000 - (addr & 0xffff); if (bcount > size) bcount = size; *table++ = cpu_to_le32(addr); @@ -288,7 +289,7 @@ } } -void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) /* __init */ +__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)) { static unsigned long dmatable = 0; static unsigned leftover = 0; @@ -320,74 +321,39 @@ 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 \n", name, dma_base); + new = ide_find_free_region(16 + extra); + hwif->no_autodma = 1; /* default DMA off if we had to configure it here */ + if (new) { + printk("%s: setting dma_base to 0x%04lx\n", name, new); + new |= PCI_BASE_ADDRESS_SPACE_IO; + (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, new); + dma_base = 0; + (void) pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, (unsigned int *) &dma_base); if (dma_base != new) { - printk("%s: operation failed, DMA disabled\n", name); + printk("%s: Operation failed, DMA disabled\n", name); dma_base = 0; } } - dma_base &= ~0xf; } } if (dma_base) { @@ -401,4 +367,3 @@ } return dma_base; } - diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.1.92/linux/drivers/block/ide-pci.c Wed Apr 1 20:11:48 1998 +++ linux/drivers/block/ide-pci.c Thu Apr 2 09:12:22 1998 @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -67,6 +67,13 @@ #define INIT_NS87415 IDE_IGNORE #endif +#ifdef CONFIG_BLK_DEV_CMD646 +extern void ide_init_cmd646(ide_hwif_t *); +#define INIT_CMD646 &ide_init_cmd646 +#else +#define INIT_CMD646 IDE_IGNORE +#endif + #ifdef CONFIG_BLK_DEV_RZ1000 extern void ide_init_rz1000(ide_hwif_t *); #define INIT_RZ1000 &ide_init_rz1000 @@ -99,7 +106,7 @@ {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}} }, {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} }, - {DEVID_CMD646, "CMD646", NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}} }, + {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}} }, {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} }, {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} }, @@ -137,7 +144,7 @@ * Match a PCI IDE port against an entry in ide_hwifs[], * based on io_base port if possible. */ -__initfunc(static ide_hwif_t *ide_match_hwif (unsigned int io_base, const char *name)) +__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char *name)) { int h; ide_hwif_t *hwif; @@ -163,7 +170,7 @@ if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { if (hwif->chipset == ide_unknown) return hwif; /* match */ - printk("%s: port 0x%04x already claimed by %s\n", name, io_base, hwif->name); + printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name); return NULL; /* already claimed */ } } @@ -188,7 +195,7 @@ return NULL; } -__initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *name)) +__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)) { unsigned int base, readback; byte reg, progif = 0; @@ -196,14 +203,14 @@ /* * Place both IDE interfaces into PCI "native" mode: */ - if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) { + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { if ((progif & 0xa) != 0xa) { printk("%s: device not capable of full native PCI mode\n", name); return 1; } printk("%s: placing both ports into native PCI mode\n", name); - (void) pcibios_write_config_byte(bus, fn, 0x09, progif|5); - if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) { + (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); return 1; } @@ -213,9 +220,10 @@ */ if (!(base = ide_find_free_region(32))) return 1; - for (reg = 0x10; reg <= 0x1c; reg += 4, base += 8) { - (void) pcibios_write_config_dword(bus, fn, reg, base|1); - if (pcibios_read_config_dword(bus, fn, reg, &readback) || (readback &= ~1) != base) { + for (reg = 0; reg < 4; reg++, base += 8) { + (void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, base | PCI_BASE_ADDRESS_SPACE_IO); + if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, &readback) || + readback != (base | PCI_BASE_ADDRESS_SPACE_IO)) { printk("%s: readback failed for basereg 0x%02x: wrote 0x%04x, read 0x%x04\n", name, reg, base, readback); return 1; } @@ -233,22 +241,19 @@ * we "know" about, this information is in the ide_pci_device_t struct; * for all other chipsets, we just assume both interfaces are enabled. */ -__initfunc(static void ide_setup_pci_device (byte bus, byte fn, unsigned int ccode, ide_pci_device_t *d)) +__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)) { - unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0; + unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0, pciirq = 0; unsigned short pcicmd = 0, tried_config = 0; - byte tmp = 0, progif = 0, pciirq = 0; + byte tmp = 0; ide_hwif_t *hwif, *mate = NULL; check_if_enabled: - if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd) - || pcibios_read_config_byte(bus, fn, 0x09, &progif) - || pcibios_read_config_byte(bus, fn, 0x3c, &pciirq)) - { + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { printk("%s: error accessing PCI regs\n", d->name); return; } - if (!(pcicmd & 1)) { /* is device disabled? */ + if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ /* * PnP BIOS was *supposed* to have set this device up for us, * but we can do it ourselves, so long as the BIOS has assigned an IRQ @@ -257,9 +262,8 @@ * but we'll eventually ignore it again if no drives respond. */ if (tried_config++ - || ide_setup_pci_baseregs(bus, fn, d->name) - || pcibios_write_config_word(bus, fn, 0x04, pcicmd|1)) - { + || ide_setup_pci_baseregs(dev, d->name) + || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { printk("%s: device disabled (BIOS)\n", d->name); return; } @@ -271,39 +275,47 @@ /* * Can we trust the reported IRQ? */ - if ((ccode >> 16) != PCI_CLASS_STORAGE_IDE || (progif & 5) != 5) { + pciirq = dev->irq; + if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { printk("%s: not 100%% native mode: will probe irqs later\n", d->name); pciirq = 0; } else if (tried_config) { printk("%s: will probe irqs later\n", d->name); pciirq = 0; - } else if (!pciirq || pciirq >= NR_IRQS) { - printk("%s: bad irq from BIOS (%d): will probe later\n", d->name, pciirq); + } else if (!pciirq) { + printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); pciirq = 0; } else { +#ifdef __sparc_v9__ + printk("%s: 100%% native mode on irq %08x\n", d->name, pciirq); +#else printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); +#endif } /* * Set up the IDE ports */ for (port = 0; port <= 1; ++port) { - unsigned int base = 0, ctl = 0; + unsigned long base = 0, ctl = 0; ide_pci_enablebit_t *e = &(d->enablebits[port]); - if (e->reg && (pcibios_read_config_byte(bus, fn, e->reg, &tmp) || (tmp & e->mask) != e->val)) + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ - if (pcibios_read_config_dword(bus, fn, 0x14+(port*8), &ctl) || (ctl &= ~3) == 0) + ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK; + if (!ctl) ctl = port ? 0x374 : 0x3f4; /* use default value */ - if (pcibios_read_config_dword(bus, fn, 0x10+(port*8), &base) || (base &= ~7) == 0) + base = dev->base_address[2*port] & ~7; + + if (!base) base = port ? 0x170 : 0x1f0; /* use default value */ if ((hwif = ide_match_hwif(base, d->name)) == NULL) continue; /* no room in ide_hwifs[] */ if (hwif->io_ports[IDE_DATA_OFFSET] != base) { ide_init_hwif_ports(hwif->io_ports, base, NULL); hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2; + hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; } hwif->chipset = ide_pci; - hwif->pci_bus = bus; - hwif->pci_fn = fn; + hwif->pci_dev = dev; hwif->pci_devid = d->devid; hwif->channel = port; if (!hwif->irq) @@ -315,16 +327,18 @@ if (no_autodma) hwif->no_autodma = 1; #ifdef CONFIG_BLK_DEV_IDEDMA - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || ((ccode >> 16) == PCI_CLASS_STORAGE_IDE && (ccode & 0x8000))) { + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || + ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0; - unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name); - if (dma_base && !(pcicmd & 4)) { + unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name); + if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { /* * Set up BM-DMA capability (PnP BIOS should have done this) */ +printk("%s: %s enabling Bus-Master DMA\n", hwif->name, d->name); hwif->no_autodma = 1; /* default DMA off if we had to configure it here */ - (void) pcibios_write_config_word(bus, fn, 0x04, (pcicmd|4)); - if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd) || !(pcicmd & 4)) { + (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { printk("%s: %s error updating PCICMD\n", hwif->name, d->name); dma_base = 0; } @@ -332,8 +346,7 @@ if (dma_base) ide_setup_dma(hwif, dma_base, 8); else - printk("%s: %s Bus-Master DMA disabled (BIOS), pcicmd=0x%04x, ccode=0x%04x, dma_base=0x%04lx\n", - hwif->name, d->name, pcicmd, ccode, dma_base); + printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ @@ -346,66 +359,32 @@ } /* - * 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); } } } diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c --- v2.1.92/linux/drivers/block/ide-proc.c Wed Apr 1 20:11:48 1998 +++ linux/drivers/block/ide-proc.c Thu Apr 2 09:12:22 1998 @@ -64,7 +64,6 @@ #include #include #include -#include #include #include #include "ide.h" @@ -211,21 +210,22 @@ if (is_pci) { #ifdef CONFIG_BLK_DEV_IDEPCI int rc = 0; + struct pci_dev *dev = hwif->pci_dev; switch (digits) { case 2: msg = "byte"; - rc = pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, reg, val); + rc = pci_write_config_byte(dev, reg, val); break; case 4: msg = "word"; - rc = pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, reg, val); + rc = pci_write_config_word(dev, reg, val); break; case 8: msg = "dword"; - rc = pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, reg, val); + rc = pci_write_config_dword(dev, reg, val); break; } if (rc) { restore_flags(flags); - printk("proc_ide_write_config: error writing %s at bus %d fn %d reg 0x%x value 0x%x\n", - msg, hwif->pci_bus, hwif->pci_fn, reg, val); + printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", + msg, dev->bus->number, dev->devfn, reg, val); printk("proc_ide_write_config: %s\n", pcibios_strerror(rc)); return -EIO; } @@ -259,14 +259,16 @@ 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'); diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.92/linux/drivers/block/ide.c Wed Apr 1 20:11:48 1998 +++ linux/drivers/block/ide.c Thu Apr 2 09:12:22 1998 @@ -107,7 +107,6 @@ #include #include #include -#include #include #include @@ -263,7 +262,7 @@ if (idebus_parameter) system_bus_speed = idebus_parameter; /* user supplied value */ #ifdef CONFIG_PCI - else if (pcibios_present()) + else if (pci_present()) system_bus_speed = 40; /* safe default value for PCI */ #endif /* CONFIG_PCI */ else @@ -1260,6 +1259,12 @@ } while ((hwif = hwif->next) != hwgroup->hwif); } +#ifdef __sparc_v9__ +#define IDE_IRQ_EQUAL(irq1, irq2) (1) +#else +#define IDE_IRQ_EQUAL(irq1, irq2) ((irq1) == (irq2)) +#endif + /* * entry point for all interrupts, caller does __cli() for us */ @@ -1270,25 +1275,28 @@ ide_hwif_t *hwif = hwgroup->hwif; ide_handler_t *handler; - if (!ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET])) + if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET])) return; + do { - if (hwif->irq != irq) disable_irq(hwif->irq); + if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq)) + disable_irq(hwif->irq); } while ((hwif = hwif->next) != hwgroup->hwif); - if (irq == hwif->irq && (handler = hwgroup->handler) != NULL) { + if (IDE_IRQ_EQUAL(irq, hwif->irq) + && (handler = hwgroup->handler) != NULL) { ide_drive_t *drive = hwgroup->drive; -#if 1 /* temporary, remove later -- FIXME */ +#if 1 /* temporary, remove later -- FIXME */ { struct request *rq = hwgroup->rq; if (rq != NULL - &&( MAJOR(rq->rq_dev) != HWIF(drive)->major - || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit)) + &&( MAJOR(rq->rq_dev) != HWIF(drive)->major + || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit)) { printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n"); return; } } -#endif /* temporary */ +#endif /* temporary */ hwgroup->handler = NULL; del_timer(&(hwgroup->timer)); /* if (drive->unmask) @@ -1308,7 +1316,8 @@ __cli(); hwif = hwgroup->hwif; do { - if (hwif->irq != irq) enable_irq(hwif->irq); + if (!IDE_IRQ_EQUAL(hwif->irq, irq)) + enable_irq(hwif->irq); } while ((hwif = hwif->next) != hwgroup->hwif); } @@ -2520,7 +2529,7 @@ __initfunc(static void probe_for_hwifs (void)) { #ifdef CONFIG_PCI - if (pcibios_present()) + if (pci_present()) { #ifdef CONFIG_BLK_DEV_IDEPCI ide_scan_pcibus(); @@ -2530,23 +2539,29 @@ 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)) diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v2.1.92/linux/drivers/block/ide.h Wed Apr 1 20:11:48 1998 +++ linux/drivers/block/ide.h Mon Apr 6 11:50:47 1998 @@ -340,8 +340,7 @@ unsigned reset : 1; /* reset after probe */ unsigned no_autodma : 1; /* don't automatically enable DMA at boot */ byte channel; /* for dual-port chips: 0=primary, 1=secondary */ - byte pci_bus; /* for pci chipsets */ - byte pci_fn; /* for pci chipsets */ + struct pci_dev *pci_dev; /* for pci chipsets */ ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */ #if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */ @@ -723,7 +722,7 @@ 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 diff -u --recursive --new-file v2.1.92/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.92/linux/drivers/block/ll_rw_blk.c Wed Apr 1 20:11:48 1998 +++ linux/drivers/block/ll_rw_blk.c Sun Apr 5 14:11:55 1998 @@ -38,6 +38,15 @@ /* * Protect the request list against multiple users.. + * + * With this spinlock the Linux block IO subsystem is 100% SMP threaded + * from the IRQ event side, and almost 100% SMP threaded from the syscall + * side (we still have protect against block device array operations, and + * the do_request() side is casually still unsafe. The kernel lock protects + * this part currently.). + * + * there is a fair chance that things will work just OK if these functions + * are called with no global kernel lock held ... */ spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED; @@ -106,6 +115,11 @@ return max_sectors[MAJOR(dev)][MINOR(dev)]; } +/* + * Is called with the request spinlock aquired. + * NOTE: the device-specific queue() functions + * have to be atomic! + */ static inline struct request **get_queue(kdev_t dev) { int major = MAJOR(dev); @@ -122,19 +136,27 @@ void unplug_device(void * data) { struct blk_dev_struct * dev = (struct blk_dev_struct *) data; + int queue_new_request=0; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock,flags); if (dev->current_request == &dev->plug) { struct request * next = dev->plug.next; dev->current_request = next; if (next || dev->queue) { dev->plug.next = NULL; - (dev->request_fn)(); + queue_new_request = 1; } } - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock,flags); + + if (queue_new_request) + /* + * request functions are smart enough to notice a change + * in the request queue, calling them without the spinlock + * is OK, i think. <-- FIXME: [is this true? --mingo] + */ + (dev->request_fn)(); } /* @@ -143,6 +165,7 @@ * on the list. * * This is called with interrupts off and no requests on the queue. + * (and with the request spinlock aquired) */ static inline void plug_device(struct blk_dev_struct * dev) { @@ -154,8 +177,8 @@ /* * look for a free request in the first N entries. - * NOTE: interrupts must be disabled on the way in, and will still - * be disabled on the way out. + * NOTE: interrupts must be disabled on the way in (on SMP the request queue + * spinlock has to be aquired), and will still be disabled on the way out. */ static inline struct request * get_request(int n, kdev_t dev) { @@ -191,13 +214,14 @@ { register struct request *req; struct wait_queue wait = { current, NULL }; + unsigned long flags; add_wait_queue(&wait_for_request, &wait); for (;;) { current->state = TASK_UNINTERRUPTIBLE; - cli(); + spin_lock_irqsave(&io_request_lock,flags); req = get_request(n, dev); - sti(); + spin_unlock_irqrestore(&io_request_lock,flags); if (req) break; run_task_queue(&tq_disk); @@ -211,10 +235,11 @@ static inline struct request * get_request_wait(int n, kdev_t dev) { register struct request *req; + unsigned long flags; - cli(); + spin_lock_irqsave(&io_request_lock,flags); req = get_request(n, dev); - sti(); + spin_unlock_irqrestore(&io_request_lock,flags); if (req) return req; return __get_request_wait(n, dev); @@ -261,8 +286,9 @@ /* * add-request adds a request to the linked list. - * It disables interrupts so that it can muck with the - * request-lists in peace. + * It disables interrupts (aquires the request spinlock) so that it can muck + * with the request-lists in peace. Thus it should be called with no spinlocks + * held. * * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA, * which is important for drive_stat_acct() above. @@ -272,6 +298,8 @@ { struct request * tmp, **current_request; short disk_index; + unsigned long flags; + int queue_new_request = 0; switch (MAJOR(req->rq_dev)) { case SCSI_DISK_MAJOR: @@ -292,16 +320,20 @@ } req->next = NULL; + + /* + * We use the goto to reduce locking complexity + */ + spin_lock_irqsave(&io_request_lock,flags); current_request = get_queue(req->rq_dev); - cli(); + if (req->bh) mark_buffer_clean(req->bh); if (!(tmp = *current_request)) { *current_request = req; if (dev->current_request != &dev->plug) - (dev->request_fn)(); - sti(); - return; + queue_new_request = 1; + goto out; } for ( ; tmp->next ; tmp = tmp->next) { if ((IN_ORDER(tmp,req) || @@ -314,11 +346,21 @@ /* for SCSI devices, call request_fn unconditionally */ if (scsi_blk_major(MAJOR(req->rq_dev))) + queue_new_request = 1; +out: + spin_unlock_irqrestore(&io_request_lock,flags); + + /* + * 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)(); - - sti(); } +/* + * 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; diff -u --recursive --new-file v2.1.92/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c --- v2.1.92/linux/drivers/block/ns87415.c Wed Dec 17 11:11:16 1997 +++ linux/drivers/block/ns87415.c Thu Apr 2 09:12:23 1998 @@ -2,6 +2,7 @@ * linux/drivers/block/ns87415.c Version 1.00 December 7, 1997 * * Copyright (C) 1997-1998 Mark Lord + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * Inspired by an earlier effort from David S. Miller (davem@caipfs.rutgers.edu) */ @@ -15,112 +16,12 @@ #include #include #include -#include +#include #include #include "ide.h" -#undef INCLUDE_OBSOLETE_NS87514_STUFF /* define this if you absolutely *need* the timings stuff */ - - -#ifdef INCLUDE_OBSOLETE_NS87514_STUFF -/* - * This part adapted from code from David S. Miller (davem@caipfs.rutgers.edu) - * which was in turn adapted from code from Mark Lord. - * - * Here as a temporary measure only. Will be removed once /proc/ide/ is working. - */ -#include "ide_modes.h" - -static void ns87415_program_modes(ide_drive_t *drive, byte active_count, byte recovery_count) -{ - ide_hwif_t *hwif = HWIF(drive); - byte cfg_reg, regval; - - cfg_reg = (0x44 + (8 * HWIF(drive)->channel) + (4 * drive->select.b.unit)); - - /* set identical PIO timings for read/write */ - regval = (17 - active_count) | ((16 - recovery_count) << 4); - pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg, regval); - pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg + 1, regval); -} - -static void set_ide_modes(ide_drive_t *drive, ide_pio_data_t *d, int bus_speed) -{ - int setup_time, active_time, cycle_time = d->cycle_time; - byte setup_count, active_count, pio_mode = d->pio_mode; - byte recovery_count, recovery_count2, cycle_count; - int recovery_time, clock_time; - - if(pio_mode > 5) - pio_mode = 5; - - setup_time = ide_pio_timings[pio_mode].setup_time; - active_time = ide_pio_timings[pio_mode].active_time; - - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - - cycle_count = (cycle_time + clock_time - 1) / clock_time; - setup_count = (setup_time + clock_time - 1) / clock_time; - active_count = (active_time + clock_time - 1) / clock_time; - - if(active_count < 2) - active_count = 2; - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - - if(recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if(recovery_count < 2) - recovery_count = 2; - if(recovery_count > 17) { - active_count += recovery_count - 17; - recovery_count = 17; - } - - if(active_count > 16) - active_count = 16; - if(recovery_count > 16) - recovery_count = 16; - - printk("active[%d CLKS] recovery[%d CLKS]\n", active_count, recovery_count); - - ns87415_program_modes(drive, active_count, recovery_count); -} - -/* Configure for best PIO mode. */ -static void ns87415_tuneproc (ide_drive_t *drive, byte mode_wanted) -{ - ide_pio_data_t d; - int bus_speed = ide_system_bus_speed(); - - switch(mode_wanted) { - case 6: - case 7: - /* Changes to Fast-devsel are unsupported. */ - return; - - case 8: - case 9: - mode_wanted &= 1; - /* XXX set_prefetch_mode(index, mode_wanted); */ - printk("%s: %sbled NS87415 prefetching...\n", drive->name, mode_wanted ? "en" : "dis"); - return; - }; - - (void) ide_get_best_pio_mode(drive, mode_wanted, 5, &d); - - printk("%s: selected NS87415 PIO mode%d (%dns)%s ", - drive->name, d.pio_mode, d.cycle_time, - d.overridden ? " (overriding vendor mode)" : ""); - - set_ide_modes(drive, &d, bus_speed); -} -#endif /* INCLUDE_OBSOLETE_NS87514_STUFF */ - -static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = {0}; +static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; /* * This routine either enables/disables (according to drive->present) @@ -131,24 +32,29 @@ { ide_hwif_t *hwif = HWIF(drive); unsigned int bit, new, *old = (unsigned int *) hwif->select_data; - unsigned int flags; - - save_flags(flags); - cli(); + struct pci_dev *dev = hwif->pci_dev; + unsigned long flags; + save_flags(flags); cli(); new = *old; /* adjust IRQ enable bit */ bit = 1 << (8 + hwif->channel); - new = drive->present ? (new | bit) : (new & ~bit); + new = drive->present ? (new & ~bit) : (new | bit); /* select PIO or DMA */ bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); new = use_dma ? (new | bit) : (new & ~bit); if (new != *old) { + if (use_dma) { + bit = (1 << (5 + drive->select.b.unit)); + outb((inb(hwif->dma_base+2) & 0x60) | bit, + hwif->dma_base+2); + } + *old = new; - (void) pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, new); + (void) pci_write_config_dword(dev, 0x40, new); } restore_flags(flags); } @@ -167,25 +73,35 @@ { byte dma_stat = inb(hwif->dma_base+2); int rc = (dma_stat & 7) != 4; - outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */ - outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */ - return rc; /* verify good DMA status */ + /* from errata: stop DMA, clear INTR & ERROR */ + outb(7, hwif->dma_base); + /* clear the INTR & ERROR bits */ + outb(dma_stat|6, hwif->dma_base+2); + /* verify good DMA status */ + return rc; } case ide_dma_write: case ide_dma_read: - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - if (!ide_dmaproc(func, drive)) /* use standard DMA stuff */ + /* select DMA xfer */ + ns87415_prepare_drive(drive, 1); + /* use standard DMA stuff */ + if (!ide_dmaproc(func, drive)) return 0; - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ + /* DMA failed: select PIO xfer */ + ns87415_prepare_drive(drive, 0); return 1; default: - return ide_dmaproc(func, drive); /* use standard DMA stuff */ + /* use standard DMA stuff */ + return ide_dmaproc(func, drive); } } __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) { - unsigned int ctrl, progif, using_inta; + struct pci_dev *dev = hwif->pci_dev; + unsigned int ctrl, using_inta; + byte progif, stat; + int timeout; /* * We cannot probe for IRQ: both ports share common IRQ on INTA. @@ -194,35 +110,51 @@ * * 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 */ } diff -u --recursive --new-file v2.1.92/linux/drivers/block/opti621.c linux/drivers/block/opti621.c --- v2.1.92/linux/drivers/block/opti621.c Wed Dec 17 11:11:16 1997 +++ linux/drivers/block/opti621.c Thu Apr 2 09:12:23 1998 @@ -73,8 +73,6 @@ #include #include "ide.h" #include "ide_modes.h" -#include -#include #define OPTI621_MAX_PIO 3 /* In fact, I do not have any PIO 4 drive diff -u --recursive --new-file v2.1.92/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c --- v2.1.92/linux/drivers/block/rz1000.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/block/rz1000.c Thu Apr 2 09:12:23 1998 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "ide.h" @@ -34,10 +33,11 @@ __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 { @@ -50,16 +50,16 @@ #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 { @@ -82,12 +82,12 @@ __initfunc(void ide_probe_for_rz100x (void)) /* called from ide.c */ { - byte index, bus, fn; + struct pci_dev *dev = NULL; - for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, index, &bus, &fn); ++index) - init_rz1000 (bus, fn, "RZ1000"); - for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, index, &bus, &fn); ++index) - init_rz1000 (bus, fn, "RZ1001"); + while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1000, dev)) + init_rz1000 (dev, "RZ1000"); + while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1001, dev)) + init_rz1000 (dev, "RZ1001"); } #endif CONFIG_BLK_DEV_IDEPCI diff -u --recursive --new-file v2.1.92/linux/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c --- v2.1.92/linux/drivers/block/sl82c105.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/sl82c105.c Thu Apr 2 09:12:23 1998 @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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; +} + diff -u --recursive --new-file v2.1.92/linux/drivers/block/trm290.c linux/drivers/block/trm290.c --- v2.1.92/linux/drivers/block/trm290.c Wed Dec 31 16:45:47 1997 +++ linux/drivers/block/trm290.c Thu Apr 2 09:12:23 1998 @@ -133,7 +133,6 @@ #include #include #include -#include #include #include @@ -213,13 +212,14 @@ { 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; diff -u --recursive --new-file v2.1.92/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.1.92/linux/drivers/block/xd.c Sun Jan 4 10:40:15 1998 +++ linux/drivers/block/xd.c Sat Apr 4 09:36:10 1998 @@ -208,6 +208,7 @@ for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++) if (check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) { *controller = j; + xd_type = j; *address = xd_bases[i]; found++; } @@ -705,9 +706,10 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.1.92/linux/drivers/char/Makefile Mon Jan 12 14:46:16 1998 +++ linux/drivers/char/Makefile Sat Apr 4 09:45:13 1998 @@ -20,7 +20,8 @@ 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 diff -u --recursive --new-file v2.1.92/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.1.92/linux/drivers/char/cyclades.c Thu Dec 4 13:09:01 1997 +++ linux/drivers/char/cyclades.c Thu Apr 2 09:12:23 1998 @@ -525,7 +525,6 @@ #include #include #include -#include #include #include @@ -4391,7 +4390,7 @@ cy_detect_pci(void)) { #ifdef CONFIG_PCI - unsigned char cyy_bus, cyy_dev_fn, cyy_rev_id; + unsigned char cyy_rev_id; unsigned long pci_intr_ctrl; unsigned char cy_pci_irq; uclong cy_pci_addr0, cy_pci_addr1, cy_pci_addr2; @@ -4399,20 +4398,17 @@ unsigned short device_id,dev_index = 0,board_index = 0; uclong mailbox; uclong Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0; + struct pci_dev *pdev = NULL; - if(pcibios_present() == 0) { /* PCI bus not present */ + if(pci_present() == 0) { /* PCI bus not present */ return(0); } for (i = 0; i < NR_CARDS; i++) { /* look for a Cyclades card by vendor and device id */ while((device_id = cy_pci_dev_id[dev_index]) != 0) { - if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES, - device_id,board_index, - &cyy_bus, &cyy_dev_fn) != 0) - { + if ((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, device_id, pdev)) == NULL) dev_index++; /* try next device id */ - board_index = 0; - } else { + else { board_index++; break; /* found a board */ } @@ -4422,37 +4418,29 @@ break; /* read PCI configuration area */ - pcibios_read_config_byte(cyy_bus, cyy_dev_fn, - PCI_INTERRUPT_LINE, &cy_pci_irq); - pcibios_read_config_dword(cyy_bus, cyy_dev_fn, - PCI_BASE_ADDRESS_0, - (unsigned int *) &cy_pci_addr0); - pcibios_read_config_dword(cyy_bus, cyy_dev_fn, - PCI_BASE_ADDRESS_1, - (unsigned int *) &cy_pci_addr1); - pcibios_read_config_dword(cyy_bus, cyy_dev_fn, - PCI_BASE_ADDRESS_2, - (unsigned int *) &cy_pci_addr2); - pcibios_read_config_byte(cyy_bus, cyy_dev_fn, - PCI_REVISION_ID, &cyy_rev_id); + cy_pci_irq = pdev->irq; + cy_pci_addr0 = pdev->base_address[0]; + cy_pci_addr1 = pdev->base_address[1]; + cy_pci_addr2 = pdev->base_address[2]; + pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){ #ifdef CY_PCI_DEBUG printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - cyy_bus, cyy_dev_fn); + pdev->bus->number, pdev->devfn); printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n", (ulong)cy_pci_addr2, (ulong)cy_pci_addr1); #endif - cy_pci_addr1 &= 0xfffffffc; - cy_pci_addr2 &= 0xfffffff0; + cy_pci_addr1 &= PCI_BASE_ADDRESS_IO_MASK; + cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK; #if defined(__alpha__) if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - cyy_bus, cyy_dev_fn); + pdev->bus->number, pdev->devfn); printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n", @@ -4537,7 +4525,7 @@ }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){ /* print message */ printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - cyy_bus, cyy_dev_fn); + pdev->bus->number, pdev->devfn); printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", @@ -4547,13 +4535,13 @@ }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ #ifdef CY_PCI_DEBUG printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - cyy_bus, cyy_dev_fn); + pdev->bus->number, pdev->devfn); printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); #endif - cy_pci_addr0 &= 0xfffffff0; + cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK; #if !defined(__alpha__) cy_pci_addr0 = (unsigned int) ioremap( cy_pci_addr0 & PAGE_MASK, @@ -4562,7 +4550,7 @@ #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( diff -u --recursive --new-file v2.1.92/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.1.92/linux/drivers/char/epca.c Tue Mar 10 10:03:31 1998 +++ linux/drivers/char/epca.c Thu Apr 2 09:12:23 1998 @@ -106,7 +106,6 @@ #ifdef ENABLE_PCI -#include #include #include #endif /* ENABLE_PCI */ @@ -1747,7 +1746,7 @@ --------------------------------------------------------------------- */ pci_boards_found = 0; - if (pcibios_present()) + if (pci_present()) { if(num_cards < MAXBOARDS) pci_boards_found += init_PCI(num_cards); @@ -4039,31 +4038,23 @@ #ifdef ENABLE_PCI /* --------------------- Begin get_PCI_configuration ---------------------- */ -int get_PCI_configuration(char bus, char device_fn, +int get_PCI_configuration(char bus, char device_fn, unsigned int *base_addr0, unsigned int *base_addr1, unsigned int *base_addr2, unsigned int *base_addr3, unsigned int *base_addr4, unsigned int *base_addr5) { /* Begin get_PCI_configuration */ - int error; + struct pci_dev *dev = pci_find_slot(bus, device_fn); - error = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, - base_addr0); - - error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, - base_addr1); - - error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, - base_addr2); - - error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_3, - base_addr3); - - error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_4, - base_addr4); + if (!dev) + return(0); - error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_5, - base_addr5); + *base_addr0 = dev->base_address[0]; + *base_addr1 = dev->base_address[1]; + *base_addr2 = dev->base_address[2]; + *base_addr3 = dev->base_address[3]; + *base_addr4 = dev->base_address[4]; + *base_addr5 = dev->base_address[5]; /* ------------------------------------------------------------------------ NOTE - The code below mask out either the 2 or 4 bits dependent on the @@ -4103,11 +4094,6 @@ else (*base_addr5) &= PCI_BASE_ADDRESS_MEM_MASK; - if (error) - { - printk(KERN_ERR " - DIGI PCI error: board not initializing due to error\n"); - return(0); - } return(1); } /* End get_PCI_configuration */ @@ -4311,5 +4297,3 @@ } /* End init_PCI */ #endif /* ENABLE_PCI */ - - diff -u --recursive --new-file v2.1.92/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.1.92/linux/drivers/char/pc_keyb.c Wed Apr 1 20:11:49 1998 +++ linux/drivers/char/pc_keyb.c Wed Apr 1 20:20:03 1998 @@ -24,6 +24,7 @@ #include #include #include +#include /* Some configuration switches are present in the include file... */ @@ -48,12 +49,17 @@ * them. */ -#ifndef __i386__ -#define INIT_KBD +/* + * Some x86 BIOSes do not correctly initializes the keyboard, so the + * "kbd-reset" command line options can be given to force a reset. + * [Ranger] + */ +#ifdef __i386__ + int kbd_startup_reset __initdata = 0; +#else + int kbd_startup_reset __initdata = 1; #endif -#ifdef INIT_KBD - __initfunc(static int kbd_wait_for_input(void)) { int status, data; @@ -202,7 +208,7 @@ printk(KERN_WARNING "initialize_kbd: %s\n", msg); } -#endif /* INIT_KBD */ + unsigned char kbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */ @@ -602,7 +608,11 @@ { 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; } diff -u --recursive --new-file v2.1.92/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.1.92/linux/drivers/char/pty.c Tue Feb 17 13:12:46 1998 +++ linux/drivers/char/pty.c Sat Apr 4 09:45:13 1998 @@ -7,6 +7,9 @@ * -- C. Scott Ananian , 14-Jan-1998 */ +#include +#include /* For EXPORT_SYMBOL */ + #include #include #include @@ -22,6 +25,9 @@ #include #include +#define BUILDING_PTY_C 1 +#include + struct pty_struct { int magic; struct wait_queue * open_wait; @@ -66,6 +72,7 @@ if (tty->driver.subtype == PTY_TYPE_MASTER) { tty_hangup(tty->link); set_bit(TTY_OTHER_CLOSED, &tty->flags); + devpts_pty_kill(MINOR(tty->device) - tty->driver.minor_start); } } @@ -363,6 +370,5 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/drivers/char/rocket.c linux/drivers/char/rocket.c --- v2.1.92/linux/drivers/char/rocket.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/rocket.c Thu Apr 2 09:12:23 1998 @@ -80,7 +80,6 @@ #include #include #ifdef ENABLE_PCI -#include #include #endif #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */ @@ -1875,31 +1874,10 @@ unsigned int aiopio[MAX_AIOPS_PER_BOARD]; char *str; CONTROLLER_t *ctlp; - unsigned short vendor_id, device_id; - int ret, error; - unsigned int port; - - error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, - &vendor_id); - ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, - &device_id); - if (error == 0) - error = ret; - ret = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, - &port); - rcktpt_io_addr[i] = (unsigned long) port; - if (error == 0) - error = ret; - - if (error) { - printk("PCI RocketPort error: %s not initializing due to error" - "reading configuration space\n", - pcibios_strerror(error)); - return(0); - } + struct pci_dev *dev = pci_find_slot(bus, device_fn); - --rcktpt_io_addr[i]; - switch(device_id) { + rcktpt_io_addr[i] = dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + switch(dev->device) { case PCI_DEVICE_ID_RP4QUAD: str = "Quadcable"; max_num_aiops = 1; @@ -1935,7 +1913,7 @@ num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, 0, FREQ_DIS, 0); - printk("Rocketport controller #%d found at %d:%d, " + printk("Rocketport controller #%d found at %02x:%02x, " "%d AIOP(s) (PCI Rocketport %s)\n", i, bus, device_fn, num_aiops, str); if(num_aiops <= 0) { @@ -2095,7 +2073,7 @@ 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 { diff -u --recursive --new-file v2.1.92/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.1.92/linux/drivers/char/stallion.c Thu Mar 26 15:57:03 1998 +++ linux/drivers/char/stallion.c Thu Apr 2 09:12:23 1998 @@ -52,7 +52,6 @@ #ifdef CONFIG_PCI #include -#include #endif /*****************************************************************************/ @@ -466,7 +465,7 @@ #ifdef CONFIG_PCI static inline int stl_findpcibrds(void); -static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr); +static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev); #endif /* @@ -2530,16 +2529,16 @@ * configuration space. */ -static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr) +static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev) { unsigned int bar[4]; stlbrd_t *brdp; - int i, rc; + int i; unsigned char irq; #if DEBUG printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", - brdtype, busnr, devnr); + brdtype, dev->bus->number, dev->devfn); #endif brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t)); @@ -2559,22 +2558,9 @@ * boards use these in different ways, so we just read in the whole * lot and then figure out what is what later. */ - for (i = 0; (i < 4); i++) { - rc = pcibios_read_config_dword(busnr, devnr, - (PCI_BASE_ADDRESS_0 + (i * 0x4)), &bar[i]); - if (rc) { - printk("STALLION: failed to read BAR register %d " - "from PCI board, errno=%x\n", i, rc); - return(0); - } - } - - rc = pcibios_read_config_byte(busnr, devnr, PCI_INTERRUPT_LINE, &irq); - if (rc) { - printk("STALLION: failed to read INTERRUPT register " - "from PCI board, errno=%x\n", rc); - return(0); - } + for (i = 0; (i < 4); i++) + bar[i] = dev->base_address[i]; + irq = dev->irq; #if DEBUG printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__, @@ -2620,24 +2606,18 @@ static inline int stl_findpcibrds() { - unsigned char busnr, devnr; - unsigned short class; - int i, rc, brdtypnr; + struct pci_dev *dev = NULL; + int i, rc; #if DEBUG printk("stl_findpcibrds()\n"); #endif - if (! pcibios_present()) + if (! pci_present()) return(0); - for (i = 0; (i < stl_nrpcibrds); i++) { - for (brdtypnr = 0; ; brdtypnr++) { - - rc = pcibios_find_device(stl_pcibrds[i].vendid, - stl_pcibrds[i].devid, brdtypnr, &busnr, &devnr); - if (rc) - break; + for (i = 0; (i < stl_nrpcibrds); i++) + while ((dev = pci_find_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) { /* * Check that we can handle more boards... @@ -2653,22 +2633,13 @@ * 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); } diff -u --recursive --new-file v2.1.92/linux/drivers/char/tga.c linux/drivers/char/tga.c --- v2.1.92/linux/drivers/char/tga.c Sun Dec 21 17:02:16 1997 +++ linux/drivers/char/tga.c Thu Apr 2 09:12:23 1998 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -137,7 +136,7 @@ #define TGA_F_HEIGHT_PADDED 18 int tga_type; -unsigned int tga_mem_base; +unsigned long tga_mem_base; unsigned long tga_fb_base; unsigned long tga_regs_base; unsigned int tga_bpp, tga_fb_width, tga_fb_height, tga_fb_stride; @@ -472,15 +471,13 @@ __initfunc(void tga_console_init(void)) { - unsigned char pci_bus, pci_devfn; + struct pci_dev *dev; int status; /* * first, find the TGA among the PCI devices... */ - status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, - 0, &pci_bus, &pci_devfn); - if (status == PCIBIOS_DEVICE_NOT_FOUND) { + if (! (dev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL))) /* PANIC!!! */ printk("tga_console_init: TGA not found!!! :-(\n"); return; @@ -489,14 +486,12 @@ /* * read BASE_REG_0 for memory address */ - pcibios_read_config_dword(pci_bus, pci_devfn, - PCI_BASE_ADDRESS_0, &tga_mem_base); - tga_mem_base &= ~15; + tga_mem_base = dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; #ifdef DEBUG - printk("tga_console_init: mem_base 0x%x\n", tga_mem_base); + printk("tga_console_init: mem_base 0x%lx\n", tga_mem_base); #endif /* DEBUG */ - tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f; + tga_type = (readl(tga_mem_base) >> 12) & 0x0f; if (tga_type != 0 && tga_type != 1 && tga_type != 3) { printk("TGA type (0x%x) unrecognized!\n", tga_type); return; @@ -561,9 +556,8 @@ 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 */ diff -u --recursive --new-file v2.1.92/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.92/linux/drivers/char/tty_io.c Wed Apr 1 20:11:49 1998 +++ linux/drivers/char/tty_io.c Sat Apr 4 09:45:14 1998 @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -1209,7 +1210,7 @@ if (device == PTMX_DEV) { /* find a free pty. */ struct tty_driver *driver = tty_drivers; - int minor; + int minor, line; /* find the pty driver */ for (driver=tty_drivers; driver; driver=driver->next) @@ -1229,6 +1230,8 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.1.92/linux/drivers/misc/parport_pc.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/misc/parport_pc.c Sat Apr 4 09:16:49 1998 @@ -458,6 +458,7 @@ static int parport_SPP_supported(struct parport *pb) { /* Do a simple read-write test to make sure the port exists. */ + parport_pc_write_econtrol(pb, 0xc); parport_pc_write_control(pb, 0xc); parport_pc_write_data(pb, 0xaa); if (parport_pc_read_data(pb) != 0xaa) return 0; @@ -894,6 +895,7 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.1.92/linux/drivers/net/3c59x.c Thu Mar 26 15:57:03 1998 +++ linux/drivers/net/3c59x.c Thu Apr 2 09:12:23 1998 @@ -65,7 +65,6 @@ #include #include #include -#include #include #include /* For NR_IRQS only. */ #include @@ -113,6 +112,7 @@ #if LINUX_VERSION_CODE < 0x20115 #define test_and_set_bit(val, addr) set_bit(val, addr) +#include #elif defined(MODULE) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver"); @@ -532,12 +532,18 @@ be best done a central PCI probe dispatch, which wouldn't work well with the current structure. So instead we detect 3Com cards in slot order. */ - if (pcibios_present()) { + if (pci_present()) { static int pci_index = 0; unsigned char pci_bus, pci_device_fn; for (;pci_index < 0xff; pci_index++) { - unsigned char pci_irq_line, pci_latency; +#if LINUX_VERSION_CODE >= 0x20155 + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif + unsigned char pci_latency; unsigned short pci_command, new_command, vendor, device; unsigned int pci_ioaddr; int board_index = 0; @@ -550,10 +556,16 @@ 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. */ diff -u --recursive --new-file v2.1.92/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.1.92/linux/drivers/net/de4x5.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/net/de4x5.c Thu Apr 2 09:12:23 1998 @@ -213,7 +213,7 @@ insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'. - For a compiled in driver, at or above line 526, place e.g. + For a compiled in driver, somewhere in this file, place e.g. #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP" Yes, I know full duplex isn't permissible on BNC or AUI; they're just @@ -390,7 +390,6 @@ #include #include #include -#include #include #include #include @@ -929,7 +928,7 @@ static int get_hw_addr(struct device *dev); static void srom_repair(struct device *dev, int card); static int test_bad_enet(struct device *dev, int status); -#ifndef __sparc_v9__ +#if !defined(__sparc_v9__) && !defined(__powerpc__) static void eisa_probe(struct device *dev, u_long iobase); #endif static void pci_probe(struct device *dev, u_long iobase); @@ -978,12 +977,15 @@ #endif /* MODULE */ static char name[DE4X5_NAME_LENGTH + 1]; -#ifndef __sparc_v9__ +#if !defined(__sparc_v9__) && !defined(__powerpc__) static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; #endif static int num_de4x5s = 0; static int cfrv = 0, useSROM = 0; -static int lastEISA = 0, lastPCI = -1; +#if !defined(__sparc_v9__) && !defined(__powerpc__) +static int lastEISA = 0; +#endif +static int lastPCI = -1; static struct device *lastModule = NULL; /* @@ -1048,7 +1050,7 @@ { u_long iobase = dev->base_addr; -#ifndef __sparc_v9__ +#if !defined(__sparc_v9__) && !defined(__powerpc__) eisa_probe(dev, iobase); #endif pci_probe(dev, iobase); @@ -1094,14 +1096,14 @@ dev->base_addr = iobase; if (lp->bus == EISA) { - printk("%s: %s at 0x%04lx (EISA slot %ld),\n", + printk("%s: %s at 0x%04lx (EISA slot %ld)", dev->name, name, iobase, ((iobase>>12)&0x0f)); } else { /* PCI port address */ - printk("%s: %s at 0x%04lx (PCI bus %d, device %d),\n", dev->name, name, + printk("%s: %s at 0x%04lx (PCI bus %d, device %d)", dev->name, name, iobase, lp->bus_num, lp->device); } - printk(" h/w address "); + printk(", h/w address "); status = get_hw_addr(dev); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ printk("%2.2x:", dev->dev_addr[i]); @@ -1305,9 +1307,8 @@ lp->state = OPEN; de4x5_dbg_open(dev); - if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, - lp->adapter_name, dev)) { + lp->adapter_name, dev)) { printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq); if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ, lp->adapter_name, dev)) { @@ -1974,7 +1975,7 @@ return; } -#ifndef __sparc_v9__ +#if !defined(__sparc_v9__) && !defined(__powerpc__) /* ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** the motherboard. Upto 15 EISA devices are supported. @@ -2063,15 +2064,14 @@ pci_probe(struct device *dev, u_long ioaddr)) { u_char pb, pbus, dev_num, dnum, dev_fn, timer; - u_short vendor, index, status; + u_short dev_id, vendor, index, status; u_int irq = 0, device, class = DE4X5_CLASS_CODE; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ struct bus_type *lp = &bus; - struct pci_dev *pdev; if (lastPCI == NO_MORE_PCI) return; - if (!pcibios_present()) { + if (!pci_present()) { lastPCI = NO_MORE_PCI; return; /* No PCI bus in this machine! */ } @@ -2091,75 +2091,92 @@ (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); + 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); + } - vendor = pdev->vendor; - device = pdev->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); - /* Search for an SROM on this bus */ - if (lp->bus_num != pb) { + /* Set the device number information */ + lp->device = dev_num; lp->bus_num = pb; - srom_search(index); - } - - /* 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 chipset information */ - if (is_DC2114x) device |= (cfrv & CFRV_RN); - lp->chipset = device; + /* Set the chipset information */ + if (is_DC2114x) device |= (cfrv & CFRV_RN); + lp->chipset = device; - /* Get the board I/O address (64 bits on sparc64) */ - iobase = pdev->base_address[0] & CBIO_MASK; + /* Get the board I/O address and IRQ */ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,85) + pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp); + iobase = tmp; + pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq); + irq = tirq; +#else + iobase = pdev->base_address[0]; + irq = pdev->irq; +#endif + iobase &= CBIO_MASK; - /* Fetch the IRQ to be used */ - irq = pdev->irq; - if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; - - /* Check if I/O accesses and Bus Mastering are enabled */ - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); -#ifdef __powerpc__ - if (!(status & PCI_COMMAND_IO)) { - status |= PCI_COMMAND_IO; - pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); + if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; + + /* Check if I/O accesses and Bus Mastering are enabled */ pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - } +#ifdef __powerpc__ + if (!(status & PCI_COMMAND_IO)) { + status |= PCI_COMMAND_IO; + pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); + pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); + } #endif /* __powerpc__ */ - if (!(status & PCI_COMMAND_IO)) continue; + if (!(status & PCI_COMMAND_IO)) continue; - if (!(status & PCI_COMMAND_MASTER)) { - status |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - } - if (!(status & PCI_COMMAND_MASTER)) continue; + if (!(status & PCI_COMMAND_MASTER)) { + status |= PCI_COMMAND_MASTER; + pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); + pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); + } + if (!(status & PCI_COMMAND_MASTER)) continue; - /* Check the latency timer for values >= 0x60 */ - pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer); - if (timer < 0x60) { - pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60); - } + /* Check the latency timer for values >= 0x60 */ + pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer); + if (timer < 0x60) { + pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60); + } - DevicePresent(DE4X5_APROM); - if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { - dev->irq = irq; - if ((status = de4x5_hw_init(dev, iobase)) == 0) { - num_de4x5s++; - if (loading_module) { - link_modules(lastModule, dev); - lastPCI = index; + DevicePresent(DE4X5_APROM); + if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { + dev->irq = irq; + if ((status = de4x5_hw_init(dev, iobase)) == 0) { + num_de4x5s++; + if (loading_module) { + link_modules(lastModule, dev); + lastPCI = index; + } + return; } - return; + } else if (ioaddr != 0) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, + iobase); } - } else if (ioaddr != 0) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, - iobase); } } @@ -2178,24 +2195,35 @@ srom_search(int index)) { u_char pb, dev_fn; - u_short dev_num, vendor, status; + u_short dev_id, dev_num, vendor, status; u_int irq = 0, device, class = DE4X5_CLASS_CODE; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ int i, j; struct bus_type *lp = &bus; - struct pci_dev *pdev; +#ifndef __sparc_v9__ + u_char tirq; + u_int tmp; +#endif for (; (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND); index++) { - +#ifdef __sparc_v9__ + struct pci_dev *pdev; + for (pdev = pci_devices; pdev; pdev = pdev->next) { + if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break; + } +#endif if (lp->bus_num != pb) return; dev_num = PCI_SLOT(dev_fn); - pdev = pci_find_dev(pb, dev_fn); - - vendor = pdev->vendor; - device = pdev->device << 8; - if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; + device = 0; + pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id); + device = dev_id; + device <<= 8; + if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) { + continue; + } /* Get the chip configuration revision register */ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv); @@ -2209,10 +2237,21 @@ lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ - iobase = pdev->base_address[0] & CBIO_MASK; +#ifndef __sparc_v9__ + pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp); + iobase = tmp; +#else + iobase = pdev->base_address[0]; +#endif + iobase &= CBIO_MASK; /* Fetch the IRQ to be used */ +#ifndef __sparc_v9__ + pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq); + irq = tirq; +#else irq = pdev->irq; +#endif if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; /* Check if I/O accesses are enabled */ @@ -4053,6 +4092,19 @@ /* If possible, try to fix a broken card - SMC only so far */ srom_repair(dev, broken); +#ifdef CONFIG_PMAC + /* If the address starts with 00 a0, we have to bit-reverse + each byte of the address. */ + if (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0xa0) { + for (i = 0; i < ETH_ALEN; ++i) { + int x = dev->dev_addr[i]; + x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4); + x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2); + dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); + } + } +#endif /* CONFIG_PMAC */ + /* Test for a bad enet address */ status = test_bad_enet(dev, status); @@ -5713,29 +5765,30 @@ 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; ivendor; - 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++; } diff -u --recursive --new-file v2.1.92/linux/drivers/net/defxx.c linux/drivers/net/defxx.c --- v2.1.92/linux/drivers/net/defxx.c Thu Feb 12 20:56:08 1998 +++ linux/drivers/net/defxx.c Thu Apr 2 09:12:23 1998 @@ -213,7 +213,6 @@ #include #include #include -#include #include #include #include @@ -455,9 +454,8 @@ int i; /* used in for loops */ int version_disp; /* was version info string already displayed? */ int port_len; /* length of port address range (in bytes) */ - u8 pci_bus; /* PCI bus number (0-255) */ - u8 pci_dev_fun; /* PCI device and function numbers (0-255) */ u16 port; /* temporary I/O (port) address */ + struct pci_dev * pdev = NULL; /* PCI device record */ u16 command; /* PCI Configuration space Command register val */ u32 slot_id; /* EISA hardware (slot) ID read from adapter */ DFX_board_t *bp; /* board pointer */ @@ -530,61 +528,58 @@ /* 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 */ + /* Initialize board structure with bus-specific info */ - 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 */ - } + bp = (DFX_board_t *) dev->priv; + bp->dev = dev; + bp->bus_type = DFX_BUS_TYPE_PCI; + bp->pci_dev = pdev; + if (dfx_driver_init(dev) == DFX_K_SUCCESS) + num_boards++; /* only increment global board count on success */ + else + dev->base_addr = 0; /* clear port address field in device structure on failure */ } - else - printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + else + printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + } /* * If we're at this point we're going through dfx_probe() for the first @@ -823,18 +818,19 @@ } 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) */ diff -u --recursive --new-file v2.1.92/linux/drivers/net/defxx.h linux/drivers/net/defxx.h --- v2.1.92/linux/drivers/net/defxx.h Mon Nov 18 01:31:31 1996 +++ linux/drivers/net/defxx.h Thu Apr 2 09:12:23 1998 @@ -1754,8 +1754,7 @@ 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) */ diff -u --recursive --new-file v2.1.92/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.1.92/linux/drivers/net/dgrs.c Tue Mar 10 10:03:32 1998 +++ linux/drivers/net/dgrs.c Thu Apr 2 09:12:23 1998 @@ -87,7 +87,6 @@ #include #include #include -#include #include #include #include @@ -109,6 +108,7 @@ #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 #define IOREMAP(ADDR, LEN) vremap(ADDR, LEN) #define IOUNMAP(ADDR) vfree(ADDR) #define COPY_FROM_USER(DST,SRC,LEN) memcpy_fromfs(DST,SRC,LEN) @@ -1373,14 +1373,19 @@ /* * First, check for PCI boards */ - if (pcibios_present()) + if (pci_present()) { int pci_index = 0; for (; pci_index < 8; pci_index++) { uchar pci_bus, pci_device_fn; +#if LINUX_VERSION_CODE < 0x20100 uchar pci_irq; +#else + uint pci_irq; + struct pci_dev *pdev; +#endif uchar pci_latency; ushort pci_command; @@ -1390,6 +1395,7 @@ &pci_device_fn)) break; +#if LINUX_VERSION_CODE < 0x20100 pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); pcibios_read_config_dword(pci_bus, pci_device_fn, @@ -1398,6 +1404,13 @@ 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; diff -u --recursive --new-file v2.1.92/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.1.92/linux/drivers/net/eepro100.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/net/eepro100.c Thu Apr 2 09:12:23 1998 @@ -59,7 +59,6 @@ #include #include #include -#include #include #include /* Processor type for cache alignment. */ #include @@ -120,6 +119,7 @@ #if (LINUX_VERSION_CODE < 0x20123) #define test_and_set_bit(val, addr) set_bit(val, addr) +#include #endif /* The total I/O port extent of the board. Nominally 0x18, but rounded up @@ -473,10 +473,16 @@ { int cards_found = 0; - if (pcibios_present()) { + if (pci_present()) { static int pci_index = 0; for (; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency; + unsigned char pci_bus, pci_device_fn, pci_latency; +#if (LINUX_VERSION_CODE >= VERSION(2,1,85)) + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif #if (LINUX_VERSION_CODE >= VERSION(1,3,44)) int pci_ioaddr; #else @@ -489,11 +495,17 @@ 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) diff -u --recursive --new-file v2.1.92/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.1.92/linux/drivers/net/hp100.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/net/hp100.c Thu Apr 2 09:12:24 1998 @@ -83,7 +83,6 @@ #include #include #include -#include #include #include @@ -331,6 +330,9 @@ int ioaddr = 0; #ifdef CONFIG_PCI int pci_start_index = 0; +#ifdef LINUX_2_1 + struct pci_dev *pdev; +#endif #endif #ifdef HP100_DEBUG_B @@ -363,7 +365,7 @@ /* at first - scan PCI bus(es) */ #ifdef CONFIG_PCI - if ( pcibios_present() ) + if ( pci_present() ) { int pci_index; @@ -384,8 +386,14 @@ 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. */ diff -u --recursive --new-file v2.1.92/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.1.92/linux/drivers/net/lance.c Thu Feb 12 20:56:08 1998 +++ linux/drivers/net/lance.c Thu Apr 2 09:12:24 1998 @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -285,7 +284,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6}; /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned char pci_irq_line = 0; +static unsigned int pci_irq_line = 0; /* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers. Assume yes until we know the memory size. */ @@ -317,36 +316,26 @@ 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 ) */ - 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); diff -u --recursive --new-file v2.1.92/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.1.92/linux/drivers/net/ne.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/ne.c Thu Apr 2 09:12:24 1998 @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -117,7 +116,7 @@ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned char pci_irq_line = 0; +static unsigned int pci_irq_line = 0; int ne_probe(struct device *dev); static int ne_probe1(struct device *dev, int ioaddr); @@ -182,7 +181,7 @@ #ifdef CONFIG_PCI /* Then look for any installed PCI clones */ - if (pcibios_present() && (ne_probe_pci(dev) == 0)) + if (pci_present() && (ne_probe_pci(dev) == 0)) return 0; #endif @@ -207,27 +206,19 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.1.92/linux/drivers/net/pcnet32.c Thu Feb 12 20:56:09 1998 +++ linux/drivers/net/pcnet32.c Thu Apr 2 09:12:24 1998 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -78,7 +77,7 @@ * in arch/i386/bios32.c * v0.21: added endian conversion for ppc, from work by cort@cs.nmt.edu * v0.22: added printing of status to ring dump - * v0.23: changed enet_statistics to net_devive_stats + * v0.23: changed enet_statistics to net_device_stats */ @@ -172,7 +171,7 @@ __initfunc(int pcnet32_probe (struct device *dev)) { unsigned int ioaddr = dev ? dev->base_addr: 0; - unsigned char irq_line = dev ? dev->irq : 0; + unsigned int irq_line = dev ? dev->irq : 0; int *port; if (ioaddr > 0x1ff) @@ -181,30 +180,20 @@ 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 ) */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); /* Avoid already found cards from previous pcnet32_probe() calls */ if (check_region(ioaddr, PCNET32_TOTAL_SIZE)) @@ -213,8 +202,7 @@ 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; diff -u --recursive --new-file v2.1.92/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.1.92/linux/drivers/net/sunhme.c Thu Feb 12 20:56:09 1998 +++ linux/drivers/net/sunhme.c Thu Apr 2 09:12:24 1998 @@ -45,7 +45,6 @@ #ifdef CONFIG_PCI #include -#include #include #endif @@ -55,7 +54,10 @@ static struct happy_meal *root_happy_dev = NULL; #endif -/* #define HMEDEBUG */ +#undef HMEDEBUG +#undef SXDEBUG +#undef RXDEBUG +#undef TXDEBUG #ifdef HMEDEBUG #define HMD(x) printk x @@ -1584,8 +1586,11 @@ happy_meal_poll_stop(hp, tregs); } -/* #define TXD(x) printk x */ +#ifdef TXDEBUG +#define TXD(x) printk x +#else #define TXD(x) +#endif static inline void happy_meal_tx(struct happy_meal *hp) { @@ -1676,8 +1681,11 @@ TXD((">")); } -/* #define RXD(x) printk x */ +#ifdef RXDEBUG +#define RXD(x) printk x +#else #define RXD(x) +#endif /* Originally I use to handle the allocation failure by just giving back just * that one ring buffer to the happy meal. Problem is that usually when that @@ -1705,7 +1713,7 @@ /* Check for errors. */ if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08lx)]", flags)); + RXD(("ERR(%08x)]", flags)); hp->net_stats.rx_errors++; if(len < ETH_ZLEN) hp->net_stats.rx_length_errors++; @@ -1724,11 +1732,8 @@ } skb = hp->rx_skbs[elem]; #ifdef NEED_DMA_SYNCHRONIZATION -#ifdef CONFIG_PCI - if(!(hp->happy_flags & HFLAG_PCI)) -#endif - mmu_sync_dma(kva_to_hva(hp, skb->data), - skb->len, hp->happy_sbus_dev->my_bus); + mmu_sync_dma(kva_to_hva(hp, skb->data), + skb->len, hp->happy_sbus_dev->my_bus); #endif if(len > RX_COPY_THRESHOLD) { struct sk_buff *new_skb; @@ -1819,7 +1824,7 @@ /* Check for errors. */ if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08lx)]", flags)); + RXD(("ERR(%08x)]", flags)); hp->net_stats.rx_errors++; if(len < ETH_ZLEN) hp->net_stats.rx_length_errors++; @@ -1926,7 +1931,7 @@ /* Check for errors. */ if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08lx)]", flags)); + RXD(("ERR(%08x)]", flags)); hp->net_stats.rx_errors++; if(len < ETH_ZLEN) hp->net_stats.rx_length_errors++; @@ -1975,7 +1980,7 @@ struct hmeal_tcvregs *tregs = hp->tcvregs; unsigned int happy_status = hme_read32(hp, &gregs->stat); - HMD(("happy_meal_interrupt: status=%08lx ", happy_status)); + HMD(("happy_meal_interrupt: status=%08x ", happy_status)); dev->interrupt = 1; @@ -2020,7 +2025,7 @@ struct hmeal_tcvregs *tregs = hp->tcvregs; unsigned int happy_status = readl((unsigned long)&gregs->stat); - HMD(("happy_meal_interrupt: status=%08lx ", happy_status)); + HMD(("happy_meal_interrupt: status=%08x ", happy_status)); dev->interrupt = 1; @@ -2065,7 +2070,7 @@ struct hmeal_tcvregs *tregs = hp->tcvregs; unsigned int happy_status = hme_read32(hp, &gregs->stat); - HMD(("happy_meal_interrupt: status=%08lx ", happy_status)); + HMD(("happy_meal_interrupt: status=%08x ", happy_status)); dev->interrupt = 1; @@ -2181,8 +2186,11 @@ return 0; } -/* #define SXD(x) printk x */ +#ifdef SXDEBUG +#define SXD(x) printk x +#else #define SXD(x) +#endif static int happy_meal_start_xmit(struct sk_buff *skb, struct device *dev) { @@ -2700,19 +2708,20 @@ } } #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 diff -u --recursive --new-file v2.1.92/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.1.92/linux/drivers/net/tlan.c Thu Feb 12 20:56:09 1998 +++ linux/drivers/net/tlan.c Thu Apr 2 09:12:24 1998 @@ -29,7 +29,6 @@ #include "tlan.h" -#include #include #include #include @@ -96,7 +95,7 @@ }; -static int TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * ); +static int TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * ); static int TLan_Init( struct device * ); static int TLan_Open(struct device *dev); static int TLan_StartTx(struct sk_buff *, struct device *); @@ -193,7 +192,7 @@ int failed; int found; u32 io_base; - u8 irq; + int irq; u8 rev; printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n", @@ -319,7 +318,8 @@ static int pad_allocated = 0; int found; TLanPrivateInfo *priv; - u8 bus, dfn, irq, rev; + u8 bus, dfn, rev; + int irq; u32 io_base, dl_ix; found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix ); @@ -398,7 +398,7 @@ * **************************************************************/ -int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix ) +int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix ) { static int dl_index = 0; static int pci_index = 0; @@ -409,7 +409,7 @@ int reg; - if ( ! pcibios_present() ) { + if ( ! pci_present() ) { printk( "TLAN: PCI Bios not present.\n" ); return 0; } @@ -425,6 +425,7 @@ ); if ( ! not_found ) { + struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn); TLAN_DBG( TLAN_DEBUG_GNRL, @@ -433,19 +434,18 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v2.1.92/linux/drivers/net/tulip.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/net/tulip.c Thu Apr 2 09:12:24 1998 @@ -82,7 +82,6 @@ #include #include #include -#include #include /* Processor type for cache alignment. */ #include #include @@ -125,8 +124,10 @@ #include #endif #if (LINUX_VERSION_CODE >= 0x20100) +#ifdef MODULE char kernel_version[] = UTS_RELEASE; #endif +#endif #ifdef SA_SHIRQ #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) #else @@ -135,6 +136,7 @@ #if (LINUX_VERSION_CODE < 0x20123) #define test_and_set_bit(val, addr) set_bit(val, addr) +#include #endif /* This my implementation of shared IRQs, now only used for 1.2.13. */ @@ -453,11 +455,17 @@ well with the current structure. So instead we detect just the Tulip cards in slot order. */ - if (pcibios_present()) { + if (pci_present()) { unsigned char pci_bus, pci_device_fn; for (;pci_index < 0xff; pci_index++) { - unsigned char pci_irq_line, pci_latency; + unsigned char pci_latency; +#if LINUX_VERSION_CODE >= 0x20155 + unsigned int pci_irq_line; + struct pci_dev *pdev; +#else + unsigned char pci_irq_line; +#endif unsigned short pci_command, vendor, device; unsigned int pci_ioaddr, chip_idx = 0; @@ -473,10 +481,16 @@ 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; diff -u --recursive --new-file v2.1.92/linux/drivers/pci/Makefile linux/drivers/pci/Makefile --- v2.1.92/linux/drivers/pci/Makefile Fri Jan 30 11:28:08 1998 +++ linux/drivers/pci/Makefile Thu Apr 2 09:12:24 1998 @@ -9,9 +9,18 @@ # parent makefile. # -L_OBJS := pci.o L_TARGET := pci.a +# Nasty trick as nobody references pcisyms.o, but we still want it linked. +ifeq ($(CONFIG_MODULES),y) +O_TARGET = pci_syms.o +OX_OBJS = pcisyms.o +O_OBJS = pci.o +L_OBJS := pci_syms.o +else +L_OBJS := pci.o +endif + ifdef CONFIG_PROC_FS L_OBJS += proc.o ifdef CONFIG_PCI_OLD_PROC @@ -22,5 +31,7 @@ ifdef CONFIG_PCI_OPTIMIZE L_OBJS += quirks.o endif + +L_OBJS += compat.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.92/linux/drivers/pci/compat.c linux/drivers/pci/compat.c --- v2.1.92/linux/drivers/pci/compat.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/pci/compat.c Thu Apr 2 09:12:24 1998 @@ -0,0 +1,43 @@ +/* + * $Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $ + * + * PCI Bus Services -- Function For Backward Compatibility + * + * Copyright 1998 Martin Mares + */ + +#include +#include +#include + +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; +} diff -u --recursive --new-file v2.1.92/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.1.92/linux/drivers/pci/oldproc.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/pci/oldproc.c Thu Apr 2 09:12:24 1998 @@ -1,5 +1,5 @@ /* - * $Id: oldproc.c,v 1.4 1998/01/05 14:16:18 mj Exp $ + * $Id: oldproc.c,v 1.10 1998/03/15 13:50:11 ecd Exp $ * * Backward-compatible procfs interface for PCI. * @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -220,9 +219,11 @@ DEVICE( OLICOM, OLICOM_OC2183, "OC-2183/2185"), DEVICE( OLICOM, OLICOM_OC2326, "OC-2326"), DEVICE( OLICOM, OLICOM_OC6151, "OC-6151/6152"), - DEVICE( SUN, SUN_EBUS, "EBUS"), - DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal"), + DEVICE( SUN, SUN_EBUS, "PCI-EBus Bridge"), + DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal Ethernet"), + DEVICE( SUN, SUN_SIMBA, "Advanced PCI Bridge"), DEVICE( SUN, SUN_PBM, "PCI Bus Module"), + DEVICE( SUN, SUN_SABRE, "Ultra IIi PCI"), DEVICE( CMD, CMD_640, "640 (buggy)"), DEVICE( CMD, CMD_643, "643"), DEVICE( CMD, CMD_646, "646"), @@ -273,6 +274,8 @@ DEVICE( ASP, ASP_ABP940UW, "ABP940UW"), DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"), DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)"), + DEVICE( CERN, CERN_HIPPI_DST, "HIPPI destination"), + DEVICE( CERN, CERN_HIPPI_SRC, "HIPPI source"), DEVICE( IMS, IMS_8849, "8849"), DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"), DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe"), @@ -378,6 +381,7 @@ 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"), diff -u --recursive --new-file v2.1.92/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.92/linux/drivers/pci/pci.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/pci/pci.c Mon Apr 6 14:01:34 1998 @@ -1,42 +1,28 @@ /* - * $Id: pci.c,v 1.55 1997/12/27 12:17:54 mj Exp $ + * $Id: pci.c,v 1.71 1998/03/30 11:14:35 mj Exp $ * - * PCI services that are built on top of the BIOS32 service. + * PCI Bus Services * - * Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter, + * Copyright 1993 -- 1998 Drew Eckhardt, Frederic Potter, * David Mosberger-Tang, Martin Mares */ #include #include #include -#include #include #include #include +#include #include struct pci_bus pci_root; -struct pci_dev *pci_devices = 0; +struct pci_dev *pci_devices = NULL; +static struct pci_dev **pci_last_dev_p = &pci_devices; #undef DEBUG -/* - * pci_malloc() returns initialized memory of size SIZE. Can be - * used only while pci_init() is active. - */ -__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp)) -{ - void *mem; - - mem = (void*) *mem_startp; - *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); - memset(mem, 0, size); - return mem; -} - - const char *pcibios_strerror(int error) { static char buf[32]; @@ -68,7 +54,45 @@ } -unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp) +struct pci_dev * +pci_find_slot(unsigned int bus, unsigned int devfn) +{ + struct pci_dev *dev; + + for(dev=pci_devices; dev; dev=dev->next) + if (dev->bus->number == bus && dev->devfn == devfn) + break; + return dev; +} + + +struct pci_dev * +pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from) +{ + if (!from) + from = pci_devices; + else + from = from->next; + while (from && (from->vendor != vendor || from->device != device)) + from = from->next; + return from; +} + + +struct pci_dev * +pci_find_class(unsigned int class, struct pci_dev *from) +{ + if (!from) + from = pci_devices; + else + from = from->next; + while (from && from->class != class) + from = from->next; + return from; +} + + +__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus)) { unsigned int devfn, l, max, class; unsigned char cmd, irq, tmp, hdr_type, is_multi = 0; @@ -97,7 +121,8 @@ continue; } - dev = pci_malloc(sizeof(*dev), mem_startp); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + memset(dev, 0, sizeof(*dev)); dev->bus = bus; dev->devfn = devfn; dev->vendor = l & 0xffff; @@ -113,13 +138,19 @@ pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class); class >>= 8; /* upper 3 bytes */ dev->class = class; + dev->hdr_type = hdr_type; switch (hdr_type & 0x7f) { /* header type */ - case 0: /* standard header */ + case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class >> 8 == PCI_CLASS_BRIDGE_PCI) goto bad; - /* read irq level (may be changed during pcibios_fixup()): */ - pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); + /* + * If the card generates interrupts, read IRQ number + * (some architectures change it during pcibios_fixup()) + */ + pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); + if (irq) + pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); dev->irq = irq; /* * read base address registers, again pcibios_fixup() can @@ -130,7 +161,7 @@ dev->base_address[reg] = (l == 0xffffffff) ? 0 : l; } break; - case 1: /* bridge header */ + case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ if (class >> 8 != PCI_CLASS_BRIDGE_PCI) goto bad; for (reg = 0; reg < 2; reg++) { @@ -138,6 +169,14 @@ dev->base_address[reg] = (l == 0xffffffff) ? 0 : l; } break; + case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ + if (class >> 16 != PCI_BASE_CLASS_BRIDGE) + goto bad; + for (reg = 0; reg < 2; reg++) { + pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l); + dev->base_address[reg] = (l == 0xffffffff) ? 0 : l; + } + break; default: /* unknown header */ bad: printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", @@ -154,8 +193,8 @@ * Put it into the global PCI device chain. It's used to * find devices once everything is set up. */ - dev->next = pci_devices; - pci_devices = dev; + *pci_last_dev_p = dev; + pci_last_dev_p = &dev->next; /* * Now insert it into the list of devices held @@ -174,7 +213,8 @@ /* * Insert it into the tree of buses. */ - child = pci_malloc(sizeof(*child), mem_startp); + child = kmalloc(sizeof(*child), GFP_ATOMIC); + memset(child, 0, sizeof(*child)); child->next = bus->children; bus->children = child; child->self = dev; @@ -203,11 +243,14 @@ pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); if ((buses & 0xFFFFFF) != 0) { + unsigned int cmax; + child->primary = buses & 0xFF; child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->number = child->secondary; - max = pci_scan_bus(child, mem_startp); + cmax = pci_scan_bus(child); + if (cmax > max) max = cmax; } else { @@ -223,7 +266,7 @@ /* * Now we can scan all subordinate buses: */ - max = pci_scan_bus(child, mem_startp); + max = pci_scan_bus(child); /* * Set the subordinate bus number to its real * value: @@ -250,36 +293,31 @@ } -__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end)) +__initfunc(void pci_init(void)) { - mem_start = pcibios_init(mem_start, mem_end); + pcibios_init(); - if (!pcibios_present()) { + if (!pci_present()) { printk("PCI: No PCI bus detected\n"); - return mem_start; } - printk("Probing PCI hardware.\n"); + printk("PCI: Probing PCI hardware.\n"); memset(&pci_root, 0, sizeof(pci_root)); - pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start); + pci_root.subordinate = pci_scan_bus(&pci_root); /* give BIOS a chance to apply platform specific fixes: */ - mem_start = pcibios_fixup(mem_start, mem_end); + pcibios_fixup(); #ifdef CONFIG_PCI_OPTIMIZE pci_quirks_init(); #endif - - return mem_start; } -struct pci_dev *pci_find_dev(unsigned char bus, unsigned char devfn) -{ - struct pci_dev *pdev; - for (pdev = pci_devices; pdev; pdev = pdev->next) { - if ((pdev->bus->number==bus) && (pdev->devfn==devfn)) break; - } - return pdev; +__initfunc(void pci_setup (char *str, int *ints)) +{ + str = pcibios_setup(str); + if (*str) + printk(KERN_ERR "PCI: Unknown option `%s'\n", str); } diff -u --recursive --new-file v2.1.92/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c --- v2.1.92/linux/drivers/pci/pcisyms.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/pci/pcisyms.c Thu Apr 2 09:12:24 1998 @@ -0,0 +1,28 @@ +/* + * $Id: pcisyms.c,v 1.2 1998/02/16 10:35:57 mj Exp $ + * + * PCI Bus Services -- Exported Symbols + * + * Copyright 1998 Martin Mares + */ + +#include +#include + +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); diff -u --recursive --new-file v2.1.92/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.1.92/linux/drivers/pci/proc.c Mon Feb 23 18:12:06 1998 +++ linux/drivers/pci/proc.c Thu Apr 2 09:12:24 1998 @@ -1,14 +1,13 @@ /* - * $Id: proc.c,v 1.1 1997/12/22 17:22:31 mj Exp $ + * $Id: proc.c,v 1.8 1998/03/12 14:32:51 mj Exp $ * * Procfs interface for the PCI bus. * - * Copyright (c) 1997 Martin Mares + * Copyright (c) 1997, 1998 Martin Mares */ #include #include -#include #include #include #include @@ -49,14 +48,27 @@ int pos = *ppos; unsigned char bus = dev->bus->number; unsigned char dfn = dev->devfn; - int cnt; + int cnt, size; - if (pos >= PCI_CFG_SPACE_SIZE) + /* + * Normal users can read only the standardized portion of the + * configuration space as several chips lock up when trying to read + * undefined locations (think of Intel PIIX4 as a typical example). + */ + + if (fsuser()) + size = PCI_CFG_SPACE_SIZE; + else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + size = 128; + else + size = 64; + + if (pos >= size) return 0; - if (nbytes >= PCI_CFG_SPACE_SIZE) - nbytes = PCI_CFG_SPACE_SIZE; - if (pos + nbytes > PCI_CFG_SPACE_SIZE) - nbytes = PCI_CFG_SPACE_SIZE - pos; + if (nbytes >= size) + nbytes = size; + if (pos + nbytes > size) + nbytes = size - pos; cnt = nbytes; if (!access_ok(VERIFY_WRITE, buf, cnt)) @@ -260,16 +272,9 @@ get_pci_dev_info }; -__initfunc(void proc_bus_pci_init(void)) +__initfunc(void proc_bus_pci_add(struct pci_bus *bus, struct proc_dir_entry *proc_pci)) { - struct proc_dir_entry *proc_pci; - struct pci_bus *bus; - - if (!pcibios_present()) - return; - proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus); - proc_register(proc_pci, &proc_pci_devices); - for(bus = &pci_root; bus; bus = bus->next) { + while (bus) { char name[16]; struct proc_dir_entry *de; struct pci_dev *dev; @@ -287,5 +292,19 @@ 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); } diff -u --recursive --new-file v2.1.92/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c --- v2.1.92/linux/drivers/pci/quirks.c Sun Dec 21 17:27:18 1997 +++ linux/drivers/pci/quirks.c Thu Apr 2 09:12:24 1998 @@ -1,5 +1,5 @@ /* - * $Id: quirks.c,v 1.2 1997/09/20 21:43:34 davem Exp $ + * $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $ * * PCI Chipset-Specific Quirks * @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c --- v2.1.92/linux/drivers/scsi/53c7,8xx.c Fri Jan 23 18:10:31 1998 +++ linux/drivers/scsi/53c7,8xx.c Thu Apr 2 09:12:24 1998 @@ -243,7 +243,6 @@ #include #include #include -#include #include #include #include @@ -1413,53 +1412,47 @@ __initfunc(static int ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, unsigned char bus, unsigned char device_fn, long long options)) { - unsigned short vendor_id, device_id, command; + unsigned short command; #ifdef LINUX_1_2 unsigned long #else unsigned int #endif base, io_port; - unsigned char irq, revision; + unsigned char revision; int error, expected_chip; int expected_id = -1, max_revision = -1, min_revision = -1; - int i; + int i, irq; + struct pci_dev *pdev = pci_find_slot(bus, device_fn); printk("scsi-ncr53c7,8xx : at PCI bus %d, device %d, function %d\n", bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); - if (!pcibios_present()) { - printk("scsi-ncr53c7,8xx : not initializing due to lack of PCI BIOS,\n" + if (!pdev) { + printk("scsi-ncr53c7,8xx : not initializing -- PCI device not found,\n" " try using memory, port, irq override instead.\n"); return -1; } - if ((error = pcibios_read_config_word (bus, device_fn, PCI_VENDOR_ID, - &vendor_id)) || - (error = pcibios_read_config_word (bus, device_fn, PCI_DEVICE_ID, - &device_id)) || - (error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, + if ((error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, &command)) || - (error = pcibios_read_config_dword (bus, device_fn, - PCI_BASE_ADDRESS_0, &io_port)) || - (error = pcibios_read_config_dword (bus, device_fn, - PCI_BASE_ADDRESS_1, &base)) || (error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION, - &revision)) || - (error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE, - &irq))) { + &revision))) { printk ("scsi-ncr53c7,8xx : error %s not initializing due to error reading configuration space\n" " perhaps you specified an incorrect PCI bus, device, or function.\n" , pcibios_strerror(error)); return -1; } + io_port = pdev->base_address[0]; + base = pdev->base_address[1]; + irq = pdev->irq; /* If any one ever clones the NCR chips, this will have to change */ - if (vendor_id != PCI_VENDOR_ID_NCR) { + if (pdev->vendor != PCI_VENDOR_ID_NCR) { printk ("scsi-ncr53c7,8xx : not initializing, 0x%04x is not NCR vendor ID\n", - (int) vendor_id); + (int) pdev->vendor); return -1; } @@ -1467,14 +1460,16 @@ if ( ! (command & PCI_COMMAND_MASTER)) { printk("SCSI: PCI Master Bit has not been set. Setting...\n"); command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO; - pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); - if (io_port >= 0x10000000) { + pci_write_config_word(pdev, PCI_COMMAND, command); + + if (io_port >= 0x10000000 && is_prep ) { /* Mapping on PowerPC can't handle this! */ unsigned long new_io_port; new_io_port = (io_port & 0x00FFFFFF) | 0x01000000; printk("SCSI: I/O moved from %08X to %08x\n", io_port, new_io_port); io_port = new_io_port; - pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port); + pdev->base_address[0] = io_port; } } #endif @@ -1519,7 +1514,7 @@ } for (i = 0; i < NPCI_CHIP_IDS; ++i) { - if (device_id == pci_chip_ids[i].pci_device_id) { + if (pdev->device == pci_chip_ids[i].pci_device_id) { max_revision = pci_chip_ids[i].max_revision; min_revision = pci_chip_ids[i].min_revision; expected_chip = pci_chip_ids[i].chip; @@ -1528,10 +1523,10 @@ expected_id = pci_chip_ids[i].pci_device_id; } - if (chip && device_id != expected_id) + if (chip && pdev->device != expected_id) printk ("scsi-ncr53c7,8xx : warning : device id of 0x%04x doesn't\n" " match expected 0x%04x\n", - (unsigned int) device_id, (unsigned int) expected_id ); + (unsigned int) pdev->device, (unsigned int) expected_id ); if (max_revision != -1 && revision > max_revision) printk ("scsi-ncr53c7,8xx : warning : revision of %d is greater than %d.\n", @@ -1598,7 +1593,7 @@ } } - 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, diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c --- v2.1.92/linux/drivers/scsi/53c7xx.c Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/53c7xx.c Thu Apr 2 09:12:24 1998 @@ -244,8 +244,6 @@ #include #include #include -#include -#include #include #include #include @@ -670,6 +668,7 @@ return h; } +#if 0 /* * Function : request_synchronous (int host, int target) * @@ -717,6 +716,7 @@ restore_flags(flags); return 0; } +#endif /* * Function : request_disconnect (int host, int on_or_off) @@ -1121,16 +1121,12 @@ /* * 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 * diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7xx.h linux/drivers/scsi/53c7xx.h --- v2.1.92/linux/drivers/scsi/53c7xx.h Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/53c7xx.h Thu Apr 2 09:12:24 1998 @@ -1247,14 +1247,6 @@ 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 diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c --- v2.1.92/linux/drivers/scsi/AM53C974.c Sun Dec 21 17:04:48 1997 +++ linux/drivers/scsi/AM53C974.c Thu Apr 2 09:12:25 1998 @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -35,6 +34,8 @@ * Robin Cutshaw (robin@xfree86.org) and is used here in a * slightly modified form. * + * PCI detection rewritten by Martin Mares + * * For the remaining code: * Copyright 1994, D. Frieauff * EMail: fri@rsx42sun0.dofn.de @@ -189,23 +190,6 @@ #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 */ -#ifndef PCI_VENDOR_ID_AMD -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_DEVICE_ID_AMD_SCSI 0x2020 -#endif -#define PCI_BASE_MASK 0xFFFFFFE0 -#define PCI_COMMAND_PERREN 0x40 -#define PCI_SCRATCH_REG_0 0x40 /* 16 bits */ -#define PCI_SCRATCH_REG_1 0x42 /* 16 bits */ -#define PCI_SCRATCH_REG_2 0x44 /* 16 bits */ -#define PCI_SCRATCH_REG_3 0x46 /* 16 bits */ -#define PCI_SCRATCH_REG_4 0x48 /* 16 bits */ -#define PCI_SCRATCH_REG_5 0x4A /* 16 bits */ -#define PCI_SCRATCH_REG_6 0x4C /* 16 bits */ -#define PCI_SCRATCH_REG_7 0x4E /* 16 bits */ - /*** SCSI block ***/ #define CTCLREG 0x00 /* r current transf. count, low byte */ #define CTCMREG 0x04 /* r current transf. count, middle byte */ @@ -363,108 +347,15 @@ int max_offset; /* max. sync. offset, 0 = asynchronous */ } override_t; -/************ PCI stuff *************/ -#define AM53C974_PCIREG_OPEN() outb(0xF1, 0xCF8); outb(0, 0xCFA) -#define AM53C974_PCIREG_CLOSE() outb(0, 0xCF8) -#define AM53C974_PCIREG_READ_BYTE(instance,a) ( inb((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_READ_WORD(instance,a) ( inw((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_READ_DWORD(instance,a) ( inl((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_BYTE(instance,x,a) ( outb((x), (a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_WORD(instance,x,a) ( outw((x), (a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_DWORD(instance,x,a) ( outl((x), (a) + (instance)->io_port) ) - -typedef struct _pci_config_t { - /* start of official PCI config space header */ - union { - unsigned int device_vendor; - struct { - unsigned short vendor; - unsigned short device; - } dv; - } dv_id; -#define _device_vendor dv_id.device_vendor -#define _vendor dv_id.dv.vendor -#define _device dv_id.dv.device - union { - unsigned int status_command; - struct { - unsigned short command; - unsigned short status; - } sc; - } stat_cmd; -#define _status_command stat_cmd.status_command -#define _command stat_cmd.sc.command -#define _status stat_cmd.sc.status - union { - unsigned int class_revision; - struct { - unsigned char rev_id; - unsigned char prog_if; - unsigned char sub_class; - unsigned char base_class; - } cr; - } class_rev; -#define _class_revision class_rev.class_revision -#define _rev_id class_rev.cr.rev_id -#define _prog_if class_rev.cr.prog_if -#define _sub_class class_rev.cr.sub_class -#define _base_class class_rev.cr.base_class - union { - unsigned int bist_header_latency_cache; - struct { - unsigned char cache_line_size; - unsigned char latency_timer; - unsigned char header_type; - unsigned char bist; - } bhlc; - } bhlc; -#define _bist_header_latency_cache bhlc.bist_header_latency_cache -#define _cache_line_size bhlc.bhlc.cache_line_size -#define _latency_timer bhlc.bhlc.latency_timer -#define _header_type bhlc.bhlc.header_type -#define _bist bhlc.bhlc.bist - unsigned int _base0; - unsigned int _base1; - unsigned int _base2; - unsigned int _base3; - unsigned int _base4; - unsigned int _base5; - unsigned int rsvd1; - unsigned int rsvd2; - unsigned int _baserom; - unsigned int rsvd3; - unsigned int rsvd4; - union { - unsigned int max_min_ipin_iline; - struct { - unsigned char int_line; - unsigned char int_pin; - unsigned char min_gnt; - unsigned char max_lat; - } mmii; - } mmii; -#define _max_min_ipin_iline mmii.max_min_ipin_iline -#define _int_line mmii.mmii.int_line -#define _int_pin mmii.mmii.int_pin -#define _min_gnt mmii.mmii.min_gnt -#define _max_lat mmii.mmii.max_lat - /* end of official PCI config space header */ - unsigned short _ioaddr; /* config type 1 - private I/O addr */ - unsigned int _pcibus; /* config type 2 - private bus id */ - unsigned int _cardnum; /* config type 2 - private card number */ -} pci_config_t; - #ifdef AM53C974_DEBUG -static void AM53C974_print_pci(struct Scsi_Host *instance); static void AM53C974_print_phase(struct Scsi_Host *instance); static void AM53C974_print_queues(struct Scsi_Host *instance); #endif /* AM53C974_DEBUG */ static void AM53C974_print(struct Scsi_Host *instance); static void AM53C974_keywait(void); -static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt); -static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt); -static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config); +static __inline__ int AM53C974_pci_detect(Scsi_Host_Template *tpnt); +static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev); static void AM53C974_config_after_reset(struct Scsi_Host *instance); static __inline__ void initialize_SCp(Scsi_Cmnd *cmd); static __inline__ void run_main(void); @@ -502,52 +393,6 @@ #ifdef AM53C974_DEBUG static int deb_stop = 1; -/************************************************************************** - * Function : void AM53C974_print_pci(struct Scsi_Host *instance) - * - * Purpose : dump the PCI registers for debugging purposes - * - * Input : instance - which AM53C974 - **************************************************************************/ -static void AM53C974_print_pci(struct Scsi_Host *instance) -{ -int i; -unsigned short vendor_id, device_id, command, status, scratch[8]; -unsigned long class_revision, base; -unsigned char irq, cache_line_size, latency_timer, header_type; - -AM53C974_PCIREG_OPEN(); - -for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i); -vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID); -device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID); -command = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND); -status = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS); -class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION); -cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE); -latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER); -header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE); -base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0); -irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE); - -AM53C974_PCIREG_CLOSE(); - - -printk("------------- start of PCI register dump -------------\n"); -printk("PCI_VENDOR_ID: 0x%x\n", vendor_id); -printk("PCI_DEVICE_ID: 0x%x\n", device_id); -printk("PCI_COMMAND: 0x%x\n", command); -printk("PCI_STATUS: 0x%x\n", status); -printk("PCI_CLASS_REVISION: 0x%lx\n", class_revision); -printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size); -printk("PCI_LATENCY_TIMER: 0x%x\n", latency_timer); -printk("PCI_HEADER_TYPE: 0x%x\n", header_type); -printk("PCI_BASE_ADDRESS_0: 0x%lx\n", base); -printk("PCI_INTERRUPT_LINE: %d\n", irq); -for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d: 0x%x\n", i, scratch[i]); -printk("------------- end of PCI register dump -------------\n\n"); -} - static struct { unsigned char value; char *name; @@ -732,7 +577,7 @@ #if defined (CONFIG_PCI) /************************************************************************** -* Function : int AM53C974_bios_detect(Scsi_Host_Template *tpnt) +* Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt) * * Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios * @@ -740,161 +585,34 @@ * * 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; +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); -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; - /* 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 ) */ - 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 */ - 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 */ - 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) * * Purpose : detects and initializes AM53C974 SCSI chips @@ -905,21 +623,19 @@ **************************************************************************/ __initfunc(int AM53C974_detect(Scsi_Host_Template *tpnt)) { -int count; /* number of boards detected */ +int count = 0; /* number of boards detected */ tpnt->proc_dir = &proc_scsi_am53c974; #if defined (CONFIG_PCI) -if (pcibios_present()) - count = AM53C974_bios_detect(tpnt); - else +if (pci_present()) + count = AM53C974_pci_detect(tpnt); #endif -count = AM53C974_nobios_detect(tpnt); return (count); } /************************************************************************** -* Function : int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config) +* Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev) * * Purpose : initializes instance and corresponding AM53/79C974 chip, * @@ -932,7 +648,7 @@ * set up by the BIOS (as reflected by contents of register CNTLREG1). * This is the only BIOS assistance we need. **************************************************************************/ -__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config)) +__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev)) { AM53C974_local_declare(); int i, j; @@ -947,9 +663,8 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/README.in2000 linux/drivers/scsi/README.in2000 --- v2.1.92/linux/drivers/scsi/README.in2000 Thu Jul 17 20:24:38 1997 +++ linux/drivers/scsi/README.in2000 Wed Apr 1 20:41:12 1998 @@ -1,4 +1,11 @@ +UPDATE NEWS: version 1.32 - 28 Mar 98 + + Removed the check for legal IN2000 hardware versions: + It appears that the driver works fine with serial + EPROMs (the 8-pin chip that defines hardware rev) as + old as 2.1, so we'll assume that all cards are OK. + UPDATE NEWS: version 1.31 - 6 Jul 97 Fixed a bug that caused incorrect SCSI status bytes to be diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.1.92/linux/drivers/scsi/aic7xxx.c Sun Jan 4 10:55:09 1998 +++ linux/drivers/scsi/aic7xxx.c Thu Apr 2 09:12:25 1998 @@ -107,7 +107,6 @@ #include #include #include -#include #include #include #include @@ -626,49 +625,6 @@ #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 * addresses to physical addresses. @@ -746,11 +702,11 @@ struct aic7xxx_scb *q_next; /* next scb in queue */ scb_flag_type flags; /* current state of scb */ struct hw_scatterlist *sg_list; /* SG list in adapter format */ - unsigned char sg_count; unsigned char sense_cmd[6]; /* * Allocate 6 characters for * sense command. */ + unsigned char sg_count; }; /* @@ -792,13 +748,14 @@ */ struct aic7xxx_host { struct Scsi_Host *host; /* pointer to scsi host */ + struct aic7xxx_host *next; /* pointer to next aic7xxx device */ int host_no; /* SCSI host number */ int instance; /* aic7xxx instance number */ int scsi_id; /* host adapter SCSI ID */ int scsi_id_b; /* channel B for twin adapters */ int irq; /* IRQ for this adapter */ - int base; /* card base address */ - unsigned int mbase; /* I/O memory address */ + unsigned long base; /* card base address */ + unsigned long mbase; /* I/O memory address */ volatile unsigned char *maddr; /* memory mapped address */ #define A_SCANNED 0x0001 #define B_SCANNED 0x0002 @@ -833,7 +790,6 @@ unsigned char qfullcount; unsigned char cmdoutcnt; unsigned char curqincnt; - struct Scsi_Host *next; /* allow for multiple IRQs */ unsigned char activescbs; /* active scbs */ scb_queue_type waiting_scbs; /* * SCBs waiting for space in @@ -923,15 +879,15 @@ hscb->control, hscb->target_channel_lun, hscb->SCSI_cmd_length, - hscb->SCSI_cmd_pointer ); + le32_to_cpu(hscb->SCSI_cmd_pointer) ); printk(" datlen:%d data:0x%lx segs:0x%x segp:0x%lx\n", - hscb->data_count, - hscb->data_pointer, + le32_to_cpu(hscb->data_count), + le32_to_cpu(hscb->data_pointer), hscb->SG_segment_count, - hscb->SG_list_pointer); + le32_to_cpu(hscb->SG_list_pointer)); printk(" sg_addr:%lx sg_len:%ld\n", - hscb->sg_list[0].address, - hscb->sg_list[0].length); + le32_to_cpu(hscb->sg_list[0].address), + le32_to_cpu(hscb->sg_list[0].length)); } #endif @@ -963,6 +919,7 @@ */ static int aic7xxx_enable_ultra = 0; /* enable ultra SCSI speeds */ static int aic7xxx_verbose = 0; /* verbose messages */ +static struct aic7xxx_host *first_aic7xxx = NULL; /* list of all our devices */ /**************************************************************************** @@ -995,7 +952,7 @@ { if (p->maddr != NULL) { -#ifdef __alpha__ +#if defined(__alpha__) || defined(__sparc_v9__) || defined(__powerpc__) int i; for (i=0; i < size; i++) @@ -2300,7 +2257,7 @@ busy_scb = p->scb_data->scb_array[busy_scbid]; - next_scbid = busy_scb->hscb->data_count >> 24; + next_scbid = le32_to_cpu(busy_scb->hscb->data_count) >> 24; if (next_scbid == SCB_LIST_NULL) { @@ -2492,8 +2449,12 @@ static void aic7xxx_reset_current_bus(struct aic7xxx_host *p) { + unsigned long processor_flags; unsigned char scsiseq; + save_flags(processor_flags); + cli(); + /* Disable reset interrupts. */ outb(inb(p->base + SIMODE1) & ~ENSCSIRST, p->base + SIMODE1); @@ -2512,6 +2473,8 @@ outb(inb(p->base + SIMODE1) | ENSCSIRST, p->base + SIMODE1); udelay(1000); + + restore_flags(processor_flags); } /*+F************************************************************************* @@ -3257,8 +3220,8 @@ if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL)) { printk(KERN_WARNING "scsi%d: Referenced SCB not valid during " - "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%x.\n", p->host_no, - intstat, scb_index, scb->flags, (unsigned int) scb->cmd); + "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%lx.\n", p->host_no, + intstat, scb_index, scb->flags, (unsigned long) scb->cmd); } else { @@ -3294,8 +3257,8 @@ scb->sense_cmd[1] = (cmd->lun << 5); scb->sense_cmd[4] = sizeof(cmd->sense_buffer); - scb->sg_list[0].address = VIRT_TO_BUS(&cmd->sense_buffer); - scb->sg_list[0].length = sizeof(cmd->sense_buffer); + scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(&cmd->sense_buffer)); + scb->sg_list[0].length = cpu_to_le32(sizeof(cmd->sense_buffer)); cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); /* @@ -3308,18 +3271,15 @@ hscb->SG_segment_count = 1; addr = VIRT_TO_BUS(&scb->sg_list[0]); - memcpy(&hscb->SG_list_pointer, &addr, - sizeof(hscb->SG_list_pointer)); + hscb->SG_list_pointer = cpu_to_le32(addr); + hscb->data_pointer = scb->sg_list[0].address; - memcpy(&hscb->data_pointer, &(scb->sg_list[0].address), - sizeof(hscb->data_pointer)); /* Maintain SCB_LINKED_NEXT */ - hscb->data_count &= 0xFF000000; + hscb->data_count &= cpu_to_le32(0xFF000000); hscb->data_count |= scb->sg_list[0].length; addr = VIRT_TO_BUS(scb->sense_cmd); - memcpy(&hscb->SCSI_cmd_pointer, &addr, - sizeof(hscb->SCSI_cmd_pointer)); + hscb->SCSI_cmd_pointer = cpu_to_le32(addr); hscb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]); scb->sg_count = hscb->SG_segment_count; @@ -3496,7 +3456,9 @@ for (i = 0; i < scb->sg_count; i++) { printk(KERN_INFO " sg[%d] - Addr 0x%x : Length %d\n", - i, scb->sg_list[i].address, scb->sg_list[i].length); + i, + le32_to_cpu(scb->sg_list[i].address), + le32_to_cpu(scb->sg_list[i].length)); } /* * XXX - What do we really want to do on an overrun? The @@ -3835,43 +3797,21 @@ * * Description: * SCSI controller interrupt handler. - * - * NOTE: Since we declared this using SA_INTERRUPT, interrupts should - * be disabled all through this function unless we say otherwise. *-F*************************************************************************/ static void aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs) { - struct aic7xxx_host *p; + struct aic7xxx_host *p = (struct aic7xxx_host *) dev_id; unsigned char intstat; unsigned long flags; - p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata; - - /* - * Search for the host with a pending interrupt. If we can't find - * one, then we've encountered a spurious interrupt. - */ - while ((p != NULL) && !(inb(p->base + INTSTAT) & INT_PEND)) - { - if (p->next == NULL) - { - p = NULL; - } - else - { - p = (struct aic7xxx_host *) p->next->hostdata; - } - } - - if (p == NULL) - return; - /* * Handle all the interrupt sources - especially for SCSI * interrupts, we won't get a second chance at them. */ intstat = inb(p->base + INTSTAT); + if (! (intstat & INT_PEND)) /* Interrupt for another device */ + return; /* * Keep track of interrupts for /proc/scsi @@ -4181,6 +4121,7 @@ } } +#if !defined(__sparc_v9__) && !defined(__powerpc__) /*+F************************************************************************* * Function: * aic7xxx_probe @@ -4258,6 +4199,7 @@ return (AIC_NONE); } +#endif /* __sparc_v9__ or __powerpc__ */ /*+F************************************************************************* * Function: @@ -4962,7 +4904,7 @@ { int i; unsigned char sblkctl, flags = 0; - int max_targets; + int max_targets, irq_flags = 0; int found = 1; char channel_ids[] = {'A', 'B', 'C'}; unsigned char target_settings; @@ -5066,7 +5008,6 @@ p->host = host; p->host_no = host->host_no; p->isr_count = 0; - p->next = NULL; p->completeq.head = NULL; p->completeq.tail = NULL; scbq_init(&p->scb_data->free_scbs); @@ -5079,53 +5020,20 @@ p->device_status[i].active_cmds = 0; p->device_status[i].last_reset = 0; } - if (aic7xxx_boards[p->irq] == NULL) - { - int result; - int irq_flags = 0; + /* + * Request an IRQ for the board. Only allow sharing IRQs with PCI devices. + */ #ifdef AIC7XXX_OLD_ISR_TYPE - irg_flags = SA_INTERRUPT; + irq_flags = SA_INTERRUPT; #endif - /* - * Warning! This must be done before requesting the irq. It is - * possible for some boards to raise an interrupt as soon as - * they are enabled. So when we request the irq from the Linux - * kernel, an interrupt is triggered immediately. Therefore, we - * must ensure the board data is correctly set before the request. - */ - aic7xxx_boards[p->irq] = host; - - /* - * Register IRQ with the kernel. Only allow sharing IRQs with - * PCI devices. - */ - if (p->chip_class == AIC_777x) - { - result = (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", NULL)); - } - else - { - result = (request_irq(p->irq, aic7xxx_isr, irq_flags | SA_SHIRQ, - "aic7xxx", NULL)); - } - if (result < 0) - { - printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n", - p->irq); - aic7xxx_boards[p->irq] = NULL; - return (0); - } - } - else + if (p->chip_class != AIC_777x) + irq_flags |= SA_SHIRQ; + if (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", p) < 0) { - /* - * We have found a host adapter sharing an IRQ of a previously - * registered host adapter. Add this host adapter's Scsi_Host - * to the beginning of the linked list of hosts at the same IRQ. - */ - p->next = aic7xxx_boards[p->irq]; - aic7xxx_boards[p->irq] = host; + printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n", + p->irq); + return (0); } /* @@ -5325,17 +5233,7 @@ printk("aic7xxx: Unable to allocate hardware SCB array; " "failing detection.\n"); release_region(p->base, MAXREG - MINREG); - /* - * Ensure that we only free the IRQ when there is _not_ another - * aic7xxx adapter sharing this IRQ. The adapters are always - * added to the beginning of the list, so we can grab the next - * pointer and place it back in the board array. - */ - if (p->next == NULL) - { - free_irq(p->irq, aic7xxx_isr); - } - aic7xxx_boards[p->irq] = p->next; + free_irq(p->irq, p); return(0); } /* At least the control byte of each SCB needs to be 0. */ @@ -5399,6 +5297,12 @@ */ unpause_sequencer(p, /* unpause_always */ TRUE); + /* + * Add it to our list of adapters. + */ + p->next = first_aic7xxx; + first_aic7xxx = p; + return (found); } @@ -5453,7 +5357,7 @@ * and a pointer to a aic7xxx_host struct upon success. *-F*************************************************************************/ static struct aic7xxx_host * -aic7xxx_alloc(Scsi_Host_Template *sht, unsigned int base, unsigned int mbase, +aic7xxx_alloc(Scsi_Host_Template *sht, unsigned long base, unsigned long mbase, aha_chip_type chip_type, int flags, scb_data_type *scb_data) { struct aic7xxx_host *p = NULL; @@ -5768,36 +5672,23 @@ 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. */ @@ -5834,11 +5725,6 @@ } /* - * We found a card, allow 1 spurious interrupt. - */ - aic7xxx_spurious_count = 1; - - /* * Pause the card preserving the IRQ type. Allow the operator * to override the IRQ trigger. */ @@ -5925,7 +5811,7 @@ default: /* Won't get here. */ break; } - printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, IRQ %d (%s), ", + printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s), ", (p->flags & USE_DEFAULTS) ? "dis" : "en", p->base, p->irq, (p->pause & IRQMS) ? "level sensitive" : "edge triggered"); /* @@ -5984,18 +5870,15 @@ aic7xxx_free(p); } } - /* - * Disallow spurious interrupts. - */ - aic7xxx_spurious_count = 0; } } +#endif /* __sparc_v9__ or __powerpc__ */ #ifdef CONFIG_PCI /* * PCI-bus probe. */ - if (pcibios_present()) + if (pci_present()) { struct { @@ -6021,102 +5904,94 @@ }; 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) - { - 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) - { - 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; - - default: - break; - } + while ((pdev = pci_find_device(aic7xxx_pci_devices[i].vendor_id, + aic7xxx_pci_devices[i].device_id, + pdev))) + { + 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; - /* - * 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); + 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; - printk("aic7xxx: <%s> at PCI %d\n", - board_names[chip_type], PCI_SLOT(pci_device_fn)); + case AIC_7873: /* 3985 */ + case AIC_7883: /* 3985-Ultra */ + chan_num = number_of_3985s; /* Has 3 controllers */ + flags |= MULTI_CHANNEL; + number_of_3985s++; + if (number_of_3985s == 3) + { + number_of_3985s = 0; + shared_scb_data = NULL; + } + break; - /* - * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so - * we mask it off. - */ - iobase &= PCI_BASE_ADDRESS_IO_MASK; + default: + break; + } - p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags, - shared_scb_data); + /* + * Read sundry information from PCI BIOS. + */ + iobase = pdev->base_address[0]; + mbase = pdev->base_address[1]; + irq = pdev->irq; + error = pci_read_config_dword(pdev, DEVCONFIG, &devconfig); + error += pci_read_config_dword(pdev, CLASS_PROGIF_REVID, &class_revid); + printk("aic7xxx: <%s> at PCI %d\n", + board_names[chip_type], PCI_SLOT(pdev->devfn)); - if (p == NULL) - { - printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n"); - continue; - } + /* + * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so + * we mask it off. + */ + iobase &= PCI_BASE_ADDRESS_IO_MASK; + p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags, shared_scb_data); + if(p) { + unsigned short pci_command; + + /* Enable bus mastering since this thing must do DMA. */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MASTER; +#ifdef __powerpc__ + /* Enable I/O and memory-space access */ + pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO; +#endif + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } else { + printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n"); + continue; + } - /* Remember to set the channel number, irq, and chip class. */ - p->chan_num = chan_num; - p->irq = irq; - p->chip_class = chip_class; + /* Remember to set the channel number, irq, and chip class. */ + p->chan_num = chan_num; + p->irq = irq; + p->chip_class = chip_class; #ifdef AIC7XXX_PAGE_ENABLE - p->flags |= PAGE_ENABLED; + p->flags |= PAGE_ENABLED; #endif - p->instance = found; + p->instance = found; /* * Remember how the card was setup in case there is no seeprom. @@ -6236,8 +6111,8 @@ /* * Print some additional information about the adapter. */ - printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, " - "IO Mem 0x%x, IRQ %d", + printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, " + "IO Mem 0x%lx, IRQ %x", (p->flags & USE_DEFAULTS) ? "dis" : "en", p->base, p->mbase, p->irq); if ((class_revid & DEVREVID) < 3) @@ -6246,13 +6121,6 @@ } printk("\n"); - /* - * I don't think we need to bother with allowing - * spurious interrupts for the 787x/785x, but what - * the hey. - */ - aic7xxx_spurious_count = 1; - if (aic7xxx_extended) p->flags |= EXTENDED_TRANSLATION; @@ -6294,13 +6162,7 @@ } index++; - /* - * Disable spurious interrupts. - */ - aic7xxx_spurious_count = 0; - } /* Found an Adaptec PCI device. */ - } - } + } /* Found an Adaptec PCI device. */ } #endif CONFIG_PCI @@ -6391,9 +6253,11 @@ /* * XXX - this relies on the host data being stored in a * little-endian format. + * + * No longer is that an issue, I've "big-endian'ified" this driver. -DaveM */ hscb->SCSI_cmd_length = cmd->cmd_len; - hscb->SCSI_cmd_pointer = VIRT_TO_BUS(cmd->cmnd); + hscb->SCSI_cmd_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->cmnd)); if (cmd->use_sg) { @@ -6410,19 +6274,19 @@ sg = (struct scatterlist *)cmd->request_buffer; for (i = 0; i < cmd->use_sg; i++) { - scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address); - scb->sg_list[i].length = (unsigned int) sg[i].length; + scb->sg_list[i].address = cpu_to_le32(VIRT_TO_BUS(sg[i].address)); + scb->sg_list[i].length = cpu_to_le32((unsigned int) sg[i].length); } - hscb->SG_list_pointer = VIRT_TO_BUS(scb->sg_list); + hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(scb->sg_list)); hscb->SG_segment_count = cmd->use_sg; scb->sg_count = hscb->SG_segment_count; /* Copy the first SG into the data pointer area. */ hscb->data_pointer = scb->sg_list[0].address; - hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24); + hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24); #if 0 printk("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n", - cmd->use_sg, aic7xxx_length(cmd, 0), hscb->data_count); + cmd->use_sg, aic7xxx_length(cmd, 0), le32_to_cpu(hscb->data_count)); #endif } else @@ -6435,11 +6299,11 @@ { hscb->SG_segment_count = 1; scb->sg_count = 1; - scb->sg_list[0].address = VIRT_TO_BUS(cmd->request_buffer); - scb->sg_list[0].length = cmd->request_bufflen; - hscb->SG_list_pointer = VIRT_TO_BUS(&scb->sg_list[0]); - hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24); - hscb->data_pointer = VIRT_TO_BUS(cmd->request_buffer); + scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); + scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen); + hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[0])); + hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24); + hscb->data_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); } else { @@ -6447,7 +6311,7 @@ scb->sg_count = 0; hscb->SG_list_pointer = 0; hscb->data_pointer = 0; - hscb->data_count = SCB_LIST_NULL << 24; + hscb->data_count = cpu_to_le32(SCB_LIST_NULL << 24); } } } @@ -6594,7 +6458,7 @@ pause_sequencer(p); while (inb(p->base + INTSTAT) & INT_PEND); { - aic7xxx_isr(p->irq, (void *) NULL, (void *) NULL); + aic7xxx_isr(p->irq, (void *) p, (void *) NULL); pause_sequencer(p); } if ((cmd != scb->cmd) || ((scb->flags & SCB_ACTIVE) == 0)) @@ -6749,7 +6613,7 @@ if (hscb_index == SCB_LIST_NULL) { disconnected = TRUE; - linked_next = (scb->hscb->data_count >> 24) & 0xFF; + linked_next = (le32_to_cpu(scb->hscb->data_count) >> 24) & 0xFF; } else { @@ -6767,8 +6631,8 @@ * linked next pointer. */ scb->hscb->control |= ABORT_SCB | MK_MESSAGE; - scb->hscb->data_count &= ~0xFF000000; - scb->hscb->data_count |= linked_next << 24; + scb->hscb->data_count &= cpu_to_le32(~0xFF000000); + scb->hscb->data_count |= cpu_to_le32(linked_next << 24); if ((p->flags & PAGE_ENABLED) == 0) { scb->hscb->control &= ~DISCONNECTED; @@ -6942,7 +6806,8 @@ { 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; diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h --- v2.1.92/linux/drivers/scsi/aic7xxx.h Sun Dec 21 17:04:48 1997 +++ linux/drivers/scsi/aic7xxx.h Thu Apr 2 09:12:25 1998 @@ -25,6 +25,12 @@ #define AIC7XXX_H_VERSION "$Revision: 3.2 $" +#ifdef __i386__ +#define AIC7XXX_BIOSPARAM aic7xxx_biosparam +#else +#define AIC7XXX_BIOSPARAM NULL +#endif + /* * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields * to do with card config are filled in after the card is detected. @@ -36,7 +42,7 @@ queuecommand: aic7xxx_queue, \ abort: aic7xxx_abort, \ reset: aic7xxx_reset, \ - bios_param: aic7xxx_biosparam, \ + bios_param: AIC7XXX_BIOSPARAM, \ can_queue: -1, /* max simultaneous cmds */\ this_id: -1, /* scsi id of host adapter */\ sg_tablesize: SG_ALL, /* max scatter-gather cmds */\ diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c --- v2.1.92/linux/drivers/scsi/aic7xxx_proc.c Tue Dec 2 20:41:21 1997 +++ linux/drivers/scsi/aic7xxx_proc.c Thu Apr 2 09:12:25 1998 @@ -86,45 +86,18 @@ { struct Scsi_Host *HBAptr; struct aic7xxx_host *p; - int found = FALSE; int size = 0; - unsigned char i; #ifdef AIC7XXX_PROC_STATS struct aic7xxx_xferstats *sp; unsigned char target, lun; + int i; #endif HBAptr = NULL; - for (i=0; i < NUMBER(aic7xxx_boards); i++) - { - if ((HBAptr = aic7xxx_boards[i]) != NULL) - { - if (HBAptr->host_no == hostno) - { - break; - } - - while ((HBAptr->hostdata != NULL) && !found && - ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL)) - { - if (HBAptr->host_no == hostno) - { - found = TRUE; - } - } - - if (!found) - { - HBAptr = NULL; - } - else - { - break; - } - } - } + for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next) + ; - if (HBAptr == NULL) + if (!p) { size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); if (size > length) @@ -136,6 +109,7 @@ return (length); } } + HBAptr = p->host; if (inout == TRUE) /* Has data been written to the file? */ { @@ -217,8 +191,8 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.1.92/linux/drivers/scsi/eata.c Mon Sep 15 09:41:09 1997 +++ linux/drivers/scsi/eata.c Sun Apr 5 11:26:29 1998 @@ -1,6 +1,14 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 + * io_port is now unsigned long. + * + * 17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88 + * Use new scsi error handling code (if linux version >= 2.1.88). + * Use new interrupt code. + * + * * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 * Use of udelay inside the wait loops to avoid timeout * problems with fast cpus. @@ -127,7 +135,7 @@ * This driver is based on the CAM (Common Access Method Committee) * EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol. * - * Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com) + * Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source @@ -331,9 +339,7 @@ #undef DEBUG_LINKED_COMMANDS #undef DEBUG_DETECT #undef DEBUG_INTERRUPT -#undef DEBUG_STATISTICS #undef DEBUG_RESET -#undef DEBUG_SMP #define MAX_ISA 4 #define MAX_VESA 0 @@ -343,15 +349,14 @@ #define MAX_CHANNEL 4 #define MAX_LUN 32 #define MAX_TARGET 32 -#define MAX_IRQ 16 #define MAX_MAILBOXES 64 #define MAX_SGLIST 64 -#define MAX_LARGE_SGLIST 252 +#define MAX_LARGE_SGLIST 122 #define MAX_INTERNAL_RETRIES 64 #define MAX_CMD_PER_LUN 2 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN) -#define SKIP UINT_MAX +#define SKIP ULONG_MAX #define FALSE 0 #define TRUE 1 #define FREE 0 @@ -415,15 +420,15 @@ ulong data_len; /* Number of valid bytes after this field */ ulong sign; /* ASCII "EATA" signature */ unchar :4, /* unused low nibble */ - version:4; /* EATA version, should be 0x1 */ + version:4; /* EATA version, should be 0x1 */ unchar ocsena:1, /* Overlap Command Support Enabled */ - tarsup:1, /* Target Mode Supported */ + tarsup:1, /* Target Mode Supported */ trnxfr:1, /* Truncate Transfer Cmd NOT Necessary */ morsup:1, /* More Supported */ - dmasup:1, /* DMA Supported */ - drqvld:1, /* DRQ Index (DRQX) is valid */ - ata:1, /* This is an ATA device */ - haaval:1; /* Host Adapter Address Valid */ + dmasup:1, /* DMA Supported */ + drqvld:1, /* DRQ Index (DRQX) is valid */ + ata:1, /* This is an ATA device */ + haaval:1; /* Host Adapter Address Valid */ ushort cp_pad_len; /* Number of pad bytes after cp_len */ unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */ ulong cp_len; /* Number of valid bytes in cp */ @@ -432,19 +437,19 @@ ushort unused; ushort scatt_size; /* Max number of entries in scatter/gather table */ unchar irq:4, /* Interrupt Request assigned to this controller */ - irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ - second:1, /* 1 if this is a secondary (not primary) controller */ - drqx:2; /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */ + irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ + second:1, /* 1 if this is a secondary (not primary) controller */ + drqx:2; /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */ unchar sync; /* 1 if scsi target id 7...0 is running sync scsi */ /* Structure extension defined in EATA 2.0B */ unchar isaena:1, /* ISA i/o addressing is disabled/enabled */ - forcaddr:1, /* Port address has been forced */ + forcaddr:1, /* Port address has been forced */ large_sg:1, /* 1 if large SG lists are supported */ res1:1, - :4; + :4; unchar max_id:5, /* Max SCSI target ID number */ - max_chan:3; /* Max SCSI channel number on this board */ + max_chan:3; /* Max SCSI channel number on this board */ /* Structure extension defined in EATA 2.0C */ unchar max_lun; /* Max SCSI LUN number */ @@ -463,17 +468,17 @@ struct eata_config { ushort len; /* Number of bytes following this field */ unchar edis:1, /* Disable EATA interface after config command */ - ocena:1, /* Overlapped Commands Enabled */ - mdpena:1, /* Transfer all Modified Data Pointer Messages */ - tarena:1, /* Target Mode Enabled for this controller */ - :4; + ocena:1, /* Overlapped Commands Enabled */ + mdpena:1, /* Transfer all Modified Data Pointer Messages */ + tarena:1, /* Target Mode Enabled for this controller */ + :4; unchar cpad[511]; }; /* Returned status packet structure */ struct mssp { unchar adapter_status:7, /* State related to current command */ - eoc:1; /* End Of Command (1 = command completed) */ + eoc:1; /* End Of Command (1 = command completed) */ unchar target_status; /* SCSI status received after data transfer */ unchar unused[2]; ulong inv_res_len; /* Number of bytes not transferred */ @@ -489,13 +494,13 @@ /* MailBox SCSI Command Packet */ struct mscp { unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ - init:1, /* Re-initialize controller and self test */ - reqsen:1, /* Transfer Request Sense Data to addr using DMA */ - sg:1, /* Use Scatter/Gather */ - :1, - interp:1, /* The controller interprets cp, not the target */ - dout:1, /* Direction of Transfer is Out (Host to Target) */ - din:1; /* Direction of Transfer is In (Target to Host) */ + init:1, /* Re-initialize controller and self test */ + reqsen:1, /* Transfer Request Sense Data to addr using DMA */ + sg:1, /* Use Scatter/Gather */ + :1, + interp:1, /* The controller interprets cp, not the target */ + dout:1, /* Direction of Transfer is Out (Host to Target) */ + din:1; /* Direction of Transfer is In (Target to Host) */ unchar sense_len; /* Request Sense Length */ unchar unused[3]; unchar fwnest:1, /* Send command to a component of an Array Group */ @@ -507,9 +512,9 @@ unchar target:5, /* SCSI target ID */ channel:3; /* SCSI channel number */ unchar lun:5, /* SCSI logical unit number */ - luntar:1, /* This cp is for Target (not LUN) */ - dispri:1, /* Disconnect Privilege granted */ - one:1; /* 1 */ + luntar:1, /* This cp is for Target (not LUN) */ + dispri:1, /* Disconnect Privilege granted */ + one:1; /* 1 */ unchar mess[3]; /* Massage to/from Target */ unchar cdb[12]; /* Command Descriptor Block */ ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ @@ -526,7 +531,6 @@ unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ unsigned int last_cp_used; /* Index of last mailbox used */ unsigned int iocount; /* Total i/o done for this board */ - unsigned int multicount; /* Total ... in second ihdlr loop */ int board_number; /* Number of this board */ char board_name[16]; /* Name of this board */ char board_id[256]; /* data from INQUIRY on this board */ @@ -542,9 +546,12 @@ static struct Scsi_Host *sh[MAX_BOARDS + 1]; static const char *driver_name = "EATA"; -static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; +static char sha[MAX_BOARDS]; -static unsigned int io_port[] __initdata = { +/* Initialize num_boards so that ihdlr can work while detect is in progress */ +static unsigned int num_boards = MAX_BOARDS; + +static unsigned long io_port[] __initdata = { /* Space for MAX_INT_PARAM ports usable while loading as a module */ SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, @@ -665,7 +672,7 @@ return; } -static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { +static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { udelay(1L); @@ -675,7 +682,7 @@ return FALSE; } -static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) { +static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) { if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; @@ -690,7 +697,7 @@ return FALSE; } -static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) { +static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) { unsigned int loop = MAXLOOP; ushort *p; @@ -698,7 +705,7 @@ while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { udelay(1L); - if (--loop == 0) return TRUE; + if (--loop == 0) return TRUE; } loop = MAXLOOP; @@ -709,7 +716,7 @@ } __initfunc (static inline int port_detect \ - (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) { + (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { unsigned char irq, dma_channel, subversion, i; unsigned char protocol_rev; struct eata_info info; @@ -723,7 +730,7 @@ sprintf(name, "%s%d", driver_name, j); if(check_region(port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base); + printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); return FALSE; } @@ -738,7 +745,7 @@ if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { printk("%s: config structure size (%ld bytes) too short, detaching.\n", - name, DEV2H(info.data_len)); + name, DEV2H(info.data_len)); return FALSE; } else if (DEV2H(info.data_len) == EATA_2_0A_SIZE) @@ -774,7 +781,7 @@ } if (!info.haaval || info.ata) { - printk("%s: address 0x%03x, unusable %s board (%d%d), detaching.\n", + printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n", name, port_base, bus_type, info.haaval, info.ata); return FALSE; } @@ -782,7 +789,7 @@ if (info.drqvld) { if (subversion == ESA) - printk("%s: warning, weird %s board using DMA.\n", name, bus_type); + printk("%s: warning, weird %s board using DMA.\n", name, bus_type); subversion = ISA; dma_channel = dma_channel_table[3 - info.drqx]; @@ -790,7 +797,7 @@ else { if (subversion == ISA) - printk("%s: warning, weird %s board not using DMA.\n", name, bus_type); + printk("%s: warning, weird %s board not using DMA.\n", name, bus_type); subversion = ESA; dma_channel = NO_DMA; @@ -803,19 +810,20 @@ if (subversion == ESA && !info.irq_tr) printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", - name, irq); + name, irq); - /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq, - eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { + /* Board detected, allocate its IRQ */ + if (request_irq(irq, eata2x_interrupt_handler, + SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), + driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); return FALSE; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - free_irq(irq, NULL); + name, dma_channel); + free_irq(irq, &sha[j]); return FALSE; } @@ -840,7 +848,7 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - if (!irqlist[irq]) free_irq(irq, NULL); + free_irq(irq, &sha[j]); if (subversion == ISA) free_dma(dma_channel); @@ -865,7 +873,6 @@ HD(j)->subversion = subversion; HD(j)->protocol_rev = protocol_rev; HD(j)->board_number = j; - irqlist[irq]++; if (HD(j)->subversion == ESA) sh[j]->unchecked_isa_dma = FALSE; @@ -937,10 +944,11 @@ } else tag_type = 'n'; - printk("%s: 2.0%c, %s 0x%03x, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\ - "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type, sh[j]->io_port, - sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue, - tag_type, YESNO(linked_comm), max_queue_depth); + printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\ + "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type, + (unsigned long)sh[j]->io_port, sh[j]->irq, dma_name, + sh[j]->sg_tablesize, sh[j]->can_queue, tag_type, YESNO(linked_comm), + max_queue_depth); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", @@ -1012,7 +1020,7 @@ unsigned char bus, devfn; unsigned int addr, k; - if (!pcibios_present()) return; + if (!pci_present()) return; for (k = 0; k < MAX_PCI; k++) { @@ -1056,11 +1064,6 @@ } #endif - for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = 0; - calls[k] = 0; - } - for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; if (!setup_done) add_pci_ports(); @@ -1073,8 +1076,9 @@ } if (j > 0) - printk("EATA/DMA 2.0x: Copyright (C) 1994-1997 Dario Ballabio.\n"); + printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n"); + num_boards = j; restore_flags(flags); return j; } @@ -1138,26 +1142,26 @@ if (i >= sh[j]->can_queue) i = 0; if (HD(j)->cp_stat[i] == FREE) { - HD(j)->last_cp_used = i; - break; - } + HD(j)->last_cp_used = i; + break; + } } if (k == sh[j]->can_queue) { printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); + printk("%s: qcomm, already in reset.\n", BN(j)); else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); + panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); SCpnt->result = DID_BUS_BUSY << 16; SCpnt->host_scribble = NULL; printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); restore_flags(flags); done(SCpnt); - return 0; + return 1; } /* Set pointer to control packet structure */ @@ -1178,21 +1182,21 @@ SCpnt->host_scribble = (unsigned char *) &cpp->index; if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCpnt->channel, SCpnt->target, + BN(j), i, SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->dout = TRUE; - break; - } + cpp->dout = TRUE; + break; + } if ((cpp->din = !cpp->dout)) for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) if (SCpnt->cmnd[0] == data_none_cmds[k]) { - cpp->din = FALSE; - break; - } + cpp->din = FALSE; + break; + } cpp->reqsen = TRUE; cpp->dispri = TRUE; @@ -1253,7 +1257,7 @@ SCpnt->pid); restore_flags(flags); done(SCpnt); - return 0; + return 1; } HD(j)->cp_stat[i] = IN_USE; @@ -1272,14 +1276,14 @@ if (SCarg->host_scribble == NULL || SCarg->serial_number != SCarg->serial_number_at_timeout) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } i = *(unsigned int *)SCarg->host_scribble; printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -1300,8 +1304,8 @@ printk("%s: abort, mbox %d is in use.\n", BN(j), i); if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", + BN(j), i, SCarg, HD(j)->cp[i].SCpnt); if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); @@ -1327,7 +1331,7 @@ SCarg->host_scribble = NULL; HD(j)->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); + BN(j), i, SCarg->pid); SCarg->scsi_done(SCarg); restore_flags(flags); return SCSI_ABORT_SUCCESS; @@ -1347,7 +1351,7 @@ cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, reset_flags); if (SCarg->host_scribble == NULL) @@ -1384,13 +1388,13 @@ if (HD(j)->cp_stat[i] == FREE) continue; if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } + HD(j)->cp_stat[i] = FREE; + printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); + continue; + } if (!(SCpnt = HD(j)->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); + panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { HD(j)->cp_stat[i] = ABORTING; @@ -1405,13 +1409,13 @@ } if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); + panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); + panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); + panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); if (SCpnt == SCarg) arg_done = TRUE; } @@ -1446,7 +1450,7 @@ HD(j)->cp_stat[i] = LOCKED; printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->pid); } else if (HD(j)->cp_stat[i] == ABORTING) { @@ -1458,7 +1462,7 @@ HD(j)->cp_stat[i] = FREE; printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->pid); } else @@ -1640,229 +1644,200 @@ } -static void 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; + HD(j)->cp_stat[i] = FREE; + cpp = &HD(j)->cp[i]; + SCpnt = spp->SCpnt; - 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; + if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); - 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 != cpp->SCpnt) + panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i, + SCpnt, cpp->SCpnt); - /* 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->host_scribble == NULL) + panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, + SCpnt->pid, SCpnt); - if (loops > 1) HD(j)->multicount++; + if (*(unsigned int *)SCpnt->host_scribble != i) + panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", + BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq); + + if (linked_comm && SCpnt->device->queue_depth > 2 + && TLDEV(SCpnt->device->type)) + flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE); + + tstatus = status_byte(spp->target_status); + + switch (spp->adapter_status) { + case ASOK: /* status OK */ + + /* Forces a reset if a disk drive keeps returning BUSY */ + if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) + status = DID_ERROR << 16; + + /* If there was a bus reset, redo operation on each target */ + else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK + && HD(j)->target_redo[SCpnt->target][SCpnt->channel]) + status = DID_BUS_BUSY << 16; + + /* Works around a flaw in scsi.c */ + else if (tstatus == CHECK_CONDITION + && SCpnt->device->type == TYPE_DISK + && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) + status = DID_BUS_BUSY << 16; + + else + status = DID_OK << 16; + + if (tstatus == GOOD) + HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; + + if (spp->target_status && SCpnt->device->type == TYPE_DISK) + printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ + "target_status 0x%x, sense key 0x%x.\n", BN(j), + SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->pid, spp->target_status, + SCpnt->sense_buffer[2]); + + HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0; + + if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; + + break; + case ASST: /* Selection Time Out */ + case 0x02: /* Command Time Out */ + + if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1) + status = DID_ERROR << 16; + else { + status = DID_TIME_OUT << 16; + HD(j)->target_to[SCpnt->target][SCpnt->channel]++; + } + + break; + + /* Perform a limited number of internal retries */ + case 0x03: /* SCSI Bus Reset Received */ + case 0x04: /* Initial Controller Power-up */ + + for (c = 0; c <= sh[j]->max_channel; c++) + for (k = 0; k < sh[j]->max_id; k++) + HD(j)->target_redo[k][c] = TRUE; + + if (SCpnt->device->type != TYPE_TAPE + && HD(j)->retries < MAX_INTERNAL_RETRIES) { + status = DID_BUS_BUSY << 16; + HD(j)->retries++; + HD(j)->last_retried_pid = SCpnt->pid; + } + else + status = DID_ERROR << 16; + + break; + case 0x05: /* Unexpected Bus Phase */ + case 0x06: /* Unexpected Bus Free */ + case 0x07: /* Bus Parity Error */ + case 0x08: /* SCSI Hung */ + case 0x09: /* Unexpected Message Reject */ + case 0x0a: /* SCSI Bus Reset Stuck */ + case 0x0b: /* Auto Request-Sense Failed */ + case 0x0c: /* Controller Ram Parity Error */ + default: + status = DID_ERROR << 16; + break; + } + + SCpnt->result = status | spp->target_status; + HD(j)->iocount++; #if defined (DEBUG_INTERRUPT) - if (SCpnt->result || do_trace) + if (SCpnt->result || do_trace) #else - if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || - (spp->adapter_status != ASOK && - spp->adapter_status != ASST && HD(j)->iocount <= 1000) || - do_trace || msg_byte(spp->target_status)) + if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || + (spp->adapter_status != ASOK && + spp->adapter_status != ASST && HD(j)->iocount <= 1000) || + do_trace || msg_byte(spp->target_status)) #endif - printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ - " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", - BN(j), i, spp->adapter_status, spp->target_status, - SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, - reg, HD(j)->iocount); - - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; - - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); - - } /* Mailbox loop */ + printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ + " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", + BN(j), i, spp->adapter_status, spp->target_status, + SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, + reg, HD(j)->iocount); - } /* Multiple command loop */ - - } /* Boards loop */ + /* Set the command state to inactive */ + SCpnt->host_scribble = NULL; - calls[irq]++; + SCpnt->scsi_done(SCpnt); -#if defined (DEBUG_SMP) - if (total_loops == 0) - printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", - driver_name, irq, calls[irq]); -#endif + } /* Mailbox loop */ - if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); + if (n_ready > 1) + printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready); -#if defined (DEBUG_STATISTICS) - if ((calls[irq] % 100000) == 10000) - for (j = 0; sh[j] != NULL; j++) - printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j), - calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount); -#endif + if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, + HD(j)->iocount); - restore_flags(flags); return; } @@ -1881,7 +1856,7 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- v2.1.92/linux/drivers/scsi/eata.h Sun Dec 21 17:04:48 1997 +++ linux/drivers/scsi/eata.h Sun Apr 5 11:26:29 1998 @@ -1,5 +1,5 @@ /* - * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. + * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. */ #ifndef _EATA_H #define _EATA_H @@ -12,19 +12,41 @@ int eata2x_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *, unsigned int); -#define EATA_VERSION "3.11.00" +#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 -#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 \ - } #endif diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.1.92/linux/drivers/scsi/eata_dma.c Mon Oct 28 14:31:24 1996 +++ linux/drivers/scsi/eata_dma.c Thu Apr 2 09:12:25 1998 @@ -1406,7 +1406,7 @@ 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)) diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.1.92/linux/drivers/scsi/eata_pio.c Thu Aug 1 05:43:04 1996 +++ linux/drivers/scsi/eata_pio.c Thu Apr 2 09:12:25 1998 @@ -880,7 +880,7 @@ 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)) diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.1.92/linux/drivers/scsi/fdomain.c Fri Nov 7 10:16:36 1997 +++ linux/drivers/scsi/fdomain.c Thu Apr 2 09:12:25 1998 @@ -20,6 +20,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. + * PCI detection rewritten by Martin Mares + ************************************************************************** SUMMARY: @@ -266,7 +268,6 @@ #include #include #include -#include #include #include @@ -749,168 +750,63 @@ return 1; /* success */ } -static int fdomain_pci_nobios_detect( int *irq, int *iobase ) -{ - int i; - int flag = 0; - - /* The proper way of doing this is to use ask the PCI bus for the device - IRQ and interrupt level. But we can't do that if PCI BIOS32 support - isn't compiled into the kernel, or if a PCI BIOS32 isn't present. - - Instead, we scan down a bunch of addresses (Future Domain tech - support says we will probably find the address before we get to - 0xf800). This works fine on some systems -- other systems may have - to scan more addresses. If you have to modify this section for your - installation, please send mail to faith@cs.unc.edu. */ - - for (i = 0xfff8; i > 0xe000; i -= 8) { - if (check_region( i, 0x10 )) { -#if DEBUG_DETECT - printk( " (%x inuse)," , i ); -#endif - continue; - } - if ((flag = fdomain_is_valid_port( i ))) break; - } - - if (!flag) return 0; /* iobase not found */ - - *irq = fdomain_get_irq( i ); - *iobase = i; - - return 1; /* success */ -} - /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* iobase) This function gets the Interrupt Level and I/O base address from - the PCI configuration registers. The I/O base address is masked with - 0xfff8 since on my card the address read from the PCI config registers - is off by one from the actual I/O base address necessary for accessing - the status and control registers on the card (PCI config register gives - 0xf801, actual address is 0xf800). This is likely a bug in the FD - config code that writes to the PCI registers, however using a mask - should be safe since I think the scan done by the card to determine the - I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at - least the old scan code we used to use to get the I/O base did... Also, - the device ID from the PCI config registers is 0x0 and should be 0x60e9 - as it is in the status registers (offset 5 from I/O base). If this is - changed in future hardware/BIOS changes it will need to be fixed in this - detection function. Comments, bug reports, etc... on this function - should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ + the PCI configuration registers. */ #ifdef CONFIG_PCI static int fdomain_pci_bios_detect( int *irq, int *iobase ) { - int error; - unsigned char pci_bus, pci_dev_fn; /* PCI bus & device function */ - unsigned char pci_irq; /* PCI interrupt line */ - unsigned int pci_base; /* PCI I/O base address */ - unsigned short pci_vendor, pci_device; /* PCI vendor & device IDs */ - - /* If the PCI BIOS doesn't exist, use the old-style detection routines. - Otherwise, get the I/O base address and interrupt from the PCI config - registers. */ - - if (!pcibios_present()) return fdomain_pci_nobios_detect( irq, iobase ); + unsigned int pci_irq; /* PCI interrupt line */ + unsigned long pci_base; /* PCI I/O base address */ + struct pci_dev *pdev = NULL; + + if (!pci_present()) return 0; #if DEBUG_DETECT /* Tell how to print a list of the known PCI devices from bios32 and list vendor and device IDs being used if in debug mode. */ - printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" ); + printk( "\nINFO: use lspci -v to see list of PCI devices\n" ); printk( "\nTMC-3260 detect:" " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n", PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70 ); #endif - /* We will have to change this if more than 1 PCI bus is present and the - FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, - which is not supported by bios32 right now anyway). This should - probably be done by a call to pcibios_find_device but I can't get it - to work... Also the device ID reported from the PCI config registers - does not match the device ID quoted in the tech manual or available - from offset 5 from the I/O base address. It should be 0x60E9, but it - is 0x0 if read from the PCI config registers. I guess the FD folks - neglected to write it to the PCI registers... This loop is necessary - to get the device function (at least until someone can get - pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ - - pci_bus = 0; - - for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { - pcibios_read_config_word( pci_bus, - pci_dev_fn, - PCI_VENDOR_ID, - &pci_vendor ); - - if (pci_vendor == PCI_VENDOR_ID_FD) { - pcibios_read_config_word( pci_bus, - pci_dev_fn, - PCI_DEVICE_ID, - &pci_device ); - - if (pci_device == PCI_DEVICE_ID_FD_36C70) { - /* Break out once we have the correct device. If other FD - PCI devices are added to this driver we will need to add - an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ - break; - } else { - /* If we can't find an FD scsi card we give up. */ - return 0; - } - } - } + if ((pdev = pci_find_device(PCI_VENDOR_ID, PCI_DEVICE_ID, pdev)) == NULL) + return 0; #if DEBUG_DETECT printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n", - pci_bus, - (pci_dev_fn & 0xf8) >> 3, - pci_dev_fn & 7 ); + pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); #endif /* We now have the appropriate device function for the FD board so we just read the PCI config info from the registers. */ - if ((error = pcibios_read_config_dword( pci_bus, - pci_dev_fn, - PCI_BASE_ADDRESS_0, - &pci_base )) - || (error = pcibios_read_config_byte( pci_bus, - pci_dev_fn, - PCI_INTERRUPT_LINE, - &pci_irq ))) { - printk ( "PCI ERROR: Future Domain 36C70 not initializing" - " due to error reading configuration space\n" ); - return 0; - } else { + pci_base = pdev->base_address[0]; + pci_irq = pdev->irq; #if DEBUG_DETECT printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", pci_irq, pci_base ); #endif - /* Now we have the I/O base address and interrupt from the PCI - configuration registers. Unfortunately it seems that the I/O base - address is off by one on my card so I mask it with 0xfff8. This - must be some kind of goof in the FD code that does the autoconfig - and writes to the PCI registers (or maybe I just don't understand - something). If they fix it in later versions of the card or BIOS - we may have to adjust the address based on the signature or - something... */ + /* Now we have the I/O base address and interrupt from the PCI + configuration registers. */ - *irq = pci_irq; - *iobase = (pci_base & 0xfff8); + *irq = pci_irq; + *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK); #if DEBUG_DETECT - printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); - printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase ); + printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); + printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase ); #endif - if (!fdomain_is_valid_port( *iobase )) return 0; - return 1; - } - return 0; + if (!fdomain_is_valid_port( *iobase )) return 0; + return 1; } #endif @@ -978,7 +874,8 @@ #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 } diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.1.92/linux/drivers/scsi/gdth.c Tue Nov 4 09:17:30 1997 +++ linux/drivers/scsi/gdth.c Thu Apr 2 09:12:25 1998 @@ -23,6 +23,19 @@ * Tested with Linux 1.2.13, ..., 2.1.61 * * * * $Log: gdth.c,v $ + * Revision 1.3 1998/02/25 23:52:32 ecd + * Final round of PCI device driver patches by Martin Mares. + * + * I could not verify each and every change to the drivers locally, + * please consult linux/Documentation/pci.txt to understand changes + * made in case patching should be necessary. + * + * Revision 1.2 1997/11/12 23:58:51 davem + * Merge to 2.1.63 to get the Ingo P5 bugfix. + * I did not touch the sound changes at all, Alan + * please look into that stuff as it is your + * territory. + * * Revision 1.10 1997/10/31 12:29:57 achim * Read heads/sectors from host drive * @@ -60,7 +73,7 @@ * Initial revision * * - * $Id: gdth.c,v 1.10 1997/10/31 12:29:57 achim Exp $ + * $Id: gdth.c,v 1.3 1998/02/25 23:52:32 ecd Exp $ ************************************************************************/ #ifdef MODULE @@ -71,7 +84,6 @@ #include #include #include -#include #include #include #include @@ -83,6 +95,8 @@ #include #if LINUX_VERSION_CODE >= 0x020100 #include +#else +#include #endif #include @@ -440,7 +454,7 @@ TRACE(("gdth_search_pci() device_id %d, index %d\n", device_id,index)); - if (!pcibios_present()) + if (!pci_present()) return 0; if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index, @@ -448,6 +462,22 @@ return 0; /* GDT PCI controller found, now read resources from config space */ +#if LINUX_VERSION_CODE >= 0x20155 + { + struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn); + base0 = pdev->base_address[0]; + base1 = pdev->base_address[1]; + base2 = pdev->base_address[2]; + if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, + PCI_ROM_ADDRESS, + (int *) &pcistr->bios))) { + printk("GDT-PCI: error %s reading configuration space", + pcibios_strerror(error)); + return -1; + } + pcistr->irq = pdev->irq; + } +#else #if LINUX_VERSION_CODE >= 0x010300 #define GDTH_BASEP (int *) #else @@ -471,6 +501,7 @@ pcibios_strerror(error)); return -1; } +#endif pcistr->device_id = device_id; if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */ diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c --- v2.1.92/linux/drivers/scsi/in2000.c Thu Jul 17 20:24:38 1997 +++ linux/drivers/scsi/in2000.c Wed Apr 1 20:41:12 1998 @@ -123,8 +123,8 @@ #include "hosts.h" -#define IN2000_VERSION "1.31" -#define IN2000_DATE "06/July/1997" +#define IN2000_VERSION "1.32" +#define IN2000_DATE "28/March/1998" /* * Note - the following defines have been moved to 'in2000.h': @@ -2031,18 +2031,12 @@ 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) { diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h --- v2.1.92/linux/drivers/scsi/in2000.h Fri Feb 6 15:33:40 1998 +++ linux/drivers/scsi/in2000.h Mon Apr 6 11:51:22 1998 @@ -2,7 +2,7 @@ * in2000.h - Linux device driver definitions for the * Always IN2000 ISA SCSI card. * - * IMPORTANT: This file is for version 1.31 - 06/Jul/1997 + * IMPORTANT: This file is for version 1.32 - 28/Mar/1998 * * Copyright (c) 1996 John Shifflett, GeoLog Consulting * john@geolog.com @@ -404,8 +404,8 @@ 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 */ \ } diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.92/linux/drivers/scsi/ncr53c8xx.c Wed Apr 1 20:11:53 1998 +++ linux/drivers/scsi/ncr53c8xx.c Thu Apr 2 09:12:25 1998 @@ -116,7 +116,6 @@ #include #include #include -#include #include #include #include @@ -136,6 +135,7 @@ #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35) #include #else +#include #ifndef __initdata #define __initdata #endif @@ -275,8 +275,12 @@ typedef u_long vm_offset_t; typedef int vm_size_t; +#ifndef bcopy #define bcopy(s, d, n) memcpy((d), (s), (n)) +#endif +#ifndef bzero #define bzero(d, n) memset((d), 0, (n)) +#endif #ifndef offsetof #define offsetof(t, m) ((size_t) (&((t *)0)->m)) @@ -309,6 +313,12 @@ ** architecture. */ +#ifdef __sparc__ +#define remap_pci_mem(base, size) ((vm_offset_t) __va(base)) +#define unmap_pci_mem(vaddr, size) +#define pcivtophys(p) ((p) & pci_dvma_mask) +#else /* __sparc__ */ +#define pcivtophys(p) (p) #ifndef NCR_IOMAPPED __initfunc( static vm_offset_t remap_pci_mem(u_long base, u_long size) @@ -337,6 +347,7 @@ #endif } #endif /* !NCR_IOMAPPED */ +#endif /* __sparc__ */ #else /* linux-1.2.13 */ @@ -1795,8 +1806,8 @@ ** Profiling data */ struct profile profile; - u_long disc_phys; - u_long disc_ref; + u_int disc_phys; + u_int disc_ref; /* ** The global control block. @@ -1839,7 +1850,7 @@ /* ** irq level */ - u_short irq; + u_int irq; }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -3795,7 +3806,8 @@ switch (old & RELOC_MASK) { case RELOC_REGISTER: - new = (old & ~RELOC_MASK) + np->paddr; + new = (old & ~RELOC_MASK) + + pcivtophys(np->paddr); break; case RELOC_LABEL: new = (old & ~RELOC_MASK) + np->p_script; @@ -4388,9 +4400,15 @@ u_long flags = 0; ncr_nvram *nvram = device->nvram; +#ifdef __sparc__ +printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=0x%x\n", + device->chip.name, unit, device->chip.revision_id, device->slot.base, + device->slot.io_port, device->slot.irq); +#else printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n", device->chip.name, unit, device->chip.revision_id, device->slot.base, device->slot.io_port, device->slot.irq); +#endif /* ** Allocate host_data structure @@ -4543,7 +4561,7 @@ np->p_scripth = vtophys(np->scripth); np->script = (np->vaddr2) ? (struct script *) np->vaddr2 : np->script0; - np->p_script = (np->vaddr2) ? np->paddr2 : vtophys(np->script0); + np->p_script = (np->vaddr2) ? pcivtophys(np->paddr2) : vtophys(np->script0); ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script)); ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); @@ -4618,7 +4636,7 @@ ** Then enable disconnects. */ save_flags(flags); cli(); - if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { + if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) { printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); restore_flags(flags); goto attach_error; @@ -5504,8 +5522,12 @@ */ #ifdef DEBUG_NCR53C8XX +#ifdef __sparc__ + printf("%s: freeing irq 0x%x\n", ncr_name(np), np->irq); +#else printf("%s: freeing irq %d\n", ncr_name(np), np->irq); #endif +#endif #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) free_irq(np->irq, np); #else @@ -5812,8 +5834,14 @@ ** Announce changes to the generic driver. */ if (tp->numtags) { + /* + * Decrease tp->maxtags (ecd, 980110) + */ + tp->maxtags = tp->numtags - 1; + PRINT_ADDR(cmd); - printf("QUEUE FULL! suspending tagged command queueing\n"); + printf("QUEUE FULL! suspending tagged command queueing (setting maxtags to %d)\n", tp->maxtags); + tp->numtags = 0; tp->num_good = 0; if (lp) { @@ -7317,10 +7345,10 @@ if (dsp == vtophys (&cp->patch[2])) { vdsp = &cp->patch[0]; - nxtdsp = vdsp[3]; + nxtdsp = scr_to_cpu(vdsp[3]); } else if (dsp == vtophys (&cp->patch[6])) { vdsp = &cp->patch[4]; - nxtdsp = vdsp[3]; + nxtdsp = scr_to_cpu(vdsp[3]); } else if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { vdsp = (u_int32 *) ((char*)np->script - np->p_script + dsp -8); nxtdsp = dsp; @@ -8233,13 +8261,13 @@ cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval)); tp->getscr[2] = - cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer)); + cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_sxfer)); tp->getscr[3] = (np->features & FE_PFEN) ? cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval)); tp->getscr[5] = - cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3)); + cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_scntl3)); assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ offsetof(struct tcb , sval )) &3) == 0); @@ -8635,8 +8663,8 @@ #define PROFILE cp->phys.header.stamp static void ncb_profile (ncb_p np, ccb_p cp) { - int co, st, en, di, se, post,work,disc; - u_long diff; + long co, st, en, di, se, post, work, disc; + u_int diff; PROFILE.end = jiffies; @@ -8659,7 +8687,7 @@ work = (st - co) - disc; - diff = (np->disc_phys - np->disc_ref) & 0xff; + diff = (scr_to_cpu(np->disc_phys) - np->disc_ref) & 0xff; np->disc_ref += diff; np->profile.num_trans += 1; @@ -9085,7 +9113,7 @@ int i, j; int attach_count = 0; ncr_nvram *nvram; - ncr_device *devp; + ncr_device *devp = 0; /* to shut up gcc */ if (!nvram_index) return 0; @@ -9211,7 +9239,7 @@ ** the order they are detected. */ - if (!pcibios_present()) + if (!pci_present()) return 0; chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]); @@ -9295,14 +9323,17 @@ { ushort vendor_id, device_id, command; uchar cache_line_size, latency_timer; - uchar irq, revision; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90) - ulong base, base_2, io_port; + uchar revision; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85) struct pci_dev *pdev; -#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) + ulong base, base_2, io_port; + uint irq; +#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) + uchar irq; uint base, base_2, io_port; #else - ulong base, base_2; + uchar irq; + ulong base, base_2, io_port; #endif int i; @@ -9312,7 +9343,7 @@ ncr_chip *chip; printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", - bus, PCI_SLOT(device_fn), PCI_FUNC(device_fn)); + bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); /* * Read info from the PCI config space. * pcibios_read_config_xxx() functions are assumed to be used for @@ -9326,12 +9357,12 @@ PCI_DEVICE_ID, &device_id); (void) pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90) - pdev = pci_find_dev(bus, device_fn); +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85) + pdev = pci_find_slot(bus, device_fn); io_port = pdev->base_address[0]; - base = pdev->base_address[1]; - base_2 = pdev->base_address[2]; - irq = pdev->irq; + base = pdev->base_address[1]; + base_2 = pdev->base_address[2]; + irq = pdev->irq; #else (void) pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, &io_port); @@ -9343,7 +9374,7 @@ PCI_INTERRUPT_LINE, &irq); #endif (void) pcibios_read_config_byte(bus, device_fn, - PCI_CLASS_REVISION, &revision); + PCI_CLASS_REVISION,&revision); (void) pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, &cache_line_size); (void) pcibios_read_config_byte(bus, device_fn, @@ -9369,24 +9400,105 @@ } #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 (base >= 0x10000000) { - base = (base & 0x00FFFFFF) | 0x01000000; - pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base); + + 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 ((chip->features & FE_CLSE) && !cache_line_size) { + cache_line_size = 16; + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size); + pcibios_write_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, cache_line_size); + pcibios_read_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, &cache_line_size); + } + + if (!latency_timer) { + latency_timer = 248; + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer); + pcibios_write_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, latency_timer); + pcibios_read_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, &latency_timer); } #endif @@ -9425,8 +9537,13 @@ base_2 &= PCI_BASE_ADDRESS_MEM_MASK; if (io_port && check_region (io_port, 128)) { +#ifdef __sparc__ + printk("ncr53c8xx: IO region 0x%lx to 0x%lx is in use\n", + io_port, (io_port + 127)); +#else printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n", (int) io_port, (int) (io_port + 127)); +#endif return -1; } @@ -9459,7 +9576,7 @@ /* * 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) diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h --- v2.1.92/linux/drivers/scsi/ncr53c8xx.h Fri Feb 6 15:33:40 1998 +++ linux/drivers/scsi/ncr53c8xx.h Mon Apr 6 11:51:23 1998 @@ -161,6 +161,8 @@ #define SCSI_NCR_IOMAPPED #elif defined(__alpha__) || defined(__powerpc__) #define SCSI_NCR_IOMAPPED +#elif defined(__sparc__) +#undef SCSI_NCR_IOMAPPED #endif /* @@ -347,13 +349,18 @@ #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 */ diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c --- v2.1.92/linux/drivers/scsi/pci2000.c Tue Feb 17 13:12:47 1998 +++ linux/drivers/scsi/pci2000.c Thu Apr 2 09:12:25 1998 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -519,21 +518,15 @@ PADAPTER2000 padapter; int z; int setirq; + struct pci_dev *pdev = NULL; - if ( pcibios_present () ) - { - for ( pci_index = 0; pci_index <= MAXADAPTER; ++pci_index ) + if ( pci_present () ) + while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_ROY_1, pdev))) { - UCHAR pci_bus, pci_device_fn; - - if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 ) - break; - pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); padapter = HOSTDATA(pshost); - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort); - padapter->basePort &= 0xFFFE; + padapter->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4; @@ -550,7 +543,7 @@ if ( WaitReady (padapter) ) goto unregister; - pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq); + pshost->irq = pdev->irq; setirq = 1; for ( z = 0; z < pci_index; z++ ) // scan for shared interrupts { @@ -573,13 +566,12 @@ 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 diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c --- v2.1.92/linux/drivers/scsi/pci2220i.c Wed Nov 5 13:18:17 1997 +++ linux/drivers/scsi/pci2220i.c Thu Apr 2 09:12:25 1998 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -632,7 +631,7 @@ ****************************************************************/ int Pci2220i_Detect (Scsi_Host_Template *tpnt) { - int pci_index = 0; + struct pci_dev *pdev = NULL; struct Scsi_Host *pshost; PADAPTER2220I hostdata; ULONG modearray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P}; @@ -640,20 +639,13 @@ int z; int setirq; - if ( pcibios_present () ) - { - for ( pci_index = 0; pci_index <= MAXADAPTER; ++pci_index ) + if ( pci_present () ) + while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_DALE_1, pdev))) { - UCHAR pci_bus, pci_device_fn; - - if ( pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 ) - break; - pshost = scsi_register (tpnt, sizeof(ADAPTER2220I)); hostdata = HOSTDATA(pshost); - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &hostdata->basePort); - hostdata->basePort &= 0xFFFE; + hostdata->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; DEB (printk ("\nBase Regs = %#04X", hostdata->basePort)); hostdata->regRemap = hostdata->basePort + RTR_LOCAL_REMAP; // 32 bit local space remap DEB (printk (" %#04X", hostdata->regRemap)); @@ -666,8 +658,7 @@ hostdata->regScratchPad = hostdata->basePort + RTR_MAILBOX; // 16 byte scratchpad I/O base address DEB (printk (" %#04X", hostdata->regScratchPad)); - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &hostdata->regBase); - hostdata->regBase &= 0xFFFE; + hostdata->regBase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK; for ( z = 0; z < 9; z++ ) // build regester address array hostdata->ports[z] = hostdata->regBase + 0x80 + (z * 4); hostdata->ports[PORT_FAIL] = hostdata->regBase + REG_FAIL; @@ -691,11 +682,11 @@ if ( !inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board goto unregister; - pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq); + pshost->irq = pdev->irq; setirq = 1; - for ( z = 0; z < pci_index; z++ ) // scan for shared interrupts + for ( z = 0; z < NumAdapters; z++ ) // scan for shared interrupts { - if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses + if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses setirq = 0; } if ( setirq ) // if not shared, posses @@ -706,7 +697,7 @@ goto unregister; } } - PsiHost[pci_index] = pshost; // save SCSI_HOST pointer + PsiHost[NumAdapters] = pshost; // save SCSI_HOST pointer pshost->unique_id = hostdata->regBase; pshost->max_id = 4; @@ -743,7 +734,6 @@ scsi_unregister (pshost); NumAdapters++; } - } return NumAdapters; } /**************************************************************** diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.1.92/linux/drivers/scsi/qlogicisp.c Wed Apr 1 20:11:53 1998 +++ linux/drivers/scsi/qlogicisp.c Thu Apr 2 09:12:25 1998 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -55,8 +54,6 @@ #define DEFAULT_LOOP_COUNT 1000000 -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) - /* End Configuration section *************************************************/ #include @@ -488,11 +485,10 @@ #define QUEUE_ENTRY_LEN 64 struct isp1020_hostdata { - u_char bus; u_char revision; - u_char device_fn; struct host_param host_param; struct dev_param dev_param[MAX_TARGETS]; + struct pci_dev *pci_dev; /* result and request queues (shared with isp1020): */ u_int req_in_ptr; /* index of next request slot */ @@ -511,8 +507,6 @@ QLOGICISP_REQ_QUEUE_LEN) #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN) -static struct Scsi_Host *irq2host[NR_IRQS]; - static void isp1020_enable_irqs(struct Scsi_Host *); static void isp1020_disable_irqs(struct Scsi_Host *); static int isp1020_init(struct Scsi_Host *); @@ -557,33 +551,26 @@ int isp1020_detect(Scsi_Host_Template *tmpt) { int hosts = 0; - u_short index; - u_char bus, device_fn; struct Scsi_Host *host; struct isp1020_hostdata *hostdata; + struct pci_dev *pdev = NULL; ENTER("isp1020_detect"); tmpt->proc_dir = &proc_scsi_isp1020; - if (pcibios_present() == 0) { - printk("qlogicisp : PCI bios not present\n"); + if (pci_present() == 0) { + printk("qlogicisp : PCI not present\n"); return 0; } - memset(irq2host, 0, sizeof(irq2host)); - - for (index = 0; pcibios_find_device(PCI_VENDOR_ID_QLOGIC, - PCI_DEVICE_ID_QLOGIC_ISP1020, - index, &bus, &device_fn) == 0; - index++) + while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, pdev))) { host = scsi_register(tmpt, sizeof(struct isp1020_hostdata)); hostdata = (struct isp1020_hostdata *) host->hostdata; memset(hostdata, 0, sizeof(struct isp1020_hostdata)); - hostdata->bus = bus; - hostdata->device_fn = device_fn; + hostdata->pci_dev = pdev; if (isp1020_init(host) || isp1020_reset_hardware(host) #if USE_NVRAM_DEFAULTS @@ -598,8 +585,8 @@ host->this_id = hostdata->host_param.initiator_scsi_id; - if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT, - "qlogicisp", NULL)) + if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT | SA_SHIRQ, + "qlogicisp", host)) { printk("qlogicisp : interrupt %d already in use\n", host->irq); @@ -611,13 +598,12 @@ printk("qlogicisp : i/o region 0x%lx-0x%lx already " "in use\n", host->io_port, host->io_port + 0xff); - free_irq(host->irq, NULL); + free_irq(host->irq, host); scsi_unregister(host); continue; } request_region(host->io_port, 0xff, "qlogicisp"); - irq2host[host->irq] = host; outw(0x0, host->io_port + PCI_SEMAPHORE); outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); @@ -641,7 +627,7 @@ hostdata = (struct isp1020_hostdata *) host->hostdata; outw(0x0, host->io_port + PCI_INTF_CTL); - free_irq(host->irq, NULL); + free_irq(host->irq, host); release_region(host->io_port, 0xff); @@ -660,8 +646,8 @@ hostdata = (struct isp1020_hostdata *) host->hostdata; sprintf(buf, - "QLogic ISP1020 SCSI on PCI bus %d device %d irq %d base 0x%lx", - hostdata->bus, (hostdata->device_fn & 0xf8) >> 3, host->irq, + "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d base 0x%lx", + hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, host->io_port); LEAVE("isp1020_info"); @@ -819,18 +805,13 @@ { Scsi_Cmnd *Cmnd; struct Status_Entry *sts; - struct Scsi_Host *host; + struct Scsi_Host *host = dev_id; struct isp1020_hostdata *hostdata; u_int in_ptr, out_ptr; u_short status; ENTER_INTR("isp1020_intr_handler"); - host = irq2host[irq]; - if (!host) { - printk("qlogicisp : unexpected interrupt on line %d\n", irq); - return; - } hostdata = (struct isp1020_hostdata *) host->hostdata; DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq)); @@ -1168,53 +1149,36 @@ static int isp1020_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; + pdev = hostdata->pci_dev; - 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)) + 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; } diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.1.92/linux/drivers/scsi/scsi.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/scsi/scsi.c Wed Apr 1 20:14:32 1998 @@ -141,7 +141,7 @@ */ 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 /* diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c --- v2.1.92/linux/drivers/scsi/scsi_obsolete.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/scsi/scsi_obsolete.c Wed Apr 1 20:14:32 1998 @@ -83,7 +83,7 @@ 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)) diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c --- v2.1.92/linux/drivers/scsi/tmscsim.c Tue Mar 10 10:03:33 1998 +++ linux/drivers/scsi/tmscsim.c Thu Apr 2 09:12:25 1998 @@ -26,7 +26,7 @@ * pending interrupt in DC390_detect() * * 1.11 02/05/97 KG/CLH Fixeds problem with partitions greater * * than 1GB * - * 1.12 25/02/98 KG Cleaned up ifdefs for 2.1 kernel * + * 1.12 15/02/98 MJ Rewritten PCI probing * ***********************************************************************/ @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -118,8 +117,6 @@ static USHORT adapterCnt = 0; static USHORT InitialTime = 0; static USHORT CurrSyncOffset = 0; -static ULONG mech1addr; -static UCHAR mech2bus, mech2Agent, mech2CfgSPenR; static PVOID DC390_phase0[]={ DC390_DataOut_0, @@ -1200,147 +1197,7 @@ void -DC390_EnableCfg( USHORT mechnum, UCHAR regval ) -{ - ULONG wlval; - - if(mechnum == 2) - { - outb(mech2bus, PCI_CFG2_FORWARD_REG); - outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG); - } - else - { - regval &= 0xFC; - wlval = mech1addr; - wlval |= (((ULONG)regval) & 0xff); - outl(wlval, PCI_CFG1_ADDRESS_REG); - } -} - - -void -DC390_DisableCfg( USHORT mechnum ) -{ - - if(mechnum == 2) - outb(0, PCI_CFG2_ENABLE_REG); - else - outl(0, PCI_CFG1_ADDRESS_REG); -} - - -UCHAR -DC390_inByte( USHORT mechnum, UCHAR regval ) -{ - UCHAR bval; - ULONG wval; - ULONG flags; - - save_flags(flags); - cli(); - DC390_EnableCfg( mechnum, regval ); - if(mechnum == 2) - { - wval = mech2Agent; - wval <<= 8; - wval |= ((USHORT) regval) & 0xff; - bval = inb(wval); - } - else - { - regval &= 3; - bval = inb(PCI_CFG1_DATA_REG | regval); - } - DC390_DisableCfg(mechnum); - restore_flags(flags); - return(bval); -} - - -USHORT -DC390_inWord( USHORT mechnum, UCHAR regval ) -{ - USHORT wval; - ULONG flags; - - save_flags(flags); - cli(); - DC390_EnableCfg(mechnum,regval); - if(mechnum == 2) - { - wval = mech2Agent; - wval <<= 8; - wval |= regval; - wval = inw(wval); - } - else - { - regval &= 3; - wval = inw(PCI_CFG1_DATA_REG | regval); - } - DC390_DisableCfg(mechnum); - restore_flags(flags); - return(wval); -} - - -ULONG -DC390_inDword(USHORT mechnum, UCHAR regval ) -{ - ULONG wlval; - ULONG flags; - USHORT wval; - - save_flags(flags); - cli(); - DC390_EnableCfg(mechnum,regval); - if(mechnum == 2) - { - wval = mech2Agent; - wval <<= 8; - wval |= regval; - wlval = inl(wval); - } - else - { - wlval = inl(PCI_CFG1_DATA_REG); - } - DC390_DisableCfg(mechnum); - restore_flags(flags); - return(wlval); -} - - -void -DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ) -{ - - USHORT wval; - ULONG flags; - - save_flags(flags); - cli(); - DC390_EnableCfg(mechnum,regval); - if(mechnum == 2) - { - wval = mech2Agent; - wval <<= 8; - wval |= regval; - outb(bval, wval); - } - else - { - regval &= 3; - outb(bval, PCI_CFG1_DATA_REG | regval); - } - DC390_DisableCfg(mechnum); - restore_flags(flags); -} - - -void -DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ) +DC390_EnDisableCE( UCHAR mode, struct pci_dev *pdev, PUCHAR regval ) { UCHAR bval; @@ -1350,15 +1207,15 @@ *regval = 0xc0; else *regval = 0x80; - DC390_OutB(mechnum,*regval,bval); + pci_write_config_byte(pdev, *regval, bval); if(mode == DISABLE_CE) - DC390_OutB(mechnum,*regval,bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); } void -DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ) +DC390_EEpromOutDI( struct pci_dev *pdev, PUCHAR regval, USHORT Carry ) { UCHAR bval; @@ -1367,32 +1224,28 @@ { bval = 0x40; *regval = 0x80; - DC390_OutB(mechnum,*regval,bval); + pci_write_config_byte(pdev, *regval, bval); } udelay(160); bval |= 0x80; - DC390_OutB(mechnum,*regval,bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); bval = 0; - DC390_OutB(mechnum,*regval,bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); } UCHAR -DC390_EEpromInDO( USHORT mechnum ) +DC390_EEpromInDO( struct pci_dev *pdev ) { - UCHAR bval,regval; + UCHAR bval; - regval = 0x80; - bval = 0x80; - DC390_OutB(mechnum,regval,bval); + pci_write_config_byte(pdev, 0x80, 0x80); udelay(160); - bval = 0x40; - DC390_OutB(mechnum,regval,bval); + pci_write_config_byte(pdev, 0x80, 0x40); udelay(160); - regval = 0x0; - bval = DC390_inByte(mechnum,regval); + pci_read_config_byte(pdev, 0x00, &bval); if(bval == 0x22) return(1); else @@ -1401,7 +1254,7 @@ USHORT -EEpromGetData1( USHORT mechnum ) +EEpromGetData1( struct pci_dev *pdev ) { UCHAR i; UCHAR carryFlag; @@ -1411,7 +1264,7 @@ for(i=0; i<16; i++) { wval <<= 1; - carryFlag = DC390_EEpromInDO(mechnum); + carryFlag = DC390_EEpromInDO(pdev); wval |= carryFlag; } return(wval); @@ -1419,7 +1272,7 @@ void -DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ) +DC390_Prepare( struct pci_dev *pdev, PUCHAR regval, UCHAR EEpromCmd ) { UCHAR i,j; USHORT carryFlag; @@ -1428,7 +1281,7 @@ j = 0x80; for(i=0; i<9; i++) { - DC390_EEpromOutDI(mechnum,regval,carryFlag); + DC390_EEpromOutDI(pdev,regval,carryFlag); carryFlag = (EEpromCmd & j) ? 1 : 0; j >>= 1; } @@ -1436,7 +1289,7 @@ void -DC390_ReadEEprom( USHORT mechnum, USHORT index ) +DC390_ReadEEprom( struct pci_dev *pdev, int index ) { UCHAR regval,cmd; PUSHORT ptr; @@ -1446,23 +1299,23 @@ 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++) @@ -1475,30 +1328,6 @@ } -USHORT -DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum ) -{ - USHORT devnum; - - devnum = BusDevFunNum; - - if(Mechnum == 2) - { - if(devnum & 0x80) - return(-1); - mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */ - mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */ - mech2Agent |= 0xc0; - mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */ - mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20; - } - else /* use mech #1 method */ - { - mech1addr = 0x80000000 | ((ULONG)devnum << 8); - } - return(0); -} - /*********************************************************************** * Function : static int DC390_init (struct Scsi_Host *host) * @@ -1511,12 +1340,12 @@ ***********************************************************************/ __initfunc(static int -DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum)) +DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, int index)) { PSH psh; PACB pACB; - if( !DC390_CheckEEpromCheckSum( MechNum, index) ) + if( !DC390_CheckEEpromCheckSum( pdev, index ) ) { psh = scsi_register( psht, sizeof(DC390_ACB) ); if( !psh ) @@ -1594,20 +1423,10 @@ __initfunc(int DC390_detect(Scsi_Host_Template *psht)) { -#ifdef FOR_PCI_OK - UCHAR pci_bus, pci_device_fn; - int error = 0; - USHORT chipType = 0; - USHORT i; -#endif - - UCHAR irq; - UCHAR istatus; + struct pci_dev *pdev = NULL; + UINT irq; UINT io_port; USHORT adaptCnt = 0; /* Number of boards detected */ - USHORT pci_index = 0; /* Device index to PCI BIOS calls */ - USHORT MechNum, BusDevFunNum; - ULONG wlval; psht->proc_dir = &proc_scsi_tmscsim; @@ -1615,81 +1434,17 @@ 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; diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/tmscsim.h linux/drivers/scsi/tmscsim.h --- v2.1.92/linux/drivers/scsi/tmscsim.h Tue Mar 10 10:03:33 1998 +++ linux/drivers/scsi/tmscsim.h Thu Apr 2 09:12:25 1998 @@ -660,21 +660,4 @@ 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 */ diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.1.92/linux/drivers/scsi/u14-34f.c Mon Sep 15 09:41:09 1997 +++ linux/drivers/scsi/u14-34f.c Sun Apr 5 11:26:29 1998 @@ -1,6 +1,13 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 + * io_port is now unsigned long. + * + * 17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88 + * Use new scsi error handling code (if linux version >= 2.1.88). + * Use new interrupt code. + * * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 * Use of udelay inside the wait loops to avoid timeout * problems with fast cpus. @@ -113,7 +120,7 @@ * * Multiple U14F and/or U34F host adapters are supported. * - * Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com) + * Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source @@ -329,9 +336,7 @@ #undef DEBUG_LINKED_COMMANDS #undef DEBUG_DETECT #undef DEBUG_INTERRUPT -#undef DEBUG_STATISTICS #undef DEBUG_RESET -#undef DEBUG_SMP #define MAX_ISA 3 #define MAX_VESA 1 @@ -341,7 +346,6 @@ #define MAX_CHANNEL 1 #define MAX_LUN 8 #define MAX_TARGET 8 -#define MAX_IRQ 16 #define MAX_MAILBOXES 16 #define MAX_SGLIST 32 #define MAX_SAFE_SGLIST 16 @@ -349,7 +353,7 @@ #define MAX_CMD_PER_LUN 2 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN) -#define SKIP UINT_MAX +#define SKIP ULONG_MAX #define FALSE 0 #define TRUE 1 #define FREE 0 @@ -424,7 +428,6 @@ unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ unsigned int last_cp_used; /* Index of last mailbox used */ unsigned int iocount; /* Total i/o done for this board */ - unsigned int multicount; /* Total ... in second ihdlr loop */ int board_number; /* Number of this board */ char board_name[16]; /* Name of this board */ char board_id[256]; /* data from INQUIRY on this board */ @@ -443,9 +446,12 @@ static struct Scsi_Host *sh[MAX_BOARDS + 1]; static const char *driver_name = "Ux4F"; -static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; +static char sha[MAX_BOARDS]; -static unsigned int io_port[] __initdata = { +/* Initialize num_boards so that ihdlr can work while detect is in progress */ +static unsigned int num_boards = MAX_BOARDS; + +static unsigned long io_port[] __initdata = { /* Space for MAX_INT_PARAM ports usable while loading as a module */ SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, @@ -462,10 +468,10 @@ #define BN(board) (HD(board)->board_name) #define SWAP_BYTE(x) ((unsigned long)( \ - (((unsigned long)(x) & 0x000000ffU) << 24) | \ - (((unsigned long)(x) & 0x0000ff00U) << 8) | \ - (((unsigned long)(x) & 0x00ff0000U) >> 8) | \ - (((unsigned long)(x) & 0xff000000U) >> 24))) + (((unsigned long)(x) & 0x000000ffU) << 24) | \ + (((unsigned long)(x) & 0x0000ff00U) << 8) | \ + (((unsigned long)(x) & 0x00ff0000U) >> 8) | \ + (((unsigned long)(x) & 0xff000000U) >> 24))) #if defined(__BIG_ENDIAN) #define H2DEV(x) SWAP_BYTE(x) @@ -560,7 +566,7 @@ return; } -static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { +static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) { udelay(1L); @@ -614,7 +620,7 @@ } __initfunc (static inline int port_detect \ - (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) { + (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { unsigned char irq, dma_channel, subversion, i; unsigned char in_byte; char *bus_type, dma_name[16]; @@ -637,8 +643,8 @@ unsigned char heads; unsigned char sectors; } mapping_table[4] = { - { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } - }; + { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } + }; struct config_1 { unsigned char bios_segment: 3; @@ -659,7 +665,7 @@ sprintf(name, "%s%d", driver_name, j); if(check_region(port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base); + printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); return FALSE; } @@ -676,17 +682,18 @@ dma_channel = dma_channel_table[config_1.dma_channel]; subversion = (in_byte & 0x0f); - /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq, - u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { + /* Board detected, allocate its IRQ */ + if (request_irq(irq, u14_34f_interrupt_handler, + SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), + driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); return FALSE; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - free_irq(irq, NULL); + name, dma_channel); + free_irq(irq, &sha[j]); return FALSE; } @@ -695,7 +702,7 @@ if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); - if (!irqlist[irq]) free_irq(irq, NULL); + free_irq(irq, &sha[j]); if (subversion == ISA) free_dma(dma_channel); @@ -734,7 +741,6 @@ HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors; HD(j)->subversion = subversion; HD(j)->board_number = j; - irqlist[irq]++; if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST; @@ -767,12 +773,12 @@ HD(j)->board_id[40] = 0; if (strcmp(&HD(j)->board_id[32], "06000600")) { - printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]); - printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n", - BN(j), &HD(j)->board_id[32]); - sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; - sh[j]->sg_tablesize = MAX_SAFE_SGLIST; - } + printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]); + printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n", + BN(j), &HD(j)->board_id[32]); + sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; + sh[j]->sg_tablesize = MAX_SAFE_SGLIST; + } } if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); @@ -792,10 +798,11 @@ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; - printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\ - "lc:%c, mq:%d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base, - sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue, - YESNO(have_old_firmware), YESNO(linked_comm), max_queue_depth); + printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\ + "lc:%c, mq:%d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port, + (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize, + sh[j]->can_queue, YESNO(have_old_firmware), YESNO(linked_comm), + max_queue_depth); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", @@ -857,11 +864,6 @@ } #endif - for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = 0; - calls[k] = 0; - } - for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; for (k = 0; io_port[k]; k++) { @@ -872,8 +874,9 @@ } if (j > 0) - printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n"); + printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n"); + num_boards = j; restore_flags(flags); return j; } @@ -938,26 +941,26 @@ if (i >= sh[j]->can_queue) i = 0; if (HD(j)->cp_stat[i] == FREE) { - HD(j)->last_cp_used = i; - break; - } + HD(j)->last_cp_used = i; + break; + } } if (k == sh[j]->can_queue) { printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); + printk("%s: qcomm, already in reset.\n", BN(j)); else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); + panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); SCpnt->result = DID_BUS_BUSY << 16; SCpnt->host_scribble = NULL; printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); restore_flags(flags); done(SCpnt); - return 0; + return 1; } /* Set pointer to control packet structure */ @@ -969,16 +972,16 @@ SCpnt->host_scribble = (unsigned char *) &cpp->index; if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCpnt->channel, SCpnt->target, + BN(j), i, SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); cpp->xdir = DTD_IN; for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->xdir = DTD_OUT; - break; - } + cpp->xdir = DTD_OUT; + break; + } if (cpp->xdir == DTD_IN) for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) @@ -1023,7 +1026,7 @@ SCpnt->pid); restore_flags(flags); done(SCpnt); - return 0; + return 1; } /* Store pointer in OGM address bytes */ @@ -1048,14 +1051,14 @@ if (SCarg->host_scribble == NULL || SCarg->serial_number != SCarg->serial_number_at_timeout) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } i = *(unsigned int *)SCarg->host_scribble; printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -1076,8 +1079,8 @@ printk("%s: abort, mbox %d is in use.\n", BN(j), i); if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", + BN(j), i, SCarg, HD(j)->cp[i].SCpnt); if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); @@ -1103,7 +1106,7 @@ SCarg->host_scribble = NULL; HD(j)->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); + BN(j), i, SCarg->pid); SCarg->scsi_done(SCarg); restore_flags(flags); return SCSI_ABORT_SUCCESS; @@ -1123,7 +1126,7 @@ cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, reset_flags); if (SCarg->host_scribble == NULL) @@ -1160,13 +1163,13 @@ if (HD(j)->cp_stat[i] == FREE) continue; if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } + HD(j)->cp_stat[i] = FREE; + printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); + continue; + } if (!(SCpnt = HD(j)->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); + panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { HD(j)->cp_stat[i] = ABORTING; @@ -1181,13 +1184,13 @@ } if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); + panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); + panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); + panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); if (SCpnt == SCarg) arg_done = TRUE; } @@ -1223,7 +1226,7 @@ HD(j)->cp_stat[i] = LOCKED; printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->pid); } else if (HD(j)->cp_stat[i] == ABORTING) { @@ -1235,7 +1238,7 @@ HD(j)->cp_stat[i] = FREE; printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->pid); } else @@ -1428,224 +1431,182 @@ } } -static void 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); + + 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 (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); + if (linked_comm && SCpnt->device->queue_depth > 2 + && TLDEV(SCpnt->device->type)) + flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE); - /* Service all the boards configured on this irq */ - for (j = 0; sh[j] != NULL; j++) { + tstatus = status_byte(spp->target_status); - if (sh[j]->irq != irq) continue; + switch (spp->adapter_status) { + case ASOK: /* status OK */ - loops = 0; - - /* 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); - - 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; - 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; - + /* 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; - case 0x92: /* Data over/under-run */ + else + status = DID_OK << 16; - 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; - } + if (tstatus == GOOD) + HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; - SCpnt->result = status | spp->target_status; - HD(j)->iocount++; + 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]); - if (loops > 1) HD(j)->multicount++; + HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0; -#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 (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; + break; + case ASST: /* Selection Time Out */ - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); + 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]++; + } - } /* Multiple command loop */ + break; - } /* Boards loop */ + /* 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; + - calls[irq]++; + case 0x92: /* Data over/under-run */ -#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 + 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; + } - if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); + SCpnt->result = status | spp->target_status; + HD(j)->iocount++; -#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); +#if defined (DEBUG_INTERRUPT) + if (SCpnt->result || do_trace) +#else + if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || + (spp->adapter_status != ASOK && + spp->adapter_status != ASST && HD(j)->iocount <= 1000) || + do_trace || msg_byte(spp->target_status)) #endif + printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ + " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", + BN(j), i, spp->adapter_status, spp->target_status, + SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, + reg, HD(j)->iocount); + + /* Set the command state to inactive */ + SCpnt->host_scribble = NULL; + + SCpnt->scsi_done(SCpnt); + + if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, + HD(j)->iocount); - restore_flags(flags); return; } @@ -1664,7 +1625,7 @@ 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); diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- v2.1.92/linux/drivers/scsi/u14-34f.h Sun Dec 21 17:04:49 1997 +++ linux/drivers/scsi/u14-34f.h Sun Apr 5 11:26:29 1998 @@ -11,18 +11,41 @@ int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "3.11.00" +#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 -#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 \ - } #endif diff -u --recursive --new-file v2.1.92/linux/fs/Config.in linux/fs/Config.in --- v2.1.92/linux/fs/Config.in Tue Mar 10 10:03:33 1998 +++ linux/fs/Config.in Sat Apr 4 09:45:14 1998 @@ -62,7 +62,7 @@ tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS tristate 'Apple Macintosh filesystem support (experimental)' CONFIG_HFS_FS tristate 'ROM filesystem support' CONFIG_ROMFS_FS -tristate 'Kernel automounter support (experimental)' CONFIG_AUTOFS_FS +tristate 'Kernel automounter support' CONFIG_AUTOFS_FS if [ "$CONFIG_AFFS_FS" != "n" ]; then define_bool CONFIG_AMIGA_PARTITION y fi @@ -74,6 +74,7 @@ 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 diff -u --recursive --new-file v2.1.92/linux/fs/Makefile linux/fs/Makefile --- v2.1.92/linux/fs/Makefile Tue Jan 20 16:44:57 1998 +++ linux/fs/Makefile Sat Apr 4 09:45:14 1998 @@ -17,7 +17,8 @@ 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 @@ -223,6 +224,14 @@ else ifeq ($(CONFIG_ADFS_FS),m) MOD_SUB_DIRS += adfs + endif +endif + +ifeq ($(CONFIG_DEVPTS_FS),y) +SUB_DIRS += devpts +else + ifeq ($(CONFIG_DEVPTS_FS),m) + MOD_SUB_DIRS += devpts endif endif diff -u --recursive --new-file v2.1.92/linux/fs/adfs/super.c linux/fs/adfs/super.c --- v2.1.92/linux/fs/adfs/super.c Mon Feb 23 18:12:10 1998 +++ linux/fs/adfs/super.c Sat Apr 4 09:45:14 1998 @@ -98,13 +98,11 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/fs/affs/super.c linux/fs/affs/super.c --- v2.1.92/linux/fs/affs/super.c Tue Mar 10 10:03:33 1998 +++ linux/fs/affs/super.c Sat Apr 4 09:45:14 1998 @@ -46,7 +46,6 @@ pr_debug("affs_put_super()\n"); - lock_super(sb); for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); if (!(sb->s_flags & MS_RDONLY)) { @@ -67,8 +66,6 @@ */ set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize); - sb->s_dev = 0; - unlock_super(sb); MOD_DEC_USE_COUNT; return; } diff -u --recursive --new-file v2.1.92/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.1.92/linux/fs/autofs/inode.c Fri Aug 15 10:01:29 1997 +++ linux/fs/autofs/inode.c Sat Apr 4 09:45:14 1998 @@ -41,16 +41,13 @@ 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")); diff -u --recursive --new-file v2.1.92/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.1.92/linux/fs/autofs/root.c Tue Feb 3 18:26:29 1998 +++ linux/fs/autofs/root.c Sat Apr 4 09:45:14 1998 @@ -109,8 +109,7 @@ if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) { do { if ( status && dentry->d_inode ) { - printk("autofs: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name); - printk("autofs: trying to recover, but prepare for Armageddon\n"); + printk("autofs warning: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name); break; } @@ -146,7 +145,10 @@ return !autofs_wait(sbi, &dentry->d_name); } - autofs_update_usage(&sbi->dirhash,ent); + /* We don't update the usages for the autofs daemon itself, this + is necessary for recursive autofs mounts */ + if ( !autofs_oz_mode(sbi) ) + autofs_update_usage(&sbi->dirhash,ent); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; return 1; @@ -188,8 +190,10 @@ } /* 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; } diff -u --recursive --new-file v2.1.92/linux/fs/coda/inode.c linux/fs/coda/inode.c --- v2.1.92/linux/fs/coda/inode.c Tue Mar 17 22:18:15 1998 +++ linux/fs/coda/inode.c Sat Apr 4 09:45:14 1998 @@ -161,9 +161,6 @@ ENTRY; - lock_super(sb); - - sb->s_dev = 0; coda_cache_clear_all(sb); sb_info = coda_sbp(sb); sb_info->sbi_vcomm->vc_inuse = 0; @@ -171,7 +168,6 @@ printk("Coda: Bye bye.\n"); memset(sb_info, 0, sizeof(* sb_info)); - unlock_super(sb); MOD_DEC_USE_COUNT; EXIT; } diff -u --recursive --new-file v2.1.92/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.92/linux/fs/dcache.c Wed Apr 1 20:11:53 1998 +++ linux/fs/dcache.c Thu Apr 2 21:23:19 1998 @@ -780,16 +780,26 @@ 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); + struct dentry *pwd = current->fs->pwd; - error = -ERANGE; - len = PAGE_SIZE + page - cwd; - if (len <= size) { - error = len; - if (copy_to_user(buf, cwd, len)) - error = -EFAULT; + error = -ENOENT; + /* Has the current directory has been unlinked? */ + if (pwd->d_parent != pwd && list_empty(&pwd->d_hash)) { + char *page = (char *) __get_free_page(GFP_USER); + error = -ENOMEM; + if (page) { + unsigned long len; + char * cwd = d_path(pwd, page, PAGE_SIZE); + + error = -ERANGE; + len = PAGE_SIZE + page - cwd; + if (len <= size) { + error = len; + if (copy_to_user(buf, cwd, len)) + error = -EFAULT; + } + free_page((unsigned long) page); + } } return error; } diff -u --recursive --new-file v2.1.92/linux/fs/devpts/Makefile linux/fs/devpts/Makefile --- v2.1.92/linux/fs/devpts/Makefile Wed Dec 31 16:00:00 1969 +++ linux/fs/devpts/Makefile Sat Apr 4 09:45:15 1998 @@ -0,0 +1,10 @@ +# +# Makefile for the linux /dev/pts virtual filesystem. +# + +O_TARGET := devpts.o +O_OBJS := root.o inode.o + +M_OBJS := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.92/linux/fs/devpts/devpts_i.h linux/fs/devpts/devpts_i.h --- v2.1.92/linux/fs/devpts/devpts_i.h Wed Dec 31 16:00:00 1969 +++ linux/fs/devpts/devpts_i.h Sat Apr 4 09:45:15 1998 @@ -0,0 +1,42 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/devpts_i.h + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include +#include +#include + +#define BUILDING_DEVPTS 1 +#include + +struct devpts_sb_info { + u32 magic; + struct super_block *next; + struct super_block **back; + int setuid; + int setgid; + uid_t uid; + gid_t gid; + umode_t mode; + + struct inode *inodes[NR_PTYS]; +}; + +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define DEVPTS_SBI_MAGIC 0x01da1d02 + +extern inline struct devpts_sb_info *SBI(struct super_block *sb) +{ + return (struct devpts_sb_info *)(sb->u.generic_sbp); +} + +extern struct inode_operations devpts_root_inode_operations; +extern struct inode_operations devpts_device_inode_operations; diff -u --recursive --new-file v2.1.92/linux/fs/devpts/inode.c linux/fs/devpts/inode.c --- v2.1.92/linux/fs/devpts/inode.c Wed Dec 31 16:00:00 1969 +++ linux/fs/devpts/inode.c Sat Apr 4 09:45:15 1998 @@ -0,0 +1,374 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/inode.c + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devpts_i.h" + +static struct super_block *mounts = NULL; + +static void devpts_put_inode(struct inode *inode) +{ +} + +static void devpts_delete_inode(struct inode *inode) +{ + inode->i_size = 0; +} + +static void devpts_put_super(struct super_block *sb) +{ + struct devpts_sb_info *sbi = SBI(sb); + struct inode *inode; + int i; + + for ( i = 0 ; i < NR_PTYS ; i++ ) { + if ( (inode = sbi->inodes[i]) ) { + if ( inode->i_count != 1 ) + printk("devpts_put_super: badness: entry %d count %d\n", + i, inode->i_count); + iput(inode); + } + } + + *sbi->back = sbi->next; + if ( sbi->next ) + SBI(sbi->next)->back = sbi->back; + + kfree(sbi); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static void devpts_read_inode(struct inode *inode); +static void devpts_write_inode(struct inode *inode); + +static struct super_operations devpts_sops = { + devpts_read_inode, + devpts_write_inode, + devpts_put_inode, + devpts_delete_inode, + NULL, /* notify_change */ + devpts_put_super, + NULL, /* write_super */ + devpts_statfs, + NULL, /* remount_fs */ + NULL, /* clear_inode */ +}; + +static int devpts_parse_options(char *options, struct devpts_sb_info *sbi) +{ + int setuid = 0; + int setgid = 0; + uid_t uid = 0; /* To shut up gcc */ + gid_t gid = 0; + umode_t mode = 0600; + char *this_char, *value; + + if ( !options ) return 1; + for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + if (!strcmp(this_char,"uid")) { + if (!value || !*value) + return 1; + uid = simple_strtoul(value,&value,0); + if (*value) + return 1; + setuid = 1; + } + else if (!strcmp(this_char,"gid")) { + if (!value || !*value) + return 1; + gid = simple_strtoul(value,&value,0); + if (*value) + return 1; + setgid = 1; + } + else if (!strcmp(this_char,"mode")) { + if (!value || !*value) + return 1; + mode = simple_strtoul(value,&value,8); + if (*value) + return 1; + } + else + return 1; + } + sbi->setuid = setuid; + sbi->setgid = setgid; + sbi->uid = uid; + sbi->gid = gid; + sbi->mode = mode & ~S_IFMT; + + return 0; +} + +struct super_block *devpts_read_super(struct super_block *s, void *data, + int silent) +{ + struct inode * root_inode; + struct dentry * root; + struct devpts_sb_info *sbi; + + MOD_INC_USE_COUNT; + + lock_super(s); + /* Super block already completed? */ + if (s->s_root) + goto out_unlock; + + sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL); + if ( !sbi ) + goto fail_unlock; + + sbi->magic = DEVPTS_SBI_MAGIC; + memset(sbi->inodes, 0, sizeof sbi->inodes); + + s->u.generic_sbp = (void *) sbi; + s->s_blocksize = 1024; + s->s_blocksize_bits = 10; + s->s_magic = DEVPTS_SUPER_MAGIC; + s->s_op = &devpts_sops; + s->s_root = NULL; + unlock_super(s); /* shouldn't we keep it locked a while longer? */ + + /* + * Get the root inode and dentry, but defer checking for errors. + */ + root_inode = iget(s, 1); /* inode 1 == root directory */ + root = d_alloc_root(root_inode, NULL); + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dput; + + if (!root) + goto fail_iput; + + /* Can this call block? (It shouldn't) */ + if ( devpts_parse_options(data,sbi) ) { + printk("devpts: called with bogus options\n"); + goto fail_dput; + } + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dec; + + /* + * Success! Install the root dentry now to indicate completion. + */ + lock_super(s); + s->s_root = root; + + sbi->next = mounts; + if ( sbi->next ) + SBI(sbi->next)->back = &(sbi->next); + sbi->back = &mounts; + mounts = s; + + unlock_super(s); + return s; + + /* + * Success ... somebody else completed the super block for us. + */ +out_unlock: + unlock_super(s); + goto out_dec; +out_dput: + if (root) + dput(root); + else + iput(root_inode); +out_dec: + MOD_DEC_USE_COUNT; + return s; + + /* + * Failure ... clear the s_dev slot and clean up. + */ +fail_dput: + /* + * dput() can block, so we clear the super block first. + */ + s->s_dev = 0; + dput(root); + goto fail_free; +fail_iput: + printk("devpts: get root dentry failed\n"); + /* + * iput() can block, so we clear the super block first. + */ + s->s_dev = 0; + iput(root_inode); +fail_free: + kfree(sbi); + goto fail_dec; +fail_unlock: + unlock_super(s); +fail_dec: + s->s_dev = 0; + MOD_DEC_USE_COUNT; + return NULL; +} + +static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +{ + struct statfs tmp; + + tmp.f_type = DEVPTS_SUPER_MAGIC; + tmp.f_bsize = 1024; + tmp.f_blocks = 0; + tmp.f_bfree = 0; + tmp.f_bavail = 0; + tmp.f_files = 0; + tmp.f_ffree = 0; + tmp.f_namelen = NAME_MAX; + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; +} + +static void devpts_read_inode(struct inode *inode) +{ + ino_t ino = inode->i_ino; + + inode->i_op = NULL; + inode->i_mode = 0; + inode->i_nlink = 0; + inode->i_size = 0; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_blocks = 0; + inode->i_blksize = 1024; + inode->i_uid = inode->i_gid = 0; + + if ( ino == 1 ) { + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; + inode->i_op = &devpts_root_inode_operations; + inode->i_nlink = 2; + return; + } + + ino -= 2; + if ( ino >= NR_PTYS ) + return; /* Bogus */ + + inode->i_nlink = 1; + + inode->i_mode = S_IFCHR; + inode->i_rdev = MKDEV(0,0); /* Gets filled in by devpts_pty_new() */ + + inode->i_op = &chrdev_inode_operations; + + return; +} + +static void devpts_write_inode(struct inode *inode) +{ +} + +static struct file_system_type devpts_fs_type = { + "devpts", + 0, + devpts_read_super, + NULL +}; + +void devpts_pty_new(int number, kdev_t device) +{ + struct super_block *sb; + struct devpts_sb_info *sbi; + struct inode *inode; + + for ( sb = mounts ; sb ; sb = sbi->next ) { + sbi = SBI(sb); + + if ( sbi->inodes[number] ) { + continue; /* Already registered, this does happen */ + } + + /* Yes, this looks backwards, but it is correct */ + inode = iget(sb, number+2); + if ( inode ) { + inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid; + inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; + inode->i_mode = sbi->mode | S_IFCHR; + inode->i_rdev = device; + sbi->inodes[number] = inode; + } + } +} + +void devpts_pty_kill(int number) +{ + struct super_block *sb; + struct devpts_sb_info *sbi; + struct inode *inode; + + for ( sb = mounts ; sb ; sb = sbi->next ) { + sbi = SBI(sb); + + inode = sbi->inodes[number]; + + if ( inode ) { + sbi->inodes[number] = NULL; + inode->i_nlink = 0; /* Is this right? */ + iput(inode); + } + } +} + +__initfunc(int init_devpts_fs(void)) +{ + return register_filesystem(&devpts_fs_type); + +} + +#ifdef MODULE + +int init_module(void) +{ + int err = init_devpts_fs(); + if ( !err ) { + devpts_upcall_new = devpts_pty_new; + devpts_upcall_kill = devpts_pty_kill; + } + return err; +} + +void cleanup_module(void) +{ + devpts_upcall_new = NULL; + devpts_upcall_kill = NULL; + unregister_filesystem(&devpts_fs_type); +} + +#endif diff -u --recursive --new-file v2.1.92/linux/fs/devpts/root.c linux/fs/devpts/root.c --- v2.1.92/linux/fs/devpts/root.c Wed Dec 31 16:00:00 1969 +++ linux/fs/devpts/root.c Sat Apr 4 09:45:15 1998 @@ -0,0 +1,169 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/fs/devpts/root.c + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +#include +#include +#include +#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/; 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; +} diff -u --recursive --new-file v2.1.92/linux/fs/exec.c linux/fs/exec.c --- v2.1.92/linux/fs/exec.c Wed Apr 1 20:11:53 1998 +++ linux/fs/exec.c Thu Apr 2 09:04:00 1998 @@ -684,15 +684,8 @@ 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 || diff -u --recursive --new-file v2.1.92/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c --- v2.1.92/linux/fs/ext2/balloc.c Sun Dec 21 17:41:24 1997 +++ linux/fs/ext2/balloc.c Thu Apr 2 13:39:52 1998 @@ -38,27 +38,33 @@ #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) -static struct ext2_group_desc * get_group_desc (struct super_block * sb, - unsigned int block_group, - struct buffer_head ** bh) +struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb, + unsigned int block_group, + struct buffer_head ** bh) { unsigned long group_desc; unsigned long desc; struct ext2_group_desc * gdp; - if (block_group >= sb->u.ext2_sb.s_groups_count) - ext2_panic (sb, "get_group_desc", + if (block_group >= sb->u.ext2_sb.s_groups_count) { + ext2_error (sb, "ext2_get_group_desc", "block_group >= groups_count - " "block_group = %d, groups_count = %lu", block_group, sb->u.ext2_sb.s_groups_count); + return NULL; + } + group_desc = block_group / EXT2_DESC_PER_BLOCK(sb); desc = block_group % EXT2_DESC_PER_BLOCK(sb); - if (!sb->u.ext2_sb.s_group_desc[group_desc]) - ext2_panic (sb, "get_group_desc", + if (!sb->u.ext2_sb.s_group_desc[group_desc]) { + ext2_error (sb, "ext2_get_group_desc", "Group descriptor not loaded - " "block_group = %d, group_desc = %lu, desc = %lu", block_group, group_desc, desc); + return NULL; + } + gdp = (struct ext2_group_desc *) sb->u.ext2_sb.s_group_desc[group_desc]->b_data; if (bh) @@ -66,22 +72,40 @@ return gdp + desc; } -static void read_block_bitmap (struct super_block * sb, +/* + * Read the bitmap for a given block_group, reading into the specified + * slot in the superblock's bitmap cache. + * + * Return >=0 on success or a -ve error code. + */ + +static int read_block_bitmap (struct super_block * sb, unsigned int block_group, unsigned long bitmap_nr) { struct ext2_group_desc * gdp; - struct buffer_head * bh; + struct buffer_head * bh = NULL; + int retval = 0; - gdp = get_group_desc (sb, block_group, NULL); + gdp = ext2_get_group_desc (sb, block_group, NULL); + if (!gdp) + goto error_out; bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize); - if (!bh) - ext2_panic (sb, "read_block_bitmap", + if (!bh) { + ext2_error (sb, "read_block_bitmap", "Cannot read block bitmap - " "block_group = %d, block_bitmap = %lu", - block_group, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap)); + block_group, (unsigned long) gdp->bg_block_bitmap); + retval = -EIO; + } + /* + * On IO error, just leave a zero in the superblock's block pointer for + * this group. The IO will be retried next time. + */ +error_out: sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group; sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh; + return retval; } /* @@ -94,11 +118,13 @@ * 1/ There is one cache per mounted file system. * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups, * this function reads the bitmap without maintaining a LRU cache. + * + * Return the slot used to store the bitmap, or a -ve error code. */ static int load__block_bitmap (struct super_block * sb, unsigned int block_group) { - int i, j; + int i, j, retval = 0; unsigned long block_bitmap_number; struct buffer_head * block_bitmap; @@ -110,16 +136,16 @@ if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) { if (sb->u.ext2_sb.s_block_bitmap[block_group]) { - if (sb->u.ext2_sb.s_block_bitmap_number[block_group] != + if (sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group) - ext2_panic (sb, "load_block_bitmap", - "block_group != block_bitmap_number"); - else return block_group; - } else { - read_block_bitmap (sb, block_group, block_group); - return block_group; + ext2_error (sb, "load_block_bitmap", + "block_group != block_bitmap_number"); } + retval = read_block_bitmap (sb, block_group, block_group); + if (retval < 0) + return retval; + return block_group; } for (i = 0; i < sb->u.ext2_sb.s_loaded_block_bitmaps && @@ -137,6 +163,14 @@ } sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number; sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap; + + /* + * There's still one special case here --- if block_bitmap == 0 + * then our last attempt to read the bitmap failed and we have + * just ended up caching that failure. Try again to read it. + */ + if (!block_bitmap) + retval = read_block_bitmap (sb, block_group, 0); } else { if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED) sb->u.ext2_sb.s_loaded_block_bitmaps++; @@ -148,24 +182,71 @@ sb->u.ext2_sb.s_block_bitmap[j] = sb->u.ext2_sb.s_block_bitmap[j - 1]; } - read_block_bitmap (sb, block_group, 0); + retval = read_block_bitmap (sb, block_group, 0); } - return 0; + return retval; } +/* + * Load the block bitmap for a given block group. First of all do a couple + * of fast lookups for common cases and then pass the request onto the guts + * of the bitmap loader. + * + * Return the slot number of the group in the superblock bitmap cache's on + * success, or a -ve error code. + * + * There is still one inconsistancy here --- if the number of groups in this + * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of + * differentiating between a group for which we have never performed a bitmap + * IO request, and a group for which the last bitmap read request failed. + */ static inline int load_block_bitmap (struct super_block * sb, unsigned int block_group) { - if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 && - sb->u.ext2_sb.s_block_bitmap_number[0] == block_group) - return 0; + int slot; - if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && - sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group && - sb->u.ext2_sb.s_block_bitmap[block_group]) - return block_group; + /* + * Do the lookup for the slot. First of all, check if we're asking + * for the same slot as last time, and did we succeed that last time? + */ + if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 && + sb->u.ext2_sb.s_block_bitmap_number[0] == block_group && + sb->u.ext2_sb.s_block_bitmap[block_group]) { + slot = 0; + } + /* + * Or can we do a fast lookup based on a loaded group on a filesystem + * small enough to be mapped directly into the superblock? + */ + else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && + sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group && + sb->u.ext2_sb.s_block_bitmap[block_group]) { + slot = block_group; + } + /* + * If not, then do a full lookup for this block group. + */ + else { + slot = load__block_bitmap (sb, block_group); + } - return load__block_bitmap (sb, block_group); + /* + * <0 means we just got an error + */ + if (slot < 0) + return slot; + + /* + * If it's a valid slot, we may still have cached a previous IO error, + * in which case the bh in the superblock cache will be zero. + */ + if (!sb->u.ext2_sb.s_block_bitmap[slot]) + return -EIO; + + /* + * Must have been read in OK to get this far. + */ + return slot; } void ext2_free_blocks (const struct inode * inode, unsigned long block, @@ -194,8 +275,7 @@ ext2_error (sb, "ext2_free_blocks", "Freeing blocks not in datazone - " "block = %lu, count = %lu", block, count); - unlock_super (sb); - return; + goto error_return; } ext2_debug ("freeing block %lu\n", block); @@ -215,8 +295,13 @@ count -= overflow; } bitmap_nr = load_block_bitmap (sb, block_group); + if (bitmap_nr < 0) + goto error_return; + bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; - gdp = get_group_desc (sb, block_group, &bh2); + gdp = ext2_get_group_desc (sb, block_group, &bh2); + if (!gdp) + goto error_return; if (test_opt (sb, CHECK_STRICT) && (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) || @@ -259,6 +344,7 @@ goto do_more; } sb->s_dirt = 1; +error_return: unlock_super (sb); return; } @@ -312,7 +398,10 @@ goal >= le32_to_cpu(es->s_blocks_count)) goal = le32_to_cpu(es->s_first_data_block); i = (goal - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb); - gdp = get_group_desc (sb, i, &bh2); + gdp = ext2_get_group_desc (sb, i, &bh2); + if (!gdp) + goto io_error; + if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) { j = ((goal - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb)); #ifdef EXT2FS_DEBUG @@ -320,6 +409,9 @@ goal_attempts++; #endif bitmap_nr = load_block_bitmap (sb, i); + if (bitmap_nr < 0) + goto io_error; + bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; ext2_debug ("goal is at %d:%d.\n", i, j); @@ -384,7 +476,12 @@ i++; if (i >= sb->u.ext2_sb.s_groups_count) i = 0; - gdp = get_group_desc (sb, i, &bh2); + gdp = ext2_get_group_desc (sb, i, &bh2); + if (!gdp) { + *err = -EIO; + unlock_super (sb); + return 0; + } if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) break; } @@ -393,6 +490,9 @@ return 0; } bitmap_nr = load_block_bitmap (sb, i); + if (bitmap_nr < 0) + goto io_error; + bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3); j = (r - bh->b_data) << 3; @@ -455,10 +555,16 @@ */ #ifdef EXT2_PREALLOCATE if (prealloc_block) { + int prealloc_goal; + + prealloc_goal = es->s_prealloc_blocks ? + es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS; + *prealloc_count = 0; *prealloc_block = tmp + 1; for (k = 1; - k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) { + k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); + k++) { if (sb->dq_op) if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize))) break; @@ -516,6 +622,12 @@ unlock_super (sb); *err = 0; return j; + +io_error: + *err = -EIO; + unlock_super (sb); + return 0; + } unsigned long ext2_count_free_blocks (struct super_block * sb) @@ -533,9 +645,14 @@ bitmap_count = 0; gdp = NULL; for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) { - gdp = get_group_desc (sb, i, NULL); + gdp = ext2_get_group_desc (sb, i, NULL); + if (!gdp) + continue; desc_count += le16_to_cpu(gdp->bg_free_blocks_count); bitmap_nr = load_block_bitmap (sb, i); + if (bitmap_nr < 0) + continue; + x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr], sb->s_blocksize); printk ("group %d: stored = %d, counted = %lu\n", @@ -590,12 +707,17 @@ 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)) diff -u --recursive --new-file v2.1.92/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v2.1.92/linux/fs/ext2/dir.c Tue Oct 21 08:57:29 1997 +++ linux/fs/ext2/dir.c Thu Apr 2 13:39:51 1998 @@ -75,7 +75,8 @@ }; int ext2_check_dir_entry (const char * function, struct inode * dir, - struct ext2_dir_entry * de, struct buffer_head * bh, + struct ext2_dir_entry_2 * de, + struct buffer_head * bh, unsigned long offset) { const char * error_msg = NULL; @@ -84,7 +85,7 @@ error_msg = "rec_len is smaller than minimal"; else if (le16_to_cpu(de->rec_len) % 4 != 0) error_msg = "rec_len % 4 != 0"; - else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len))) + else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len)) error_msg = "rec_len is too small for name_len"; else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) > dir->i_sb->s_blocksize) @@ -97,7 +98,7 @@ "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", dir->i_ino, error_msg, offset, (unsigned long) le32_to_cpu(de->inode), - le16_to_cpu(de->rec_len), le16_to_cpu(de->name_len)); + le16_to_cpu(de->rec_len), de->name_len); return error_msg == NULL ? 1 : 0; } @@ -108,7 +109,7 @@ unsigned long offset, blk; int i, num, stored; struct buffer_head * bh, * tmp, * bha[16]; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; struct super_block * sb; int err; struct inode *inode = filp->f_dentry->d_inode; @@ -158,7 +159,7 @@ * to make sure. */ if (filp->f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { - de = (struct ext2_dir_entry *) + de = (struct ext2_dir_entry_2 *) (bh->b_data + i); /* It's too expensive to do a full * dirent test each time round this @@ -178,7 +179,7 @@ while (!error && filp->f_pos < inode->i_size && offset < sb->s_blocksize) { - de = (struct ext2_dir_entry *) (bh->b_data + offset); + de = (struct ext2_dir_entry_2 *) (bh->b_data + offset); if (!ext2_check_dir_entry ("ext2_readdir", inode, de, bh, offset)) { /* On error, skip the f_pos to the @@ -200,7 +201,7 @@ 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; diff -u --recursive --new-file v2.1.92/linux/fs/ext2/file.c linux/fs/ext2/file.c --- v2.1.92/linux/fs/ext2/file.c Wed Apr 1 20:11:53 1998 +++ linux/fs/ext2/file.c Thu Apr 2 13:39:51 1998 @@ -13,6 +13,9 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * ext2 fs regular file handling primitives + * + * 64-bit file support on 64-bit platforms by Jakub Jelinek + * (jj@sunsite.ms.mff.cuni.cz) */ #include @@ -36,6 +39,23 @@ static long long ext2_file_lseek(struct file *, long long, int); static ssize_t ext2_file_write (struct file *, const char *, size_t, loff_t *); static int ext2_release_file (struct inode *, struct file *); +#if BITS_PER_LONG < 64 +static int ext2_open_file (struct inode *, struct file *); + +#else + +#define EXT2_MAX_SIZE(bits) \ + (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \ + (1LL << (bits - 2)) * (1LL << (bits - 2)) + \ + (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * \ + (1LL << bits)) - 1) + +static long long ext2_max_sizes[] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) +}; + +#endif /* * We have mostly NULL's here: the current defaults are ok for @@ -49,7 +69,11 @@ NULL, /* poll - default */ ext2_ioctl, /* ioctl */ generic_file_mmap, /* mmap */ +#if BITS_PER_LONG == 64 NULL, /* no special open is needed */ +#else + ext2_open_file, +#endif ext2_release_file, /* release */ ext2_sync_file, /* fsync */ NULL, /* fasync */ @@ -86,7 +110,6 @@ long long offset, int origin) { - long long retval; struct inode *inode = file->f_dentry->d_inode; switch (origin) { @@ -96,17 +119,20 @@ case 1: offset += file->f_pos; } - retval = -EINVAL; - /* make sure the offset fits in 32 bits */ - if (((unsigned long long) offset >> 32) == 0) { - if (offset != file->f_pos) { - file->f_pos = offset; - file->f_reada = 0; - file->f_version = ++event; - } - retval = offset; + if (((unsigned long long) offset >> 32) != 0) { +#if BITS_PER_LONG < 64 + return -EINVAL; +#else + if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)]) + return -EINVAL; +#endif + } + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_reada = 0; + file->f_version = ++event; } - return retval; + return offset; } static inline void remove_suid(struct inode *inode) @@ -128,7 +154,7 @@ size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - __u32 pos; + off_t pos; long block; int offset; int written, c; @@ -165,14 +191,37 @@ pos = *ppos; if (pos != *ppos) return -EINVAL; +#if BITS_PER_LONG >= 64 + if (pos > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)]) + return -EINVAL; +#endif } /* Check for overflow.. */ +#if BITS_PER_LONG < 64 if (pos > (__u32) (pos + count)) { count = ~pos; /* == 0xFFFFFFFF - pos */ if (!count) return -EFBIG; } +#else + off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)]; + + if (pos + count > max) { + count = max - pos; + if (!count) + return -EFBIG; + } + if (((pos + count) >> 32) && + !(sb->u.ext2_sb.s_es->s_feature_ro_compat & + cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) { + /* If this is the first large file created, add a flag + to the superblock */ + sb->u.ext2_sb.s_es->s_feature_ro_compat |= + cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + } +#endif /* * If a file has been opened in synchronous mode, we have to ensure @@ -265,12 +314,25 @@ /* * 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 diff -u --recursive --new-file v2.1.92/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c --- v2.1.92/linux/fs/ext2/ialloc.c Mon Sep 8 21:24:51 1997 +++ linux/fs/ext2/ialloc.c Thu Apr 2 13:39:52 1998 @@ -37,50 +37,41 @@ #include #include -static struct ext2_group_desc * get_group_desc (struct super_block * sb, - unsigned int block_group, - struct buffer_head ** bh) -{ - unsigned long group_desc; - unsigned long desc; - struct ext2_group_desc * gdp; - - if (block_group >= sb->u.ext2_sb.s_groups_count) - ext2_panic (sb, "get_group_desc", - "block_group >= groups_count - " - "block_group = %d, groups_count = %lu", - block_group, sb->u.ext2_sb.s_groups_count); - - group_desc = block_group / EXT2_DESC_PER_BLOCK(sb); - desc = block_group % EXT2_DESC_PER_BLOCK(sb); - if (!sb->u.ext2_sb.s_group_desc[group_desc]) - ext2_panic (sb, "get_group_desc", - "Group descriptor not loaded - " - "block_group = %d, group_desc = %lu, desc = %lu", - block_group, group_desc, desc); - gdp = (struct ext2_group_desc *) - sb->u.ext2_sb.s_group_desc[group_desc]->b_data; - if (bh) - *bh = sb->u.ext2_sb.s_group_desc[group_desc]; - return gdp + desc; -} - -static void read_inode_bitmap (struct super_block * sb, +/* + * Read the inode allocation bitmap for a given block_group, reading + * into the specified slot in the superblock's bitmap cache. + * + * Return >=0 on success or a -ve error code. + */ +static int read_inode_bitmap (struct super_block * sb, unsigned long block_group, unsigned int bitmap_nr) { struct ext2_group_desc * gdp; - struct buffer_head * bh; + struct buffer_head * bh = NULL; + int retval = 0; - gdp = get_group_desc (sb, block_group, NULL); + gdp = ext2_get_group_desc (sb, block_group, NULL); + if (!gdp) { + retval = -EIO; + goto error_out; + } bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize); - if (!bh) - ext2_panic (sb, "read_inode_bitmap", + if (!bh) { + ext2_error (sb, "read_inode_bitmap", "Cannot read inode bitmap - " "block_group = %lu, inode_bitmap = %lu", - block_group, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap)); + block_group, (unsigned long) gdp->bg_inode_bitmap); + retval = -EIO; + } + /* + * On IO error, just leave a zero in the superblock's block pointer for + * this group. The IO will be retried next time. + */ +error_out: sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group; sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh; + return retval; } /* @@ -93,11 +84,13 @@ * 1/ There is one cache per mounted file system. * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups, * this function reads the bitmap without maintaining a LRU cache. + * + * Return the slot used to store the bitmap, or a -ve error code. */ static int load_inode_bitmap (struct super_block * sb, unsigned int block_group) { - int i, j; + int i, j, retval = 0; unsigned long inode_bitmap_number; struct buffer_head * inode_bitmap; @@ -117,7 +110,10 @@ else return block_group; } else { - read_inode_bitmap (sb, block_group, block_group); + retval = read_inode_bitmap (sb, block_group, + block_group); + if (retval < 0) + return retval; return block_group; } } @@ -138,6 +134,15 @@ } sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number; sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap; + + /* + * There's still one special case here --- if inode_bitmap == 0 + * then our last attempt to read the bitmap failed and we have + * just ended up caching that failure. Try again to read it. + */ + if (!inode_bitmap) + retval = read_inode_bitmap (sb, block_group, 0); + } else { if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED) sb->u.ext2_sb.s_loaded_inode_bitmaps++; @@ -149,9 +154,9 @@ sb->u.ext2_sb.s_inode_bitmap[j] = sb->u.ext2_sb.s_inode_bitmap[j - 1]; } - read_inode_bitmap (sb, block_group, 0); + retval = read_inode_bitmap (sb, block_group, 0); } - return 0; + return retval; } /* @@ -212,13 +217,15 @@ ino > le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count)) { ext2_error (sb, "free_inode", "reserved inode or nonexistent inode"); - unlock_super (sb); - return; + goto error_return; } es = sb->u.ext2_sb.s_es; block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb); bitmap_nr = load_inode_bitmap (sb, block_group); + if (bitmap_nr < 0) + goto error_return; + bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; is_directory = S_ISDIR(inode->i_mode); @@ -233,12 +240,14 @@ ext2_warning (sb, "ext2_free_inode", "bit already cleared for inode %lu", ino); else { - gdp = get_group_desc (sb, block_group, &bh2); - gdp->bg_free_inodes_count = - cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1); - if (is_directory) - gdp->bg_used_dirs_count = - cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1); + gdp = ext2_get_group_desc (sb, block_group, &bh2); + if (gdp) { + gdp->bg_free_inodes_count = + cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1); + if (is_directory) + gdp->bg_used_dirs_count = + cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1); + } mark_buffer_dirty(bh2, 1); es->s_free_inodes_count = cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); @@ -250,6 +259,7 @@ wait_on_buffer (bh); } sb->s_dirt = 1; +error_return: unlock_super (sb); } @@ -317,9 +327,10 @@ /* I am not yet convinced that this next bit is necessary. i = dir->u.ext2_i.i_block_group; for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { - tmp = get_group_desc (sb, i, &bh2); - if ((le16_to_cpu(tmp->bg_used_dirs_count) << 8) < - le16_to_cpu(tmp->bg_free_inodes_count)) { + tmp = ext2_get_group_desc (sb, i, &bh2); + if (tmp && + (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < + le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } @@ -329,9 +340,10 @@ */ if (!gdp) { for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { - tmp = get_group_desc (sb, j, &bh2); - if (le16_to_cpu(tmp->bg_free_inodes_count) && - le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) { + tmp = ext2_get_group_desc (sb, j, &bh2); + if (tmp && + le16_to_cpu(tmp->bg_free_inodes_count) && + le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) { if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) > le16_to_cpu(gdp->bg_free_blocks_count))) { @@ -348,8 +360,8 @@ * Try to place the inode in its parent directory */ i = dir->u.ext2_i.i_block_group; - tmp = get_group_desc (sb, i, &bh2); - if (le16_to_cpu(tmp->bg_free_inodes_count)) + tmp = ext2_get_group_desc (sb, i, &bh2); + if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) gdp = tmp; else { @@ -361,8 +373,9 @@ i += j; if (i >= sb->u.ext2_sb.s_groups_count) i -= sb->u.ext2_sb.s_groups_count; - tmp = get_group_desc (sb, i, &bh2); - if (le16_to_cpu(tmp->bg_free_inodes_count)) { + tmp = ext2_get_group_desc (sb, i, &bh2); + if (tmp && + le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } @@ -376,8 +389,9 @@ for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) { if (++i >= sb->u.ext2_sb.s_groups_count) i = 0; - tmp = get_group_desc (sb, i, &bh2); - if (le16_to_cpu(tmp->bg_free_inodes_count)) { + tmp = ext2_get_group_desc (sb, i, &bh2); + if (tmp && + le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } @@ -391,6 +405,13 @@ return NULL; } bitmap_nr = load_inode_bitmap (sb, i); + if (bitmap_nr < 0) { + unlock_super (sb); + iput(inode); + *err = -EIO; + return NULL; + } + bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data, EXT2_INODES_PER_GROUP(sb))) < @@ -504,9 +525,14 @@ bitmap_count = 0; gdp = NULL; for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) { - gdp = get_group_desc (sb, i, NULL); + gdp = ext2_get_group_desc (sb, i, NULL); + if (!gdp) + continue; desc_count += le16_to_cpu(gdp->bg_free_inodes_count); bitmap_nr = load_inode_bitmap (sb, i); + if (bitmap_nr < 0) + continue; + x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr], EXT2_INODES_PER_GROUP(sb) / 8); printk ("group %d: stored = %d, counted = %lu\n", @@ -536,9 +562,14 @@ 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) diff -u --recursive --new-file v2.1.92/linux/fs/ext2/inode.c linux/fs/ext2/inode.c --- v2.1.92/linux/fs/ext2/inode.c Wed Apr 1 20:11:53 1998 +++ linux/fs/ext2/inode.c Thu Apr 2 13:39:52 1998 @@ -12,9 +12,12 @@ * * 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 @@ -417,9 +420,44 @@ int create, int *err) { struct buffer_head * bh; - + int prev_blocks; + + prev_blocks = inode->i_blocks; + bh = ext2_getblk (inode, block, create, err); - if (!bh || buffer_uptodate(bh)) + if (!bh) + return bh; + + /* + * If the inode has grown, and this is a directory, then perform + * preallocation of a few more blocks to try to keep directory + * fragmentation down. + */ + if (create && + S_ISDIR(inode->i_mode) && + inode->i_blocks > prev_blocks && + EXT2_HAS_COMPAT_FEATURE(inode->i_sb, + EXT2_FEATURE_COMPAT_DIR_PREALLOC)) { + int i; + struct buffer_head *tmp_bh; + + for (i = 1; + i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks; + i++) { + /* + * ext2_getblk will zero out the contents of the + * directory for us + */ + tmp_bh = ext2_getblk(inode, block+i, create, err); + if (!tmp_bh) { + brelse (bh); + return 0; + } + brelse (tmp_bh); + } + } + + if (buffer_uptodate(bh)) return bh; ll_rw_block (READ, 1, &bh); wait_on_buffer (bh); @@ -447,18 +485,23 @@ inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { ext2_error (inode->i_sb, "ext2_read_inode", "bad inode number: %lu", inode->i_ino); - return; + goto bad_inode; } block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb); - if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) - ext2_panic (inode->i_sb, "ext2_read_inode", + if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) { + ext2_error (inode->i_sb, "ext2_read_inode", "group >= groups count"); + goto bad_inode; + } group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb); desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1); bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc]; - if (!bh) - ext2_panic (inode->i_sb, "ext2_read_inode", + if (!bh) { + ext2_error (inode->i_sb, "ext2_read_inode", "Descriptor not loaded"); + goto bad_inode; + } + gdp = (struct ext2_group_desc *) bh->b_data; /* * Figure out the offset within the block group inode table @@ -467,10 +510,12 @@ EXT2_INODE_SIZE(inode->i_sb); block = le32_to_cpu(gdp[desc].bg_inode_table) + (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); - if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) - ext2_panic (inode->i_sb, "ext2_read_inode", - "unable to read i-node block - " + if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) { + ext2_error (inode->i_sb, "ext2_read_inode", + "unable to read inode block - " "inode=%lu, block=%lu", inode->i_ino, block); + goto bad_inode; + } offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1); raw_inode = (struct ext2_inode *) (bh->b_data + offset); @@ -493,7 +538,20 @@ inode->u.ext2_i.i_frag_size = raw_inode->i_fsize; inode->u.ext2_i.i_osync = 0; inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl); - inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); + if (S_ISDIR(inode->i_mode)) + inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); + else { + inode->u.ext2_i.i_dir_acl = 0; + inode->u.ext2_i.i_high_size = + le32_to_cpu(raw_inode->i_size_high); +#if BITS_PER_LONG < 64 + if (raw_inode->i_size_high) + inode->i_size = (__u32)-1; +#else + inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) + << 32; +#endif + } inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version); inode->u.ext2_i.i_block_group = block_group; inode->u.ext2_i.i_next_alloc_block = 0; @@ -542,6 +600,11 @@ inode->i_attr_flags |= ATTR_FLAG_NOATIME; inode->i_flags |= MS_NOATIME; } + return; + +bad_inode: + make_bad_inode(inode); + return; } static int ext2_update_inode(struct inode * inode, int do_sync) @@ -561,18 +624,22 @@ inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { ext2_error (inode->i_sb, "ext2_write_inode", "bad inode number: %lu", inode->i_ino); - return 0; + return -EIO; } block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb); - if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) - ext2_panic (inode->i_sb, "ext2_write_inode", + if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) { + ext2_error (inode->i_sb, "ext2_write_inode", "group >= groups count"); + return -EIO; + } group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb); desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1); bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc]; - if (!bh) - ext2_panic (inode->i_sb, "ext2_write_inode", + if (!bh) { + ext2_error (inode->i_sb, "ext2_write_inode", "Descriptor not loaded"); + return -EIO; + } gdp = (struct ext2_group_desc *) bh->b_data; /* * Figure out the offset within the block group inode table @@ -581,10 +648,12 @@ EXT2_INODE_SIZE(inode->i_sb); block = le32_to_cpu(gdp[desc].bg_inode_table) + (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); - if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) - ext2_panic (inode->i_sb, "ext2_write_inode", - "unable to read i-node block - " + if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) { + ext2_error (inode->i_sb, "ext2_write_inode", + "unable to read inode block - " "inode=%lu, block=%lu", inode->i_ino, block); + return -EIO; + } offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1; raw_inode = (struct ext2_inode *) (bh->b_data + offset); @@ -603,7 +672,16 @@ raw_inode->i_frag = inode->u.ext2_i.i_frag_no; raw_inode->i_fsize = inode->u.ext2_i.i_frag_size; raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl); - raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl); + if (S_ISDIR(inode->i_mode)) + raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl); + else { +#if BITS_PER_LONG < 64 + raw_inode->i_size_high = + cpu_to_le32(inode->u.ext2_i.i_high_size); +#else + raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); +#endif + } raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); @@ -620,7 +698,7 @@ printk ("IO error syncing ext2 inode [" "%s:%08lx]\n", kdevname(inode->i_dev), inode->i_ino); - err = -1; + err = -EIO; } } brelse (bh); diff -u --recursive --new-file v2.1.92/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c --- v2.1.92/linux/fs/ext2/ioctl.c Wed Apr 1 20:11:53 1998 +++ linux/fs/ext2/ioctl.c Thu Apr 2 13:39:52 1998 @@ -19,16 +19,18 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { - unsigned long flags; + unsigned int flags; ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); switch (cmd) { case EXT2_IOC_GETFLAGS: + flags = inode->u.ext2_i.i_flags & EXT2_FL_USER_VISIBLE; return put_user(inode->u.ext2_i.i_flags, (int *) arg); case EXT2_IOC_SETFLAGS: if (get_user(flags, (int *) arg)) - return -EFAULT; + return -EFAULT; + flags = flags & EXT2_FL_USER_MODIFIABLE; /* * The IMMUTABLE and APPEND_ONLY flags can only be changed by * the super user when the security level is zero. @@ -44,7 +46,8 @@ 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 diff -u --recursive --new-file v2.1.92/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.92/linux/fs/ext2/namei.c Mon Feb 23 18:12:10 1998 +++ linux/fs/ext2/namei.c Thu Apr 2 13:39:51 1998 @@ -14,6 +14,8 @@ * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 + * Directory entry file type support and forward compatibility hooks + * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 */ #include @@ -39,18 +41,12 @@ /* * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. */ -static int ext2_match (int len, const char * const name, - struct ext2_dir_entry * de) +static inline int ext2_match (int len, const char * const name, + struct ext2_dir_entry_2 * de) { if (!de || !le32_to_cpu(de->inode) || len > EXT2_NAME_LEN) return 0; - /* - * "" means "." ---> so paths like "/usr/lib//libc.a" work - */ - if (!len && le16_to_cpu(de->name_len) == 1 && (de->name[0] == '.') && - (de->name[1] == '\0')) - return 1; - if (len != le16_to_cpu(de->name_len)) + if (len != de->name_len) return 0; return !memcmp(name, de->name, len); } @@ -65,7 +61,7 @@ */ static struct buffer_head * ext2_find_entry (struct inode * dir, const char * const name, int namelen, - struct ext2_dir_entry ** res_dir) + struct ext2_dir_entry_2 ** res_dir) { struct super_block * sb; struct buffer_head * bh_use[NAMEI_RA_SIZE]; @@ -96,7 +92,7 @@ for (block = 0, offset = 0; offset < dir->i_size; block++) { struct buffer_head * bh; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; char * dlimit; if ((block % NAMEI_RA_BLOCKS) == 0 && toread) { @@ -105,9 +101,11 @@ } bh = bh_use[block % NAMEI_RA_SIZE]; if (!bh) { +#if 0 ext2_error (sb, "ext2_find_entry", "directory #%lu contains a hole at offset %lu", dir->i_ino, offset); +#endif offset += sb->s_blocksize; continue; } @@ -119,13 +117,13 @@ break; } - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; dlimit = bh->b_data + sb->s_blocksize; while ((char *) de < dlimit) { if (!ext2_check_dir_entry ("ext2_find_entry", dir, de, bh, offset)) goto failure; - if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) { + if (ext2_match (namelen, name, de)) { for (i = 0; i < NAMEI_RA_SIZE; ++i) { if (bh_use[i] != bh) brelse (bh_use[i]); @@ -134,7 +132,7 @@ return bh; } offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry *) + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } @@ -158,7 +156,7 @@ int ext2_lookup(struct inode * dir, struct dentry *dentry) { struct inode * inode; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; struct buffer_head * bh; if (dentry->d_name.len > EXT2_NAME_LEN) @@ -190,13 +188,13 @@ */ static struct buffer_head * ext2_add_entry (struct inode * dir, const char * name, int namelen, - struct ext2_dir_entry ** res_dir, + struct ext2_dir_entry_2 ** res_dir, int *err) { unsigned long offset; unsigned short rec_len; struct buffer_head * bh; - struct ext2_dir_entry * de, * de1; + struct ext2_dir_entry_2 * de, * de1; struct super_block * sb; *err = -EINVAL; @@ -226,7 +224,7 @@ return NULL; rec_len = EXT2_DIR_REC_LEN(namelen); offset = 0; - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; *err = -ENOSPC; while (1) { if ((char *)de >= sb->s_blocksize + bh->b_data) { @@ -243,16 +241,17 @@ ext2_debug ("creating next block\n"); - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; de->inode = le32_to_cpu(0); de->rec_len = le16_to_cpu(sb->s_blocksize); dir->i_size = offset + sb->s_blocksize; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); } else { ext2_debug ("skipping to next block\n"); - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; } } if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh, @@ -261,24 +260,25 @@ brelse (bh); return NULL; } - if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) { + if (ext2_match (namelen, name, de)) { *err = -EEXIST; brelse (bh); return NULL; } if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) || - (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)) + rec_len)) { + (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) { offset += le16_to_cpu(de->rec_len); if (le32_to_cpu(de->inode)) { - de1 = (struct ext2_dir_entry *) ((char *) de + - EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len))); + de1 = (struct ext2_dir_entry_2 *) ((char *) de + + EXT2_DIR_REC_LEN(de->name_len)); de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) - - EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len))); - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len))); + EXT2_DIR_REC_LEN(de->name_len)); + de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); de = de1; } de->inode = cpu_to_le32(0); - de->name_len = cpu_to_le16(namelen); + de->name_len = namelen; + de->file_type = 0; memcpy (de->name, name, namelen); /* * XXX shouldn't update any times until successful @@ -292,6 +292,7 @@ * and/or different from the directory change time. */ dir->i_mtime = dir->i_ctime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); dir->i_version = ++event; mark_buffer_dirty(bh, 1); @@ -300,7 +301,7 @@ return bh; } offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } brelse (bh); return NULL; @@ -310,15 +311,15 @@ * ext2_delete_entry deletes a directory entry by merging it with the * previous entry */ -static int ext2_delete_entry (struct ext2_dir_entry * dir, +static int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct buffer_head * bh) { - struct ext2_dir_entry * de, * pde; + struct ext2_dir_entry_2 * de, * pde; int i; i = 0; pde = NULL; - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; while (i < bh->b_size) { if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, de, bh, i)) @@ -333,7 +334,7 @@ } i += le16_to_cpu(de->rec_len); pde = de; - de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } return -ENOENT; } @@ -350,7 +351,7 @@ { struct inode * inode; struct buffer_head * bh; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; int err = -EIO; /* @@ -371,6 +372,9 @@ return err; } de->inode = cpu_to_le32(inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_REG_FILE; dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -386,7 +390,7 @@ { struct inode * inode; struct buffer_head * bh; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; int err = -EIO; err = -ENAMETOOLONG; @@ -400,29 +404,48 @@ inode->i_uid = current->fsuid; inode->i_mode = mode; inode->i_op = NULL; - if (S_ISREG(inode->i_mode)) + bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!bh) + goto out_no_entry; + de->inode = cpu_to_le32(inode->i_ino); + dir->i_version = ++event; + if (S_ISREG(inode->i_mode)) { inode->i_op = &ext2_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) { + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_REG_FILE; + } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext2_dir_inode_operations; if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_DIR; } - else if (S_ISLNK(inode->i_mode)) + else if (S_ISLNK(inode->i_mode)) { inode->i_op = &ext2_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_SYMLINK; + } else if (S_ISCHR(inode->i_mode)) { inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_CHRDEV; + } else if (S_ISBLK(inode->i_mode)) { inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_BLKDEV; + } else if (S_ISFIFO(inode->i_mode)) { init_fifo(inode); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_FIFO; + } if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); mark_inode_dirty(inode); - bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!bh) - goto out_no_entry; - de->inode = cpu_to_le32(inode->i_ino); - dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); @@ -445,7 +468,7 @@ { struct inode * inode; struct buffer_head * bh, * dir_block; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; int err; err = -ENAMETOOLONG; @@ -463,6 +486,7 @@ inode->i_op = &ext2_dir_inode_operations; inode->i_size = inode->i_sb->s_blocksize; + inode->i_blocks = 0; dir_block = ext2_bread (inode, 0, 1, &err); if (!dir_block) { inode->i_nlink--; /* is this nlink == 0? */ @@ -470,17 +494,22 @@ iput (inode); return err; } - inode->i_blocks = inode->i_sb->s_blocksize / 512; - de = (struct ext2_dir_entry *) dir_block->b_data; + de = (struct ext2_dir_entry_2 *) dir_block->b_data; de->inode = cpu_to_le32(inode->i_ino); - de->name_len = cpu_to_le16(1); - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len))); + de->name_len = 1; + de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); strcpy (de->name, "."); - de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_DIR; + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); de->inode = cpu_to_le32(dir->i_ino); de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1)); - de->name_len = cpu_to_le16(2); + de->name_len = 2; strcpy (de->name, ".."); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_DIR; inode->i_nlink = 2; mark_buffer_dirty(dir_block, 1); brelse (dir_block); @@ -492,6 +521,9 @@ if (!bh) goto out_no_entry; de->inode = cpu_to_le32(inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_DIR; dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -499,6 +531,7 @@ wait_on_buffer (bh); } dir->i_nlink++; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); d_instantiate(dentry, inode); brelse (bh); @@ -520,7 +553,7 @@ { unsigned long offset; struct buffer_head * bh; - struct ext2_dir_entry * de, * de1; + struct ext2_dir_entry_2 * de, * de1; struct super_block * sb; int err; @@ -532,8 +565,8 @@ inode->i_ino); return 1; } - de = (struct ext2_dir_entry *) bh->b_data; - de1 = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); + de = (struct ext2_dir_entry_2 *) bh->b_data; + de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || strcmp (".", de->name) || strcmp ("..", de1->name)) { ext2_warning (inode->i_sb, "empty_dir", @@ -542,19 +575,21 @@ return 1; } offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); - de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len)); + de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len)); while (offset < inode->i_size ) { if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err); if (!bh) { +#if 0 ext2_error (sb, "empty_dir", "directory #%lu contains a hole at offset %lu", inode->i_ino, offset); +#endif offset += sb->s_blocksize; continue; } - de = (struct ext2_dir_entry *) bh->b_data; + de = (struct ext2_dir_entry_2 *) bh->b_data; } if (!ext2_check_dir_entry ("empty_dir", inode, de, bh, offset)) { @@ -566,7 +601,7 @@ return 0; } offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } brelse (bh); return 1; @@ -577,7 +612,7 @@ int retval; struct inode * inode; struct buffer_head * bh; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; retval = -ENAMETOOLONG; if (dentry->d_name.len > EXT2_NAME_LEN) @@ -652,6 +687,7 @@ mark_inode_dirty(inode); dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); d_delete(dentry); @@ -666,7 +702,7 @@ int retval; struct inode * inode; struct buffer_head * bh; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; retval = -ENAMETOOLONG; if (dentry->d_name.len > EXT2_NAME_LEN) @@ -711,6 +747,7 @@ wait_on_buffer (bh); } dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); inode->i_nlink--; mark_inode_dirty(inode); @@ -726,7 +763,7 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname) { - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; struct inode * inode; struct buffer_head * bh = NULL, * name_block = NULL; char * link; @@ -774,6 +811,9 @@ if (!bh) goto out_no_entry; de->inode = cpu_to_le32(inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = EXT2_FT_SYMLINK; dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -797,7 +837,7 @@ struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; - struct ext2_dir_entry * de; + struct ext2_dir_entry_2 * de; struct buffer_head * bh; int err; @@ -815,6 +855,21 @@ return err; de->inode = cpu_to_le32(inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) { + if (S_ISREG(inode->i_mode)) + de->file_type = EXT2_FT_REG_FILE; + else if (S_ISDIR(inode->i_mode)) + de->file_type = EXT2_FT_DIR; + else if (S_ISLNK(inode->i_mode)) + de->file_type = EXT2_FT_SYMLINK; + else if (S_ISCHR(inode->i_mode)) + de->file_type = EXT2_FT_CHRDEV; + else if (S_ISBLK(inode->i_mode)) + de->file_type = EXT2_FT_BLKDEV; + else if (S_ISFIFO(inode->i_mode)) + de->file_type = EXT2_FT_FIFO; + } dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -831,8 +886,8 @@ } #define PARENT_INO(buffer) \ - ((struct ext2_dir_entry *) ((char *) buffer + \ - le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode + ((struct ext2_dir_entry_2 *) ((char *) buffer + \ + le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode /* * rename uses retrying to avoid race-conditions: at least they should be @@ -850,7 +905,7 @@ { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; - struct ext2_dir_entry * old_de, * new_de; + struct ext2_dir_entry_2 * old_de, * new_de; int retval; old_bh = new_bh = dir_bh = NULL; @@ -942,6 +997,10 @@ * ok, that's it */ new_de->inode = le32_to_cpu(old_inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + new_de->file_type = old_de->file_type; + ext2_delete_entry (old_de, old_bh); old_dir->i_version = ++event; @@ -951,6 +1010,7 @@ mark_inode_dirty(new_inode); } old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; + old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(old_dir); if (dir_bh) { PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); @@ -962,6 +1022,7 @@ 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); } } diff -u --recursive --new-file v2.1.92/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v2.1.92/linux/fs/ext2/super.c Wed Jul 16 10:26:21 1997 +++ linux/fs/ext2/super.c Sat Apr 4 09:45:15 1998 @@ -107,12 +107,10 @@ int db_count; int i; - lock_super (sb); if (!(sb->s_flags & MS_RDONLY)) { sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state); mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); } - sb->s_dev = 0; db_count = sb->u.ext2_sb.s_db_per_group; for (i = 0; i < db_count; i++) if (sb->u.ext2_sb.s_group_desc[i]) @@ -126,7 +124,7 @@ if (sb->u.ext2_sb.s_block_bitmap[i]) brelse (sb->u.ext2_sb.s_block_bitmap[i]); brelse (sb->u.ext2_sb.s_sbh); - unlock_super (sb); + MOD_DEC_USE_COUNT; return; } @@ -516,11 +514,11 @@ 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; diff -u --recursive --new-file v2.1.92/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.1.92/linux/fs/fat/inode.c Fri Jan 23 18:10:32 1998 +++ linux/fs/fat/inode.c Sat Apr 4 09:45:15 1998 @@ -72,7 +72,6 @@ void fat_put_super(struct super_block *sb) { - lock_super(sb); if (MSDOS_SB(sb)->cvf_format) { dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version); MSDOS_SB(sb)->cvf_format->unmount_cvf(sb); @@ -99,8 +98,7 @@ kfree(MSDOS_SB(sb)->options.iocharset); MSDOS_SB(sb)->options.iocharset = NULL; } - sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; return; } diff -u --recursive --new-file v2.1.92/linux/fs/filesystems.c linux/fs/filesystems.c --- v2.1.92/linux/fs/filesystems.c Tue Mar 17 22:18:15 1998 +++ linux/fs/filesystems.c Sat Apr 4 09:45:15 1998 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,10 @@ #ifdef CONFIG_ADFS_FS init_adfs_fs(); +#endif + +#ifdef CONFIG_DEVPTS_FS + init_devpts_fs(); #endif #ifdef CONFIG_NLS diff -u --recursive --new-file v2.1.92/linux/fs/hfs/super.c linux/fs/hfs/super.c --- v2.1.92/linux/fs/hfs/super.c Tue Mar 17 22:18:15 1998 +++ linux/fs/hfs/super.c Sat Apr 4 09:45:15 1998 @@ -122,8 +122,6 @@ { struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb; - lock_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { hfs_mdb_commit(mdb, 0); sb->s_dirt = 0; @@ -135,12 +133,8 @@ /* 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; } diff -u --recursive --new-file v2.1.92/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- v2.1.92/linux/fs/hpfs/hpfs_fs.c Tue Nov 18 10:36:45 1997 +++ linux/fs/hpfs/hpfs_fs.c Sat Apr 4 09:45:16 1998 @@ -731,9 +731,6 @@ static void hpfs_put_super(struct super_block *s) { - lock_super(s); - s->s_dev = 0; - unlock_super(s); MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.1.92/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.1.92/linux/fs/isofs/inode.c Tue Mar 10 10:03:34 1998 +++ linux/fs/isofs/inode.c Sat Apr 4 09:45:16 1998 @@ -49,14 +49,12 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.1.92/linux/fs/minix/inode.c Fri Jan 23 18:10:32 1998 +++ linux/fs/minix/inode.c Sat Apr 4 09:45:16 1998 @@ -59,7 +59,6 @@ { int i; - lock_super(sb); if (!(sb->s_flags & MS_RDONLY)) { sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state; mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); @@ -70,8 +69,7 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.1.92/linux/fs/ncpfs/inode.c Tue Mar 17 22:18:15 1998 +++ linux/fs/ncpfs/inode.c Sat Apr 4 09:45:16 1998 @@ -407,8 +407,6 @@ { struct ncp_server *server = NCP_SBP(sb); - lock_super(sb); - ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); @@ -423,9 +421,6 @@ ncp_kfree_s(server->packet, server->packet_size); ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); - - sb->s_dev = 0; - unlock_super(sb); MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.1.92/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.1.92/linux/fs/nfs/inode.c Tue Mar 17 22:18:15 1998 +++ linux/fs/nfs/inode.c Sat Apr 4 09:45:16 1998 @@ -126,10 +126,6 @@ struct nfs_server *server = &sb->u.nfs_sb.s_server; struct rpc_clnt *rpc; - /* - * Lock the super block while we bring down the daemons. - */ - lock_super(sb); if ((rpc = server->client) != NULL) rpc_shutdown_client(rpc); @@ -142,8 +138,7 @@ nfs_invalidate_dircache_sb(sb); kfree(server->hostname); - sb->s_dev = 0; - unlock_super(sb); + MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.1.92/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c --- v2.1.92/linux/fs/ntfs/fs.c Tue Mar 17 22:18:15 1998 +++ linux/fs/ntfs/fs.c Sat Apr 4 09:45:17 1998 @@ -693,12 +693,9 @@ 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); diff -u --recursive --new-file v2.1.92/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.1.92/linux/fs/proc/inode.c Wed Apr 1 20:11:53 1998 +++ linux/fs/proc/inode.c Sat Apr 4 09:45:17 1998 @@ -80,20 +80,13 @@ } } -static void proc_put_super(struct super_block *sb) -{ - lock_super(sb); - sb->s_dev = 0; - unlock_super(sb); -} - static struct super_operations proc_sops = { proc_read_inode, proc_write_inode, proc_put_inode, proc_delete_inode, /* delete_inode(struct inode *) */ NULL, - proc_put_super, + NULL, NULL, proc_statfs, NULL @@ -198,9 +191,9 @@ 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? */ diff -u --recursive --new-file v2.1.92/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.1.92/linux/fs/proc/link.c Wed Apr 1 20:11:53 1998 +++ linux/fs/proc/link.c Wed Apr 1 20:16:52 1998 @@ -20,12 +20,6 @@ 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 struct file_operations proc_fd_link_operations = { diff -u --recursive --new-file v2.1.92/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.1.92/linux/fs/romfs/inode.c Tue Mar 10 10:03:34 1998 +++ linux/fs/romfs/inode.c Sat Apr 4 09:45:17 1998 @@ -157,9 +157,6 @@ static void romfs_put_super(struct super_block *sb) { - lock_super(sb); - sb->s_dev = 0; - unlock_super(sb); MOD_DEC_USE_COUNT; return; } diff -u --recursive --new-file v2.1.92/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.92/linux/fs/smbfs/inode.c Tue Mar 10 10:03:34 1998 +++ linux/fs/smbfs/inode.c Sat Apr 4 09:45:17 1998 @@ -322,8 +322,6 @@ { struct smb_sb_info *server = &(sb->u.smbfs_sb); - lock_super(sb); - if (server->sock_file) { smb_proc_disconnect(server); smb_dont_catch_keepalive(server); @@ -337,9 +335,6 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/fs/super.c linux/fs/super.c --- v2.1.92/linux/fs/super.c Tue Mar 17 22:18:15 1998 +++ linux/fs/super.c Sat Apr 4 09:45:18 1998 @@ -668,18 +668,26 @@ 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; diff -u --recursive --new-file v2.1.92/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v2.1.92/linux/fs/sysv/inode.c Mon Feb 23 18:12:11 1998 +++ linux/fs/sysv/inode.c Sat Apr 4 09:45:18 1998 @@ -492,12 +492,14 @@ sb->s_op = &sysv_sops; root_inode = iget(sb,SYSV_ROOT_INO); sb->s_root = d_alloc_root(root_inode, NULL); - unlock_super(sb); if (!sb->s_root) { printk("SysV FS: get root inode failed\n"); sysv_put_super(sb); + sb->sb_dev = 0; + unlock_super(sb); return NULL; } + unlock_super(sb); sb->s_dirt = 1; /* brelse(bh); resp. brelse(bh1); brelse(bh2); occurs when the disk is unmounted. */ @@ -530,15 +532,14 @@ void sysv_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; } diff -u --recursive --new-file v2.1.92/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c --- v2.1.92/linux/fs/ufs/ufs_super.c Mon Feb 23 18:12:11 1998 +++ linux/fs/ufs/ufs_super.c Sat Apr 4 09:45:18 1998 @@ -335,15 +335,13 @@ 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; diff -u --recursive --new-file v2.1.92/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h --- v2.1.92/linux/include/asm-i386/smp.h Fri Jan 23 18:10:32 1998 +++ linux/include/asm-i386/smp.h Sun Apr 5 12:08:41 1998 @@ -155,7 +155,6 @@ extern int smp_found_config; extern int smp_scan_config(unsigned long, unsigned long); extern unsigned long smp_alloc_memory(unsigned long mem_base); -extern unsigned char *apic_reg; extern unsigned char boot_cpu_id; extern unsigned long cpu_present_map; extern volatile int cpu_number_map[NR_CPUS]; @@ -192,24 +191,25 @@ * APIC handlers: Note according to the Intel specification update * you should put reads between APIC writes. * Intel Pentium processor specification update [11AP, pg 64] - * "Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle" + * "Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle" */ +#define APIC_BASE ((char *)0xFEE00000) + extern __inline void apic_write(unsigned long reg, unsigned long v) { - *((volatile unsigned long *)(apic_reg+reg))=v; + *((volatile unsigned long *)(APIC_BASE+reg))=v; } extern __inline unsigned long apic_read(unsigned long reg) { - return *((volatile unsigned long *)(apic_reg+reg)); + return *((volatile unsigned long *)(APIC_BASE+reg)); } /* - * This function is needed by all SMP systems. It must _always_ be valid from the initial - * startup. This may require magic on some systems (in the i86 case we dig out the boot - * cpu id from the config and set up a fake apic_reg pointer so that before we activate - * the apic we get the right answer). Hopefully other processors are more sensible 8) + * This function is needed by all SMP systems. It must _always_ be valid + * from the initial startup. We map APIC_BASE very early in page_setup(), + * so this is correct in the x86 case. */ #define smp_processor_id() (current->processor) @@ -217,7 +217,7 @@ extern __inline 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 */ diff -u --recursive --new-file v2.1.92/linux/include/asm-i386/string.h linux/include/asm-i386/string.h --- v2.1.92/linux/include/asm-i386/string.h Thu Mar 26 15:57:05 1998 +++ linux/include/asm-i386/string.h Wed Apr 1 20:46:09 1998 @@ -442,7 +442,7 @@ case 0: COMMON(""); return to; case 1: COMMON("\n\tmovsb"); return to; case 2: COMMON("\n\tmovsw"); return to; - case 3: COMMON("\n\tmovsw\n\tmovsb"); return to; + default: COMMON("\n\tmovsw\n\tmovsb"); return to; } #undef COMMON } @@ -593,7 +593,7 @@ 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 } diff -u --recursive --new-file v2.1.92/linux/include/linux/bios32.h linux/include/linux/bios32.h --- v2.1.92/linux/include/linux/bios32.h Tue Jan 14 16:46:07 1997 +++ linux/include/linux/bios32.h Mon Apr 6 16:30:55 1998 @@ -1,61 +1,34 @@ /* - * BIOS32, PCI BIOS functions and defines - * Copyright 1994, Drew Eckhardt - * - * For more information, please consult - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * P.O. Box 14070 - * Portland, OR 97214 - * U. S. A. - * Phone: 800-433-5177 / +1-503-797-4207 - * Fax: +1-503-234-6762 - * - * Manuals are $25 each or $50 for all three, plus $7 shipping - * within the United States, $35 abroad. + * This is only a stub file to make drivers not yet converted to the new + * PCI probing mechanism work. [mj] */ #ifndef BIOS32_H #define BIOS32_H -/* - * Error values that may be returned by the PCI bios. Use - * pcibios_strerror() to convert to a printable string. - */ -#define PCIBIOS_SUCCESSFUL 0x00 -#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 -#define PCIBIOS_BAD_VENDOR_ID 0x83 -#define PCIBIOS_DEVICE_NOT_FOUND 0x86 -#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 -#define PCIBIOS_SET_FAILED 0x88 -#define PCIBIOS_BUFFER_TOO_SMALL 0x89 - -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); +#include + +#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); +} + +#define pcibios_read_config_byte(b,d,w,p) \ + (((w) == PCI_INTERRUPT_LINE) ? __pcibios_read_irq(b,d,p) : __pcibios_read_config_byte(b,d,w,p)) -#endif /* BIOS32_H */ +#endif diff -u --recursive --new-file v2.1.92/linux/include/linux/devpts_fs.h linux/include/linux/devpts_fs.h --- v2.1.92/linux/include/linux/devpts_fs.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/devpts_fs.h Sat Apr 4 09:45:19 1998 @@ -0,0 +1,69 @@ +/* -*- linux-c -*- --------------------------------------------------------- * + * + * linux/include/linux/devpts_fs.h + * + * Copyright 1998 H. Peter Anvin -- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ------------------------------------------------------------------------- */ + +/* + * Prototypes for the pty driver <-> devpts filesystem interface. Most + * of this is really just a hack so we can exclude it or build it as a + * module, and probably should go away eventually. + */ + +#ifndef _LINUX_DEVPTS_FS_H +#define _LINUX_DEVPTS_FS_H 1 + +#include +#include + +#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 */ diff -u --recursive --new-file v2.1.92/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.1.92/linux/include/linux/ext2_fs.h Fri Feb 6 15:32:54 1998 +++ linux/include/linux/ext2_fs.h Thu Apr 2 13:39:51 1998 @@ -31,6 +31,7 @@ * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files */ #define EXT2_PREALLOCATE +#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 /* * The second extended file system version @@ -190,8 +191,18 @@ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ #define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ +/* Reserved for compression usage... */ +#define EXT2_DIRTY_FL 0x00000100 +#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ +#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */ +#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ +/* End compression flags --- maybe not all used */ +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ - + +#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */ +#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ + /* * ioctl commands */ @@ -255,6 +266,8 @@ } osd2; /* OS dependent 2 */ }; +#define i_size_high i_dir_acl + #if defined(__KERNEL__) || defined(__linux__) #define i_reserved1 osd1.linux1.l_i_reserved1 #define i_frag osd2.linux2.l_i_frag @@ -367,9 +380,26 @@ __u8 s_uuid[16]; /* 128-bit uuid for volume */ char s_volume_name[16]; /* volume name */ char s_last_mounted[64]; /* directory where last mounted */ - __u32 s_reserved[206]; /* Padding to the end of the block */ + __u32 s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_padding1; + __u32 s_reserved[204]; /* Padding to the end of the block */ }; +#ifdef __KERNEL__ +#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) +#else +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) +#endif + /* * Codes for operating systems */ @@ -394,11 +424,27 @@ * 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 @@ -419,6 +465,35 @@ }; /* + * 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 * * NOTE: It must be a multiple of 4 @@ -451,13 +526,16 @@ 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 */ diff -u --recursive --new-file v2.1.92/linux/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h --- v2.1.92/linux/include/linux/ext2_fs_i.h Sat May 4 00:06:18 1996 +++ linux/include/linux/ext2_fs_i.h Thu Apr 2 13:39:51 1998 @@ -35,6 +35,7 @@ __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 */ }; diff -u --recursive --new-file v2.1.92/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.92/linux/include/linux/pci.h Wed Apr 1 20:11:54 1998 +++ linux/include/linux/pci.h Mon Apr 6 14:00:49 1998 @@ -1,5 +1,5 @@ /* - * $Id: pci.h,v 1.51 1997/12/27 13:55:23 mj Exp $ + * $Id: pci.h,v 1.62 1998/03/15 13:50:05 ecd Exp $ * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt @@ -68,6 +68,10 @@ #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 */ @@ -99,8 +103,8 @@ /* 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, @@ -149,6 +153,36 @@ #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 @@ -236,7 +270,8 @@ /* * 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 + * . */ #define PCI_VENDOR_ID_COMPAQ 0x0e11 #define PCI_DEVICE_ID_COMPAQ_1280 0x3033 @@ -518,7 +553,9 @@ #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 @@ -601,6 +638,8 @@ #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 @@ -783,6 +822,9 @@ #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 @@ -933,10 +975,47 @@ #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) -/* create an index into the pci_dev base_address[] array from an offset */ -#define PCI_BASE_INDEX(o) (((o)-PCI_BASE_ADDRESS_0)>>2) - #ifdef __KERNEL__ + +/* + * Error values that may be returned by the PCI bios. Use + * pcibios_strerror() to convert to a printable string. + */ +#define PCIBIOS_SUCCESSFUL 0x00 +#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 +#define PCIBIOS_BAD_VENDOR_ID 0x83 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 +#define PCIBIOS_SET_FAILED 0x88 +#define PCIBIOS_BUFFER_TOO_SMALL 0x89 + +/* Direct configuration space access */ + +int pcibios_present (void); +void pcibios_init(void); +void pcibios_fixup(void); +char *pcibios_setup (char *str); +int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val); +int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val); +int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val); +int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val); +int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val); +int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val); +const char *pcibios_strerror (int error); + +/* Don't use these in new code, use pci_find_... instead */ + +int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn); +int pcibios_find_device (unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus, + unsigned char *dev_fn); + /* * There is one pci_dev structure for each slot-number/function-number * combination: @@ -952,6 +1031,7 @@ unsigned short vendor; unsigned short device; unsigned int class; /* 3 bytes: (base,sub,prog-if) */ + unsigned int hdr_type; /* PCI header type */ unsigned int master : 1; /* set if device is master capable */ /* * In theory, the irq level can be read from configuration @@ -990,15 +1070,25 @@ 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); - -extern unsigned int pci_scan_bus (struct pci_bus *bus, unsigned long *mem_startp); -extern int get_pci_list (char *buf); +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); + +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); + +#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 */ diff -u --recursive --new-file v2.1.92/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.92/linux/include/linux/proc_fs.h Wed Apr 1 20:11:54 1998 +++ linux/include/linux/proc_fs.h Mon Apr 6 11:50:36 1998 @@ -134,6 +134,7 @@ PROC_NET_DN_L1, PROC_NET_DN_L2, PROC_NET_DN_SKT, + PROC_NET_NETSTAT, PROC_NET_LAST }; diff -u --recursive --new-file v2.1.92/linux/include/linux/skbuff.h linux/include/linux/skbuff.h --- v2.1.92/linux/include/linux/skbuff.h Wed Apr 1 20:11:54 1998 +++ linux/include/linux/skbuff.h Mon Apr 6 11:50:36 1998 @@ -75,13 +75,7 @@ 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 */ diff -u --recursive --new-file v2.1.92/linux/include/net/br.h linux/include/net/br.h --- v2.1.92/linux/include/net/br.h Thu Mar 27 14:40:11 1997 +++ linux/include/net/br.h Fri Apr 3 17:48:11 1998 @@ -27,7 +27,7 @@ /* * We time out our entries in the FDB after this many seconds. */ -#define FDB_TIMEOUT 300 +#define FDB_TIMEOUT 20 /* JRP: 20s as NSC bridge code, was 300 for Linux */ /* * the following defines are the initial values used when the @@ -40,6 +40,10 @@ #define BRIDGE_FORWARD_DELAY 15 #define HOLD_TIME 1 +/* broacast/multicast storm limitation. This per source. */ +#define MAX_MCAST_PER_PERIOD 4 +#define MCAST_HOLD_TIME 10 /* in jiffies unit (10ms increment) */ + #define Default_path_cost 10 /* @@ -71,13 +75,25 @@ #define BRIDGE_ID_ULA bi.p_u.ula #define BRIDGE_ID bi.id +/* JRP: on the network the flags field is between "type" and "root_id" + * this is unfortunated! To make the code portable to a RISC machine + * the pdus are now massaged a little bit for processing + */ +#define TOPOLOGY_CHANGE 0x01 +#define TOPOLOGY_CHANGE_ACK 0x80 +#define BRIDGE_BPDU_8021_CONFIG_SIZE 35 /* real size */ +#define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET 4 +#define BRIDGE_BPDU_8021_PROTOCOL_ID 0 +#define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0 +#define BRIDGE_LLC1_HS 3 +#define BRIDGE_LLC1_DSAP 0x42 +#define BRIDGE_LLC1_SSAP 0x42 +#define BRIDGE_LLC1_CTRL 0x03 + typedef struct { unsigned short protocol_id; unsigned char protocol_version_id; unsigned char type; - unsigned char flags; -#define TOPOLOGY_CHANGE 0x01 -#define TOPOLOGY_CHANGE_ACK 0x80 bridge_id_t root_id; /* (4.5.1.1) */ unsigned int root_path_cost; /* (4.5.1.2) */ bridge_id_t bridge_id; /* (4.5.1.3) */ @@ -86,8 +102,23 @@ unsigned short max_age; /* (4.5.1.6) */ unsigned short hello_time; /* (4.5.1.7) */ unsigned short forward_delay; /* (4.5.1.8) */ + unsigned char top_change_ack; + unsigned char top_change; } Config_bpdu; +#ifdef __LITTLE_ENDIAN +#define config_bpdu_hton(config_bpdu) \ + (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \ + (config_bpdu)->port_id = htons((config_bpdu)->port_id); \ + (config_bpdu)->message_age = htons((config_bpdu)->message_age); \ + (config_bpdu)->max_age = htons((config_bpdu)->max_age); \ + (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \ + (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay); +#else +#define config_bpdu_hton(config_bpdu) +#endif +#define config_bpdu_ntoh config_bpdu_hton + /** Topology Change Notification BPDU Parameters (4.5.2) **/ @@ -112,12 +143,10 @@ unsigned short bridge_max_age; /* (4.5.3.8) */ unsigned short bridge_hello_time; /* (4.5.3.9) */ unsigned short bridge_forward_delay; /* (4.5.3.10) */ - unsigned int topology_change_detected; /* (4.5.3.11) */ - unsigned int topology_change; /* (4.5.3.12) */ + unsigned int top_change_detected; /* (4.5.3.11) */ + unsigned int top_change; /* (4.5.3.12) */ unsigned short topology_change_time; /* (4.5.3.13) */ unsigned short hold_time; /* (4.5.3.14) */ - unsigned int top_change; - unsigned int top_change_detected; } Bridge_data; /** Port Parameters (4.5.5) **/ @@ -149,8 +178,11 @@ unsigned char pad[2]; unsigned short port; unsigned int timer; - unsigned int flags; + unsigned short flags; #define FDB_ENT_VALID 0x01 + unsigned short mcast_count; + unsigned int mcast_timer; /* oldest xxxxxcast */ + /* AVL tree of all addresses, sorted by address */ short fdb_avl_height; struct fdb *fdb_avl_left; @@ -159,6 +191,19 @@ struct fdb *fdb_next; }; +/* data returned on BRCMD_DISPLAY_FDB */ +struct fdb_info { + unsigned char ula[6]; + unsigned char port; + unsigned char flags; + unsigned int timer; +}; +struct fdb_info_hdr { + int copied; /* nb of entries copied to user */ + int not_copied; /* when user buffer is too small */ + int cmd_time; +}; + #define IS_BRIDGED 0x2e @@ -169,6 +214,34 @@ #define BR_ACCEPT 1 #define BR_REJECT 0 +/* JRP: extra statistics for debug */ +typedef struct { + /* br_receive_frame counters */ + int port_disable_up_stack; + int rcv_bpdu; + int notForwarding; + int forwarding_up_stack; + int unknown_state; + + /* br_tx_frame counters */ + int port_disable; + int port_not_disable; + + /* br_forward counters */ + int local_multicast; + int forwarded_multicast; /* up stack as well */ + int flood_unicast; + int aged_flood_unicast; + int forwarded_unicast; + int forwarded_unicast_up_stack; + int forwarded_ip_up_stack; + int forwarded_ip_up_stack_lie; /* received on alternate device */ + int arp_for_local_mac; + int drop_same_port; + int drop_same_port_aged; + int drop_multicast; +} br_stats_counter; + struct br_stat { unsigned int flags; Bridge_data bridge_data; @@ -178,6 +251,7 @@ unsigned short protocols[BR_MAX_PROTOCOLS]; unsigned short prot_id[BR_MAX_PROT_STATS]; /* Protocol encountered */ unsigned int prot_counter[BR_MAX_PROT_STATS]; /* How many packets ? */ + br_stats_counter packet_cnts; }; /* defined flags for br_stat.flags */ @@ -215,9 +289,10 @@ int br_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 */ diff -u --recursive --new-file v2.1.92/linux/include/net/ip.h linux/include/net/ip.h --- v2.1.92/linux/include/net/ip.h Thu Mar 26 15:57:06 1998 +++ linux/include/net/ip.h Mon Apr 6 11:52:59 1998 @@ -128,6 +128,7 @@ 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]; diff -u --recursive --new-file v2.1.92/linux/include/net/snmp.h linux/include/net/snmp.h --- v2.1.92/linux/include/net/snmp.h Sat Nov 29 10:33:21 1997 +++ linux/include/net/snmp.h Fri Apr 3 17:48:11 1998 @@ -124,5 +124,12 @@ unsigned long UdpInErrors; unsigned long UdpOutDatagrams; }; + +struct linux_mib +{ + unsigned long SyncookiesSent; + unsigned long SyncookiesRecv; + unsigned long SyncookiesFailed; +}; #endif diff -u --recursive --new-file v2.1.92/linux/include/net/sock.h linux/include/net/sock.h --- v2.1.92/linux/include/net/sock.h Wed Apr 1 20:11:54 1998 +++ linux/include/net/sock.h Mon Apr 6 11:51:18 1998 @@ -274,7 +274,8 @@ struct open_request *syn_wait_queue; struct open_request **syn_wait_last; - int syn_backlog; + + int syn_backlog; /* Backlog of received SYNs */ }; diff -u --recursive --new-file v2.1.92/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.92/linux/include/net/tcp.h Wed Apr 1 20:11:54 1998 +++ linux/include/net/tcp.h Mon Apr 6 11:53:01 1998 @@ -941,6 +941,9 @@ (*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) @@ -959,20 +962,6 @@ { tp->syn_wait_queue = NULL; 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); diff -u --recursive --new-file v2.1.92/linux/init/main.c linux/init/main.c --- v2.1.92/linux/init/main.c Wed Apr 1 20:11:54 1998 +++ linux/init/main.c Mon Apr 6 13:47:08 1998 @@ -40,6 +40,9 @@ #include +#ifdef CONFIG_PCI +#include +#endif /* * Versions of gcc older than that listed below may actually compile @@ -61,23 +64,25 @@ extern int kswapd(void *); extern void kswapd_setup(void); +extern void dquot_init(void); extern void init_IRQ(void); extern void init_modules(void); extern long console_init(long, long); extern void sock_init(void); extern void uidcache_init(void); -extern unsigned long pci_init(unsigned long, unsigned long); extern long mca_init(long, long); extern long sbus_init(long, long); extern long powermac_init(unsigned long, unsigned long); extern void sysctl_init(void); extern void filescache_init(void); extern void signals_init(void); -extern void dquot_init(void); extern void smp_setup(char *str, int *ints); +#ifdef __i386__ extern void ioapic_pirq_setup(char *str, int *ints); +#endif extern void no_scroll(char *str, int *ints); +extern void kbd_reset_setup(char *str, int *ints); extern void panic_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints); extern void msmouse_setup(char *str, int *ints); @@ -473,8 +478,10 @@ #ifdef __SMP__ { "nosmp", smp_setup }, { "maxcpus=", smp_setup }, +#ifdef __i386__ { "pirq=", ioapic_pirq_setup }, #endif +#endif #ifdef CONFIG_BLK_DEV_RAM { "ramdisk_start=", ramdisk_start_setup }, { "load_ramdisk=", load_ramdisk }, @@ -492,6 +499,7 @@ { "console=", console_setup }, #ifdef CONFIG_VT { "no-scroll", no_scroll }, + { "kbd-reset", kbd_reset_setup }, #endif #ifdef CONFIG_BUGi386 { "no-hlt", no_halt }, @@ -737,6 +745,9 @@ #ifdef CONFIG_IP_PNP { "ip=", ip_auto_config_setup }, #endif +#ifdef CONFIG_PCI + { "pci=", pci_setup }, +#endif #ifdef CONFIG_PARIDE_PD { "pd.", pd_setup }, #endif @@ -1015,24 +1026,15 @@ 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(); calibrate_delay(); @@ -1070,6 +1072,24 @@ #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 diff -u --recursive --new-file v2.1.92/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.92/linux/kernel/ksyms.c Wed Apr 1 20:11:54 1998 +++ linux/kernel/ksyms.c Thu Apr 2 09:12:26 1998 @@ -54,10 +54,6 @@ extern unsigned char aux_device_present, kbd_read_mask; -#ifdef CONFIG_PCI -#include -#include -#endif #if defined(CONFIG_PROC_FS) #include #endif @@ -100,19 +96,6 @@ #endif EXPORT_SYMBOL(get_options); -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pcibios_present); -EXPORT_SYMBOL(pcibios_find_class); -EXPORT_SYMBOL(pcibios_find_device); -EXPORT_SYMBOL(pcibios_read_config_byte); -EXPORT_SYMBOL(pcibios_read_config_word); -EXPORT_SYMBOL(pcibios_read_config_dword); -EXPORT_SYMBOL(pcibios_write_config_byte); -EXPORT_SYMBOL(pcibios_write_config_word); -EXPORT_SYMBOL(pcibios_write_config_dword); -EXPORT_SYMBOL(pcibios_strerror); -#endif - /* process memory management */ EXPORT_SYMBOL(do_mmap); EXPORT_SYMBOL(do_munmap); @@ -265,6 +248,7 @@ EXPORT_SYMBOL(unregister_binfmt); EXPORT_SYMBOL(search_binary_handler); EXPORT_SYMBOL(prepare_binprm); +EXPORT_SYMBOL(compute_creds); EXPORT_SYMBOL(remove_arg_zero); /* execution environment registration */ @@ -354,6 +338,7 @@ EXPORT_SYMBOL(_ctype); EXPORT_SYMBOL(secure_tcp_sequence_number); EXPORT_SYMBOL(get_random_bytes); +EXPORT_SYMBOL(securebits); /* Program loader interfaces */ EXPORT_SYMBOL(setup_arg_pages); diff -u --recursive --new-file v2.1.92/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.92/linux/mm/page_alloc.c Wed Apr 1 20:11:55 1998 +++ linux/mm/page_alloc.c Sat Apr 4 09:26:23 1998 @@ -292,8 +292,12 @@ 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; } diff -u --recursive --new-file v2.1.92/linux/net/core/dev.c linux/net/core/dev.c --- v2.1.92/linux/net/core/dev.c Tue Mar 17 22:18:16 1998 +++ linux/net/core/dev.c Fri Apr 3 17:48:11 1998 @@ -1342,10 +1342,7 @@ 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); diff -u --recursive --new-file v2.1.92/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.1.92/linux/net/ipv4/af_inet.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/af_inet.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * AF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.68 1998/03/27 07:02:42 davem Exp $ + * Version: $Id: af_inet.c,v 1.69 1998/04/03 09:49:42 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -117,10 +117,13 @@ #define min(a,b) ((a)<(b)?(a):(b)) +struct linux_mib net_statistics; + extern int sysctl_core_destroy_delay; extern int raw_get_info(char *, char **, off_t, int, int); extern int snmp_get_info(char *, char **, off_t, int, int); +extern int netstat_get_info(char *, char **, off_t, int, int); extern int afinet_get_info(char *, char **, off_t, int, int); extern int tcp_get_info(char *, char **, off_t, int, int); extern int udp_get_info(char *, char **, off_t, int, int); @@ -1016,6 +1019,12 @@ 0, &proc_net_inode_operations, raw_get_info }; +static struct proc_dir_entry proc_net_netstat = { + PROC_NET_NETSTAT, 7, "netstat", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + netstat_get_info +}; static struct proc_dir_entry proc_net_snmp = { PROC_NET_SNMP, 4, "snmp", S_IFREG | S_IRUGO, 1, 0, 0, @@ -1141,6 +1150,7 @@ #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); diff -u --recursive --new-file v2.1.92/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c --- v2.1.92/linux/net/ipv4/ip_input.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv4/ip_input.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.27 1998/03/08 05:56:24 davem Exp $ + * Version: $Id: ip_input.c,v 1.29 1998/04/03 10:52:06 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, diff -u --recursive --new-file v2.1.92/linux/net/ipv4/proc.c linux/net/ipv4/proc.c --- v2.1.92/linux/net/ipv4/proc.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv4/proc.c Fri Apr 3 17:48:11 1998 @@ -7,7 +7,7 @@ * PROC file system. It is mainly used for debugging and * statistics. * - * Version: $Id: proc.c,v 1.27 1998/03/18 07:51:59 davem Exp $ + * Version: $Id: proc.c,v 1.28 1998/04/03 09:49:45 freitag Exp $ * * Authors: Fred N. van Kempen, * Gerald J. Heim, @@ -25,6 +25,7 @@ * Alan Cox : Allow inode to be NULL (kernel socket) * Andi Kleen : Add support for open_requests and * split functions for more readibility. + * Andi Kleen : Add support for /proc/net/netstat * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -326,6 +327,34 @@ tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss); */ + if (offset >= len) + { + *start = buffer; + return 0; + } + *start = buffer + offset; + len -= offset; + if (len > length) + 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; diff -u --recursive --new-file v2.1.92/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c --- v2.1.92/linux/net/ipv4/syncookies.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv4/syncookies.c Fri Apr 3 17:48:11 1998 @@ -9,11 +9,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: syncookies.c,v 1.4 1998/03/08 05:56:34 davem Exp $ + * $Id: syncookies.c,v 1.5 1998/04/03 09:49:46 freitag Exp $ * * Missing: IPv6 support. - * Some counter so that the Administrator can see when the machine - * is under a syn flood attack. */ #include @@ -88,6 +86,8 @@ found: *mssp = w[-1]; + net_statistics.SyncookiesSent++; + isn |= i; return isn; } @@ -110,8 +110,9 @@ __u32 seq; if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT - && tcp_lastsynq_overflow) + && tcp_lastsynq_overflow) { return 0; + } mssind = cookie & 7; cookie &= ~7; @@ -157,8 +158,12 @@ 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) diff -u --recursive --new-file v2.1.92/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.1.92/linux/net/ipv4/sysctl_net_ipv4.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/sysctl_net_ipv4.c Fri Apr 3 17:48:11 1998 @@ -1,7 +1,7 @@ /* * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. * - * $Id: sysctl_net_ipv4.c,v 1.31 1998/03/30 08:41:41 davem Exp $ + * $Id: sysctl_net_ipv4.c,v 1.32 1998/04/03 09:49:47 freitag Exp $ * * Begun April 1, 1996, Mike Shaver. * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] @@ -154,8 +154,6 @@ {NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg, 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}, diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.92/linux/net/ipv4/tcp.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/tcp.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.108 1998/03/29 08:43:51 davem Exp $ + * Version: $Id: tcp.c,v 1.110 1998/04/03 09:49:51 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1160,6 +1160,11 @@ break; } + if (sk->shutdown & RCV_SHUTDOWN) { + sk->done = 1; + break; + } + if (sk->state == TCP_CLOSE) { if (!sk->done) { sk->done = 1; @@ -1169,11 +1174,6 @@ break; } - if (sk->shutdown & RCV_SHUTDOWN) { - sk->done = 1; - break; - } - if (nonblock) { copied = -EAGAIN; break; @@ -1529,7 +1529,7 @@ 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. diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.92/linux/net/ipv4/tcp_input.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/tcp_input.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.103 1998/03/30 08:41:12 davem Exp $ + * Version: $Id: tcp_input.c,v 1.104 1998/04/01 07:41:24 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1906,7 +1906,10 @@ tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1; tp->rcv_wup = TCP_SKB_CB(skb)->seq+1; - tp->snd_wnd = htons(th->window) << tp->snd_wscale; + /* RFC1323: The window in SYN & SYN/ACK segments is + * never scaled. + */ + tp->snd_wnd = htons(th->window); tp->snd_wl1 = TCP_SKB_CB(skb)->seq; tp->snd_wl2 = TCP_SKB_CB(skb)->ack_seq; tp->fin_seq = TCP_SKB_CB(skb)->seq; @@ -1918,6 +1921,7 @@ tp->snd_wscale = tp->rcv_wscale = 0; tp->window_clamp = min(tp->window_clamp,65535); } + if (tp->tstamp_ok) { tp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED; @@ -1980,6 +1984,9 @@ 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; diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.92/linux/net/ipv4/tcp_ipv4.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/tcp_ipv4.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.127 1998/03/30 08:41:25 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.131 1998/04/03 10:52:04 davem Exp $ * * IPv4 specific functions * @@ -39,11 +39,12 @@ * 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 @@ -812,6 +813,11 @@ if (req->sk) { /* not yet accept()ed */ sk = req->sk; /* report error in accept */ } else { +#ifdef TCP_NEW_LISTEN + tp->syn_backlog--; +#else + sk->ack_backlog--; +#endif tcp_synq_unlink(tp, req, prev); req->class->destructor(req); tcp_openreq_free(req); @@ -1017,7 +1023,6 @@ } int sysctl_max_syn_backlog = 1024; -int sysctl_tcp_syn_taildrop = 1; struct or_calltable or_ipv4 = { tcp_v4_send_synack, @@ -1025,7 +1030,7 @@ tcp_v4_send_reset }; -#ifdef NEW_LISTEN +#ifdef TCP_NEW_LISTEN #define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */ #define BACKLOGMAX(sk) sysctl_max_syn_backlog #else @@ -1057,27 +1062,19 @@ if (sysctl_tcp_syncookies) { syn_flood_warning(skb); want_cookie = 1; - } else + } else #endif - if (sysctl_tcp_syn_taildrop) { - struct open_request *req; - - req = tcp_synq_unlink_tail(&sk->tp_pinfo.af_tcp); - tcp_openreq_free(req); - tcp_statistics.TcpAttemptFails++; - } else { - goto error; - } + goto drop; } else { if (isn == 0) isn = tcp_v4_init_sequence(sk, skb); - BACKLOG(sk)++; } + BACKLOG(sk)++; + req = tcp_openreq_alloc(); if (req == NULL) { - if (!want_cookie) BACKLOG(sk)--; - goto error; + goto dropbacklog; } req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ @@ -1137,7 +1134,10 @@ tcp_statistics.TcpAttemptFails++; return -ENOTCONN; /* send reset */ -error: +dropbacklog: + if (!want_cookie) + BACKLOG(sk)--; +drop: tcp_statistics.TcpAttemptFails++; return 0; } @@ -1184,7 +1184,12 @@ newtp->ato = 0; newtp->snd_wl1 = req->rcv_isn; newtp->snd_wl2 = req->snt_isn; + + /* RFC1323: The window in SYN & SYN/ACK segments + * is never scaled. + */ newtp->snd_wnd = ntohs(skb->h.th->window); + newtp->max_window = newtp->snd_wnd; newtp->pending = 0; newtp->retransmits = 0; @@ -1270,6 +1275,10 @@ return newsk; } +/* + * The three way handshake has completed - we got a valid synack - + * now create the new socket. + */ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req, struct dst_entry *dst) @@ -1280,7 +1289,7 @@ int snd_mss; int mtu; -#ifdef NEW_LISTEN +#ifdef TCP_NEW_LISTEN if (sk->ack_backlog > sk->max_ack_backlog) goto exit; /* head drop */ #endif @@ -1288,13 +1297,14 @@ struct rtable *rt; if (ip_route_output(&rt, - opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr, - req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0)) + opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr, + req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0)) return NULL; dst = &rt->u.dst; } -#ifdef NEW_LISTEN +#ifdef TCP_NEW_LISTEN + sk->tp_pinfo.af_tcp.syn_backlog--; sk->ack_backlog++; #endif @@ -1343,6 +1353,11 @@ after(TCP_SKB_CB(skb)->seq, req->snt_isn+1)) return; tcp_synq_unlink(tp, req, prev); +#ifdef TCP_NEW_LISTEN + (req->sk ? sk->ack_backlog : tp->syn_backlog)--; +#else + sk->ack_backlog--; +#endif req->class->destructor(req); tcp_openreq_free(req); } @@ -1468,9 +1483,14 @@ skb->csum = csum_partial((char *)th, len, 0); case CHECKSUM_HW: if (tcp_v4_check(th,len,skb->nh.iph->saddr,skb->nh.iph->daddr,skb->csum)) { - printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n", - NIPQUAD(skb->nh.iph->saddr), ntohs(th->source), NIPQUAD(skb->nh.iph->daddr), - ntohs(th->dest), len, skb->len, ntohs(skb->nh.iph->tot_len)); + printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, " + "len=%d/%d/%d\n", + NIPQUAD(ntohl(skb->nh.iph->saddr)), + ntohs(th->source), + NIPQUAD(ntohl(skb->nh.iph->daddr)), + ntohs(th->dest), + len, skb->len, + ntohs(skb->nh.iph->tot_len)); tcp_statistics.TcpInErrs++; goto discard_it; } @@ -1642,7 +1662,7 @@ 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. */ diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.1.92/linux/net/ipv4/tcp_output.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/tcp_output.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.81 1998/03/30 08:41:36 davem Exp $ + * Version: $Id: tcp_output.c,v 1.83 1998/04/03 08:10:45 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -109,6 +109,9 @@ th->check = 0; th->urg_ptr = ntohs(tcb->urg_ptr); if(tcb->flags & TCPCB_FLAG_SYN) { + /* RFC1323: The window in SYN & SYN/ACK segments + * is never scaled. + */ th->window = htons(tp->rcv_wnd); tcp_syn_build_options((__u32 *)(th + 1), sk->mss, sysctl_tcp_timestamps, @@ -610,6 +613,24 @@ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN; TCP_SKB_CB(skb)->end_seq++; tp->write_seq++; + + /* Special case to avoid Nagle bogosity. If this + * segment is the last segment, and it was queued + * due to Nagle/SWS-avoidance, send it out now. + */ + if(tp->send_head == skb && + !sk->nonagle && + skb->len < (sk->mss >> 1) && + tp->packets_out && + !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) { + update_send_head(sk); + TCP_SKB_CB(skb)->when = jiffies; + tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; + tp->packets_out++; + tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); + if(!tcp_timer_is_set(sk, TIME_RETRANS)) + tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto); + } } else { /* Socket is locked, keep trying until memory is available. */ do { @@ -755,6 +776,8 @@ &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; diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c --- v2.1.92/linux/net/ipv4/tcp_timer.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv4/tcp_timer.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.45 1998/03/30 08:41:31 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.47 1998/04/03 10:52:05 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -451,6 +451,7 @@ if ((long)(now - conn->expires) <= 0) break; + tcp_synq_unlink(tp, conn, prev); if (conn->retrans >= sysctl_tcp_retries1) { #ifdef TCP_DEBUG @@ -459,7 +460,11 @@ #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) diff -u --recursive --new-file v2.1.92/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.92/linux/net/ipv6/tcp_ipv6.c Wed Apr 1 20:11:55 1998 +++ linux/net/ipv6/tcp_ipv6.c Fri Apr 3 17:48:11 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.72 1998/03/30 08:41:52 davem Exp $ + * $Id: tcp_ipv6.c,v 1.74 1998/04/03 09:50:01 freitag Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -42,9 +42,6 @@ #include -extern int sysctl_tcp_timestamps; -extern int sysctl_tcp_window_scaling; - static void tcp_v6_send_reset(struct sk_buff *skb); static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, struct sk_buff *skb); @@ -748,12 +745,12 @@ if (sk->ack_backlog >= sk->max_ack_backlog) { printk(KERN_DEBUG "droping syn ack:%d max:%d\n", sk->ack_backlog, sk->max_ack_backlog); - tcp_statistics.TcpAttemptFails++; - goto exit; + goto drop; } req = tcp_openreq_alloc(); if (req == NULL) { + goto drop; } sk->ack_backlog++; @@ -796,8 +793,11 @@ 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,