diff -u --recursive --new-file v2.2.0-pre6/linux/CREDITS linux/CREDITS --- v2.2.0-pre6/linux/CREDITS Fri Jan 8 22:35:58 1999 +++ linux/CREDITS Sun Jan 10 10:26:51 1999 @@ -765,9 +765,9 @@ S: Germany N: Richard Henderson +E: rth@twiddle.net E: rth@cygnus.com -E: richard@gnu.org -D: Alpha/ELF, gcc, binutils, and glibc +D: Alpha hacker, kernel and userland S: 50 E. Middlefield #10 S: Mountain View, California 94043 S: USA @@ -910,7 +910,9 @@ N: Niels Kristian Bech Jensen E: nkbj@image.dk W: http://www.image.dk/~nkbj -D: 4.4BSD and NeXTstep support in read-only ufs +D: 4.4BSD and NeXTstep filesystem support in the old ufs. +D: Openstep filesystem support in the new ufs. +D: Danish HOWTO, Linux+FreeBSD mini-HOWTO. S: Dr. Holsts Vej 34, lejl. 164 S: DK-8230 Åbyhøj S: Denmark @@ -1507,7 +1509,12 @@ N: Reed H. Petty E: rhp@draper.net +W: http://www.draper.net D: Loop device driver extensions +D: Encryption transfer modules (no export) +S: Post Office Box 1815 +S: Harrison, Arkansas 72602-1815 +S: USA N: Kai Petzke E: wpp@marie.physik.tu-berlin.de diff -u --recursive --new-file v2.2.0-pre6/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.2.0-pre6/linux/Documentation/Configure.help Thu Jan 7 15:11:35 1999 +++ linux/Documentation/Configure.help Sun Jan 10 22:27:27 1999 @@ -131,6 +131,13 @@ If you are not sure, say Y; apart from resulting in a 45 KB bigger kernel, it won't hurt. +Kernel FP software completion +CONFIG_MATHEMU + This option is required for IEEE compliant floating point arithmetic + on the Alpha. The only time you would ever not say Y is to say M + in order to debug the code. Do not say anything but Y unless you + know what you are doing. + Normal PC floppy disk support CONFIG_BLK_DEV_FD If you want to use the floppy disk drive(s) of your PC under Linux, @@ -1169,38 +1176,50 @@ if you have a floppy drive, otherwise N. Easy. Alpha system type -CONFIG_ALPHA_AVANTI - Find out what type of Alpha motherboard you have. You will probably - want to read the Linux/Alpha home page on the WWW at - http://www.azstarnet.com/~axplinux/ (to browse the WWW, you need to +CONFIG_ALPHA_GENERIC + This is the system type of your hardware. A "generic" kernel will + run on any supported Alpha system. Configuring a kernel for one + specific system can save about 200K and operate more efficiently. + + To find out what type of Alpha system you have, you may want to + check out the Linux/Alpha FAQ, accessible on the WWW from + http://www.azstarnet.com/~axplinux/ (To browse the WWW, you need to have access to a machine on the Internet that has a program like - lynx or netscape) and also the Alpha-HOWTO, available via FTP (user: - anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. For this - question, it suffices to give a unique prefix of the option you want - to choose. The choices: - ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400) - AlphaStations. These usually come with a TGA graphics adapter, - so you'll want to say Y to "TGA Console support", below, if you - have one of these. - ** Alpha-XL: A.k.a. "Windows NT Dream Machine" :-) These usually - come with a TGA graphics adapter, so you'll want to say Y to "TGA - Console support", below, if you have one of these. - ** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha - PC; it sports an EISA bus. The boot process on Jensen machines is - difficult (no booting from floppies, MILO doesn't work). You need - to have access to a second Linux workstation. The Linux/Alpha - FAQ, accessible from the above mentioned WWW page, has details. - ** Noname: a.k.a. AXPpci33, a PCI-bus based board using the 21066 - Alpha CPU, running at either 166 or 233 MHz. You also want to - choose this option if you have a UDB (Universal Desktop Box - a.k.a. Multia) machine. - ** Cabriolet: also called AlphaPC64, a PCI-bus based board using the - 21064 Alpha CPU typically running at 275 or 300 MHz. - ** EB66: "Evaluation Board" - ** EB66+: "Evaluation Board" -### -### Add info about Platform2000, EB164, etc. -### + lynx or netscape). In summary: + + Alcor/Alpha-XLT AS 600 + Alpha-XL XL-233, XL-266 + AlphaBook1 Alpha laptop + Avanti AS 200, AS 205, AS 250, AS 255, AS 300, AS 400 + Cabriolet AlphaPC64, AlphaPCI64 + DP264 DP264 + EB164 EB164 21164 evaluation board + EB64+ EB64+ 21064 evaluation board + EB66 EB66 21066 evaluation board + EB66+ EB66+ 21066 evaluation board + Jensen DECpc 150, DEC 2000 model 300, DEC 2000 model 500 + LX164 AlphaPC164-LX + Miata Personal Workstation 433a, 433au, 500a, + 500au, 600a, or 600au + Mikasa AS 1000 + Noname AXPpci33, UDB (Multia) + Noritake AS 1000A, AS 600A, AS 800 + PC164 AlphaPC164 + Rawhide AS 1200, AS 4000, AS 4100 + Ruffian RPX164-2, AlphaPC164-UX, AlphaPC164-BX + SX164 AlphaPC164-SX + Sable AS 2000, AS 2100 + Takara Takara + + If you don't know what to do, choose "generic". + +EV5 CPU daughtercard +CONFIG_ALPHA_PRIMO + Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx. + +EV5 CPU(s) +CONFIG_ALPHA_GAMMA + Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx. Using SRM as bootloader CONFIG_ALPHA_SRM @@ -1225,6 +1244,12 @@ If unsure, say N. +Use SRM PCI setup +CONFIG_ALPHA_SRM_SETUP + This option controls whether or not the PCI configuration set up by + SRM is modified. If you say Y, the existing PCI configuration will + be left intact. + Non-standard serial port support CONFIG_SERIAL_NONSTANDARD Say Y here if you have any non-standard serial boards -- boards @@ -4108,6 +4133,17 @@ say M here and read Documentation/modules.txt. The module will be called in2000.o. +Initio 91XXU(W) SCSI support +CONFIG_SCSI_INITIO + This is support for the Initio 91XXU(W) SCSI host adapter. + Please read the SCSI-HOWTO, available via FTP (user: anonymous) at + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called initio.o + PAS16 SCSI support CONFIG_SCSI_PAS16 This is support for a SCSI host adapter. It is explained in section @@ -8461,13 +8497,40 @@ Ignore multiple suspend/resume cycles CONFIG_APM_IGNORE_SUSPEND_BOUNCE - This option is necessary on the Dell Inspiron 3200, but should be - safe for all other laptops. When enabled, a system suspend event - that occurs within one second of a resume is ignored. Without this - the Inspiron will shut itself off a few seconds after you open the - lid, requiring you to press the power button to resume it a second - time. + This option is necessary on the Dell Inspiron 3200 and others, but + should be safe for all other laptops. When enabled, a system suspend + event that occurs within one second of a resume is ignored. Without + this the Inspiron will shut itself off a few seconds after you open + the lid, requiring you to press the power button to resume it a + second time. Say Y. + +RTC stores time in GMT +CONFIG_APM_RTC_IS_GMT + This option can be used when your RTC (Real Time Clock aka. Hardware + Clock) stores the time in GMT (Greenwich Mean Time) rather than + localtime. When suspending/resuming, the kernel needs to know what + is stored in the RTC so it can update the system clock (which is + always GMT). Without this option the kernel attempts to measure + the offset between the RTC and the system clock. This means you + can loose one second on each suspend/resume cycle. + Also, on the Dell Inspiron 3200, the hardware slows down the system + even before the kernel can measure the RTC/system clock offset. It + can then take 15 seconds to do this measurement and it can be + incorrect by several seconds. + Say Y if GMT is stored in your RTC. + GMT is usually the best anyway, because you don't have to worry about + daylight savings time changes. The only reason to not use GMT in + your RTC is if you also run a broken OS that doesn't understand GMT. + +Allow interrupts during APM BIOS calls +CONFIG_APM_ALLOW_INTS + Normally we disable external interrupts while we are making calls to + the APM BIOS as a measure to lessen the effects of a badly behaving + BIOS implementation. The BIOS should reeanble interrupts if it + needs to. Unfortunately, some BIOS's do not - especially those in + many of the newer IBM Thinkpads. If you experience hangs when you + suspend, try setting this to Y. Otherwise, say N. Watchdog Timer Support CONFIG_WATCHDOG diff -u --recursive --new-file v2.2.0-pre6/linux/Documentation/sound/VIA-chipset linux/Documentation/sound/VIA-chipset --- v2.2.0-pre6/linux/Documentation/sound/VIA-chipset Fri Jan 8 22:35:59 1999 +++ linux/Documentation/sound/VIA-chipset Sat Jan 9 19:16:43 1999 @@ -39,5 +39,5 @@ and rebuild a kernel without PCI quirk support. -Other than this paticular glitch the VIA [M]VP* chipsets appear to work +Other than this particular glitch the VIA [M]VP* chipsets appear to work perfectly with Linux. diff -u --recursive --new-file v2.2.0-pre6/linux/Makefile linux/Makefile --- v2.2.0-pre6/linux/Makefile Fri Jan 8 22:36:00 1999 +++ linux/Makefile Sun Jan 10 22:56:43 1999 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION =-pre6 +EXTRAVERSION =-pre7 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -412,8 +412,9 @@ depend dep: dep-files $(MODVERFILE) +# make checkconfig: Prune 'scripts' directory to avoid "false positives". checkconfig: - perl -w scripts/checkconfig.pl `find * -name '*.[hcS]' -print | sort` + perl -w scripts/checkconfig.pl `find * -path 'scripts' -prune -o -name '*.[hcS]' -print | sort` checkhelp: perl -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print` diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.2.0-pre6/linux/arch/alpha/Makefile Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/Makefile Sun Jan 10 09:59:54 1999 @@ -31,17 +31,19 @@ ifeq ($(CONFIG_ALPHA_EV4),y) CFLAGS := $(CFLAGS) -mcpu=ev4 endif - # Leave out EV5, since it is too hard to figure out whether we - # should use EV56 insns or not. + ifeq ($(CONFIG_ALPHA_PYXIS),y) + CFLAGS := $(CFLAGS) -mcpu=ev56 + endif ifeq ($(CONFIG_ALPHA_EV6),y) CFLAGS := $(CFLAGS) -mcpu=ev6 endif endif # For TSUNAMI, we must have the assembler not emulate our instructions. +# The same is true for POLARIS. # BWX is most important, but we don't really want any emulation ever. ifeq ($(old_gas),y) - ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI),) + ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS),) # How do we do #error in make? CFLAGS := --error-please-upgrade-your-assembler endif @@ -51,6 +53,9 @@ endif ifeq ($(CONFIG_ALPHA_PYXIS),y) CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED + endif + ifeq ($(CONFIG_ALPHA_POLARIS),y) + CFLAGS := $(CFLAGS) -Wa,-m21164a endif endif diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.2.0-pre6/linux/arch/alpha/config.in Thu Dec 31 10:28:58 1998 +++ linux/arch/alpha/config.in Sun Jan 10 09:59:54 1999 @@ -43,6 +43,7 @@ Platform2000 CONFIG_ALPHA_P2K \ Rawhide CONFIG_ALPHA_RAWHIDE \ Ruffian CONFIG_ALPHA_RUFFIAN \ + RX164 CONFIG_ALPHA_RX164 \ SX164 CONFIG_ALPHA_SX164 \ Sable CONFIG_ALPHA_SABLE \ Takara CONFIG_ALPHA_TAKARA" Generic @@ -51,7 +52,7 @@ unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 unset CONFIG_PCI CONFIG_ALPHA_EISA unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA -unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS +unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION @@ -129,6 +130,12 @@ define_bool CONFIG_PCI y define_bool CONFIG_ALPHA_EV5 y define_bool CONFIG_ALPHA_MCPCIA y +fi +if [ "$CONFIG_ALPHA_RX164" = "y" ] +then + define_bool CONFIG_PCI y + define_bool CONFIG_ALPHA_EV5 y + define_bool CONFIG_ALPHA_POLARIS y fi if [ "$CONFIG_ALPHA_JENSEN" = "y" ] then diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v2.2.0-pre6/linux/arch/alpha/kernel/Makefile Tue Dec 22 14:16:53 1998 +++ linux/arch/alpha/kernel/Makefile Sun Jan 10 09:59:54 1999 @@ -23,11 +23,11 @@ ifdef CONFIG_ALPHA_GENERIC O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \ - core_t2.o core_tsunami.o \ + core_t2.o core_tsunami.o core_polaris.o \ sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \ sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \ sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \ - sys_sx164.o sys_takara.o \ + sys_sx164.o sys_takara.o sys_rx164.o \ es1888.o smc37c669.o smc37c93x.o else @@ -53,6 +53,9 @@ ifdef CONFIG_ALPHA_TSUNAMI O_OBJS += core_tsunami.o endif +ifdef CONFIG_ALPHA_POLARIS +O_OBJS += core_polaris.o +endif # Board support ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),) @@ -84,6 +87,9 @@ endif ifdef CONFIG_ALPHA_RUFFIAN O_OBJS += sys_ruffian.o +endif +ifdef CONFIG_ALPHA_RX164 +O_OBJS += sys_rx164.o endif ifdef CONFIG_ALPHA_SABLE O_OBJS += sys_sable.o diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/bios32.h linux/arch/alpha/kernel/bios32.h --- v2.2.0-pre6/linux/arch/alpha/kernel/bios32.h Wed Sep 9 14:51:03 1998 +++ linux/arch/alpha/kernel/bios32.h Sun Jan 10 09:59:54 1999 @@ -32,6 +32,13 @@ #define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */ /* + * We try to make the DEFAULT_MEM_BASE addresses *always* have more than + * a single bit set. This is so that devices like the broken Myrinet card + * will always have a PCI memory address that will never match a IDSEL + * address in PCI Config space, which can cause problems with early rev cards. + */ + +/* * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address * that get passed through the PCI<->ISA bridge chip. Although this causes * us to set the PCI->Mem window bases lower than normal, we still allocate @@ -45,22 +52,20 @@ #define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */ /* - * We try to make this address *always* have more than 1 bit set. - * this is so that devices like the broken Myrinet card will always have - * a PCI memory address that will never match a IDSEL address in - * PCI Config space, which can cause problems with early rev cards. - * - * However, APECS and LCA have only 34 bits for physical addresses, thus - * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb. + * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI + * bus memory addresses for SPARSE access to be less than 128Mb. */ #define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB) /* - * We try to make this address *always* have more than 1 bit set. - * this is so that devices like the broken Myrinet card will always have - * a PCI memory address that will never match a IDSEL address in - * PCI Config space, which can cause problems with early rev cards. - * + * Because the MCPCIA core logic supports more bits for physical addresses, + * it should allow an expanded range of SPARSE memory addresses. + * However, we do not use them all, in order to avoid the HAE manipulation + * that would be needed. + */ +#define RAWHIDE_DEFAULT_MEM_BASE (64*MB + 2*MB) + +/* * Because CIA and PYXIS and T2 have more bits for physical addresses, * they support an expanded range of SPARSE memory addresses. */ diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c --- v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_polaris.c Sun Jan 10 22:56:43 1999 @@ -0,0 +1,275 @@ +/* + * linux/arch/alpha/kernel/core_polaris.c + * + * POLARIS chip-specific code + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" +#include "bios32.h" + +/* + * BIOS32-style PCI interface: + */ + +#ifdef DEBUG_CONFIG +# define DBG_CFG(args) printk args +#else +# define DBG_CFG(args) +#endif + +#define DEBUG_MCHECK +#ifdef DEBUG_MCHECK +# define DBG_MCK(args) printk args +/* #define DEBUG_MCHECK_DUMP */ +#else +# define DBG_MCK(args) +#endif + +static volatile unsigned int POLARIS_mcheck_expected = 0; +static volatile unsigned int POLARIS_mcheck_taken = 0; +static volatile unsigned short POLARIS_jd = 0; + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address. This is fairly straightforward + * on POLARIS, since the chip itself generates Type 0 or Type 1 + * cycles automatically depending on the bus number (Bus 0 is + * hardwired to Type 0, all others are Type 1. Peer bridges + * are not supported). + * + * All types: + * + * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |1|1|1|1|1|0|0|1|1|1|1|1|1|1|1|0|B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|x|x| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., scsi and ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1) +{ + *type1 = (bus == 0) ? 0 : 1; + *pci_addr = (bus << 16) | (device_fn << 8) | (where) | + POLARIS_DENSE_CONFIG_BASE; + + DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " returning address 0x%p\n" + bus, device_fn, where, *pci_addr)); + + return 0; +} + +int +polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = __kernel_ldbu(*(vucp)pci_addr); + return PCIBIOS_SUCCESSFUL; +} + + +int +polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = __kernel_ldwu(*(vusp)pci_addr); + return PCIBIOS_SUCCESSFUL; +} + + +int +polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = *(vuip)pci_addr; + return PCIBIOS_SUCCESSFUL; +} + + +int +polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + __kernel_stb(value, *(vucp)pci_addr); + mb(); + __kernel_ldbu(*(vucp)pci_addr); + return PCIBIOS_SUCCESSFUL; +} + + +int +polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + __kernel_stw(value, *(vusp)pci_addr); + mb(); + __kernel_ldbu(*(vusp)pci_addr); + return PCIBIOS_SUCCESSFUL; +} + + +int +polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, + struct linux_hose_info *hose) +{ + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *(vuip)pci_addr = value; + mb(); + *(vuip)pci_addr; + return PCIBIOS_SUCCESSFUL; +} + +void __init +polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + /* May need to initialize error reporting (see PCICTL0/1), but + * for now assume that the firmware has done the right thing + * already. + */ +#if 0 + printk("polaris_init_arch(): trusting firmware for setup\n"); +#endif +} + +int polaris_pci_clr_err(void) +{ + POLARIS_jd = *((vusp)POLARIS_W_STATUS); + DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n", + POLARIS_jd)); + /* Write 1's to settable bits to clear errors */ + *((vusp)POLARIS_W_STATUS) = 0x7800; mb(); + POLARIS_jd = *((vusp)POLARIS_W_STATUS); + return 0; +} + +void polaris_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ + struct el_common *mchk_header; + struct el_POLARIS_sysdata_mcheck *mchk_sysdata; + + mchk_header = (struct el_common *)la_ptr; + + mchk_sysdata = + (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset); + +#if 0 + DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n", + POLARIS_mcheck_expected, mchk_sysdata->psc_status)); +#endif +#ifdef DEBUG_MCHECK_DUMP + { + unsigned long *ptr; + int i; + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); + } + } +#endif /* DEBUG_MCHECK_DUMP */ + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); + if (POLARIS_mcheck_expected) { + DBG_MCK(("POLARIS machine check expected\n")); + POLARIS_mcheck_expected = 0; + POLARIS_mcheck_taken = 1; + mb(); + mb(); + draina(); + polaris_pci_clr_err(); + wrmces(0x7); + mb(); + } +#if 1 + else { + printk("POLARIS machine check NOT expected\n") ; + DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + POLARIS_mcheck_expected = 0; + POLARIS_mcheck_taken = 1; + mb(); + mb(); + draina(); + polaris_pci_clr_err(); + wrmces(0x7); + mb(); + } +#endif +} diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c --- v2.2.0-pre6/linux/arch/alpha/kernel/core_t2.c Wed Sep 9 14:51:03 1998 +++ linux/arch/alpha/kernel/core_t2.c Sat Jan 9 19:08:21 1999 @@ -143,7 +143,7 @@ conf_read(unsigned long addr, unsigned char type1) { unsigned long flags; - unsigned int stat0, value, cpu; + unsigned int value, cpu; unsigned long t2_cfg = 0; cpu = smp_processor_id(); @@ -153,11 +153,14 @@ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); #if 0 - /* Reset status register to avoid losing errors. */ - stat0 = *(vulp)T2_IOCSR; - *(vulp)T2_IOCSR = stat0; - mb(); - DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0)); + { + unsigned long stat0; + /* Reset status register to avoid losing errors. */ + stat0 = *(vulp)T2_IOCSR; + *(vulp)T2_IOCSR = stat0; + mb(); + DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0)); + } #endif /* If Type1 access, must set T2 CFG. */ @@ -202,7 +205,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) { unsigned long flags; - unsigned int stat0, cpu; + unsigned int cpu; unsigned long t2_cfg = 0; cpu = smp_processor_id(); @@ -210,11 +213,14 @@ __save_and_cli(flags); /* avoid getting hit by machine check */ #if 0 - /* Reset status register to avoid losing errors. */ - stat0 = *(vulp)T2_IOCSR; - *(vulp)T2_IOCSR = stat0; - mb(); - DBG(("conf_write: T2 ERR was 0x%x\n", stat0)); + { + unsigned long stat0; + /* Reset status register to avoid losing errors. */ + stat0 = *(vulp)T2_IOCSR; + *(vulp)T2_IOCSR = stat0; + mb(); + DBG(("conf_write: T2 ERR was 0x%x\n", stat0)); + } #endif /* If Type1 access, must set T2 CFG. */ @@ -346,7 +352,6 @@ void __init t2_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - unsigned long t2_err; unsigned int i; for (i = 0; i < NR_CPUS; i++) { @@ -355,13 +360,15 @@ } #if 0 - /* - * Set up error reporting. - */ - t2_err = *(vulp)T2_IOCSR ; - t2_err |= (0x1 << 7) ; /* master abort */ - *(vulp)T2_IOCSR = t2_err ; - mb() ; + { + /* Set up error reporting. */ + unsigned long t2_err; + + t2_err = *(vulp)T2_IOCSR; + t2_err |= (0x1 << 7); /* master abort */ + *(vulp)T2_IOCSR = t2_err; + mb(); + } #endif printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE); diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c --- v2.2.0-pre6/linux/arch/alpha/kernel/core_tsunami.c Wed Sep 9 14:51:03 1998 +++ linux/arch/alpha/kernel/core_tsunami.c Sun Jan 10 22:56:43 1999 @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -302,14 +301,22 @@ * For now, windows 1,2 and 3 are disabled. In the future, * we may want to use them to do scatter/gather DMA. * - * Window 0 goes at 1 GB and is 1 GB large. + * Window 0 goes at 1 GB and is 1 GB large, mapping to 0. */ pchip->wsba[0].csr = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U); pchip->wsm[0].csr = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL; pchip->tba[0].csr = 0; +#if 0 pchip->wsba[1].csr = 0; +#else + /* make the second window at 2Gb for 1Gb mapping to 1Gb */ + pchip->wsba[1].csr = 1L | ((0x80000000U) & 0xfff00000U); + pchip->wsm[1].csr = (0x40000000UL - 1) & 0xfff00000UL; + pchip->tba[1].csr = 0x40000000; +#endif + pchip->wsba[2].csr = 0; pchip->wsba[3].csr = 0; mb(); @@ -359,7 +366,9 @@ /* Find how many hoses we have, and initialize them. */ tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start); - tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start); + /* must change this for TYPHOON which may have 4 */ + if (TSUNAMI_cchip->csc.csr & 1L<<14) + tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start); } static inline void @@ -378,7 +387,9 @@ { int cpu = smp_processor_id(); tsunami_pci_clr_err_1(TSUNAMI_pchip0, cpu); - tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu); + /* must change this for TYPHOON which may have 4 */ + if (TSUNAMI_cchip->csc.csr & 1L<<14) + tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu); return 0; } diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.2.0-pre6/linux/arch/alpha/kernel/entry.S Thu Dec 31 10:28:58 1998 +++ linux/arch/alpha/kernel/entry.S Sat Jan 9 19:08:21 1999 @@ -8,10 +8,9 @@ #define halt .long PAL_halt #define rti .long PAL_rti -#define SIGCHLD 20 +#define SIGCHLD 20 #define NR_SYSCALLS 370 -#define osf_vfork sys_fork /* * These offsets must match with alpha_mv in . @@ -502,6 +501,17 @@ .end sys_clone .align 3 +.globl sys_vfork +.ent sys_vfork +sys_vfork: + bsr $1,do_switch_stack + bis $30,$30,$16 + jsr $26,alpha_vfork + bsr $1,undo_switch_stack + ret $31,($26),1 +.end sys_vfork + +.align 3 .globl alpha_switch_to .ent alpha_switch_to alpha_switch_to: @@ -822,7 +832,7 @@ .quad sys_getpgrp .quad sys_getpagesize .quad alpha_ni_syscall /* 65 */ - .quad osf_vfork + .quad sys_vfork .quad sys_newstat .quad sys_newlstat .quad alpha_ni_syscall diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.2.0-pre6/linux/arch/alpha/kernel/irq.c Thu Dec 31 10:28:58 1998 +++ linux/arch/alpha/kernel/irq.c Sun Jan 10 09:59:54 1999 @@ -105,6 +105,8 @@ # define IACK_SC PYXIS_IACK_SC #elif defined(CONFIG_ALPHA_TSUNAMI) # define IACK_SC TSUNAMI_IACK_SC +#elif defined(CONFIG_ALPHA_POLARIS) +# define IACK_SC POLARIS_IACK_SC #else /* This is bogus but necessary to get it to compile on all platforms. */ # define IACK_SC 1L @@ -314,14 +316,14 @@ int get_irq_list(char *buf) { - int i, j; + int i; struct irqaction * action; char *p = buf; #ifdef __SMP__ p += sprintf(p, " "); - for (j = 0; j < smp_num_cpus; j++) - p += sprintf(p, "CPU%d ", j); + for (i = 0; i < smp_num_cpus; i++) + p += sprintf(p, "CPU%d ", i); *p++ = '\n'; #endif diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h --- v2.2.0-pre6/linux/arch/alpha/kernel/machvec.h Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/machvec.h Sun Jan 10 09:59:54 1999 @@ -13,6 +13,11 @@ we can read and write it as we like. ;-) */ #define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache) +/* Whee. POLARIS doesn't have an HAE. Fix things up for the GENERIC + kernel by defining the HAE address to be that of the cache. Now + we can read and write it as we like. ;-) */ +#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache) + /* Only a few systems don't define IACK_SC, handling all interrupts through the SRM console. But splitting out that one case from IO() below seems like such a pain. Define this to get things to compile. */ @@ -91,6 +96,7 @@ #define DO_LCA_IO IO(LCA,lca,lca) #define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia) #define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis) +#define DO_POLARIS_IO IO(POLARIS,polaris,polaris) #define DO_T2_IO IO(T2,t2,t2) #define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami) @@ -103,6 +109,7 @@ #define DO_LCA_BUS BUS(lca) #define DO_MCPCIA_BUS BUS(mcpcia) #define DO_PYXIS_BUS BUS(pyxis) +#define DO_POLARIS_BUS BUS(polaris) #define DO_T2_BUS BUS(t2) #define DO_TSUNAMI_BUS BUS(tsunami) diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.2.0-pre6/linux/arch/alpha/kernel/process.c Fri Jan 8 22:36:00 1999 +++ linux/arch/alpha/kernel/process.c Sat Jan 9 19:10:39 1999 @@ -55,6 +55,7 @@ unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; @@ -256,11 +257,26 @@ * with parameters (SIGCHLD, 0). */ int alpha_clone(unsigned long clone_flags, unsigned long usp, - struct switch_stack * swstack) + struct switch_stack * swstack) { if (!usp) usp = rdusp(); - return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1)); + return do_fork(clone_flags & ~CLONE_VFORK, usp, (struct pt_regs *) (swstack+1)); +} + +int alpha_vfork(struct switch_stack * swstack) +{ + int child; + struct semaphore sem = MUTEX_LOCKED; + + current->vfork_sem = &sem; + child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), + (struct pt_regs *) (swstack+1)); + + if (child > 0) + down(&sem); + + return child; } extern void ret_from_sys_call(void); diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h --- v2.2.0-pre6/linux/arch/alpha/kernel/proto.h Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/proto.h Sun Jan 10 09:59:59 1999 @@ -76,6 +76,22 @@ extern void mcpcia_init_arch(unsigned long *, unsigned long *); extern void mcpcia_machine_check(u64, u64, struct pt_regs *); +/* core_polaris.c */ +extern int polaris_hose_read_config_byte (u8, u8, u8, u8 *value, + struct linux_hose_info *hose); +extern int polaris_hose_read_config_word (u8, u8, u8, u16 *value, + struct linux_hose_info *hose); +extern int polaris_hose_read_config_dword (u8, u8, u8, u32 *value, + struct linux_hose_info *hose); +extern int polaris_hose_write_config_byte (u8, u8, u8, u8 value, + struct linux_hose_info *hose); +extern int polaris_hose_write_config_word (u8, u8, u8, u16 value, + struct linux_hose_info *hose); +extern int polaris_hose_write_config_dword (u8, u8, u8, u32 value, + struct linux_hose_info *hose); +extern void polaris_init_arch(unsigned long *, unsigned long *); +extern void polaris_machine_check(u64, u64, struct pt_regs *); + /* core_pyxis.c */ extern int pyxis_hose_read_config_byte (u8, u8, u8, u8 *value, struct linux_hose_info *hose); @@ -129,8 +145,6 @@ extern void tsunami_machine_check(u64, u64, struct pt_regs *); /* setup.c */ -extern void init_pit_rest(void); -extern void generic_init_pit (void); extern unsigned long srm_hae; /* smp.c */ @@ -143,6 +157,8 @@ /* time.c */ extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs); +extern void rtc_init_pit(void); +extern void generic_init_pit(void); extern unsigned long est_cycle_freq; /* smc37c93x.c */ diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.2.0-pre6/linux/arch/alpha/kernel/setup.c Wed Dec 16 10:32:54 1998 +++ linux/arch/alpha/kernel/setup.c Sun Jan 10 09:59:59 1999 @@ -109,6 +109,7 @@ extern struct alpha_machine_vector mikasa_mv; extern struct alpha_machine_vector mikasa_primo_mv; extern struct alpha_machine_vector monet_mv; +extern struct alpha_machine_vector webbrick_mv; extern struct alpha_machine_vector noname_mv; extern struct alpha_machine_vector noritake_mv; extern struct alpha_machine_vector noritake_primo_mv; @@ -116,6 +117,7 @@ extern struct alpha_machine_vector pc164_mv; extern struct alpha_machine_vector rawhide_mv; extern struct alpha_machine_vector ruffian_mv; +extern struct alpha_machine_vector rx164_mv; extern struct alpha_machine_vector sable_mv; extern struct alpha_machine_vector sable_gamma_mv; extern struct alpha_machine_vector sx164_mv; @@ -137,6 +139,7 @@ #pragma weak mikasa_mv #pragma weak mikasa_primo_mv #pragma weak monet_mv +#pragma weak webbrick_mv #pragma weak noname_mv #pragma weak noritake_mv #pragma weak noritake_primo_mv @@ -144,6 +147,7 @@ #pragma weak pc164_mv #pragma weak rawhide_mv #pragma weak ruffian_mv +#pragma weak rx164_mv #pragma weak sable_mv #pragma weak sable_gamma_mv #pragma weak sx164_mv @@ -264,7 +268,7 @@ if (initrd_end > *memory_end_p) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end, memory_end_p); + initrd_end, (unsigned long) memory_end_p); initrd_start = initrd_end = 0; } } @@ -275,6 +279,16 @@ if (alpha_mv.init_arch) alpha_mv.init_arch(memory_start_p, memory_end_p); + /* Initialize the timers. */ + /* ??? There is some circumstantial evidence that this needs + to be done now rather than later in time_init, which would + be more natural. Someone please explain or refute. */ +#if defined(CONFIG_RTC) + rtc_init_pit(); +#else + alpha_mv.init_pit(); +#endif + /* * Give us a default console. TGA users will see nothing until * chr_dev_init is called, rather late in the boot sequence. @@ -349,8 +363,8 @@ static char unofficial_names[][8] = {"100", "Ruffian"}; -static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164"}; -static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3}; +static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"}; +static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4}; static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"}; static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2}; @@ -430,7 +444,7 @@ static struct alpha_machine_vector *eb164_vecs[] __initlocaldata = { - &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv + &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv, &rx164_mv }; static struct alpha_machine_vector *eb64p_vecs[] __initlocaldata = @@ -455,7 +469,7 @@ &monet_mv, /* monet */ &dp264_mv, /* clipper */ &dp264_mv, /* goldrush */ - &dp264_mv, /* webbrick */ + &webbrick_mv, /* webbrick */ &dp264_mv, /* catamaran */ }; @@ -556,10 +570,12 @@ &pc164_mv, &rawhide_mv, &ruffian_mv, + &rx164_mv, &sable_mv, &sable_gamma_mv, &sx164_mv, &takara_mv, + &webbrick_mv, &xl_mv, &xlt_mv }; diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.2.0-pre6/linux/arch/alpha/kernel/sys_dp264.c Wed Dec 16 10:32:54 1998 +++ linux/arch/alpha/kernel/sys_dp264.c Sun Jan 10 09:59:59 1999 @@ -125,6 +125,7 @@ outb(0, DMA1_RESET_REG); outb(0, DMA2_RESET_REG); outb(DMA_MODE_CASCADE, DMA2_MODE_REG); + outb(0, DMA2_MASK_REG); if (alpha_using_srm) alpha_mv.device_interrupt = dp264_srm_device_interrupt; @@ -287,6 +288,29 @@ return slot; } +static int __init +webbrick_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[13][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { -1, -1, -1, -1, -1}, /* IdSel 7 ISA Bridge */ + { -1, -1, -1, -1, -1}, /* IdSel 8 unused */ + { 29, 29, 29, 29, 29}, /* IdSel 9 21143 #1 */ + { -1, -1, -1, -1, -1}, /* IdSel 10 unused */ + { 30, 30, 30, 30, 30}, /* IdSel 11 21143 #2 */ + { -1, -1, -1, -1, -1}, /* IdSel 12 unused */ + { -1, -1, -1, -1, -1}, /* IdSel 13 unused */ + { 47, 47, 46, 45, 44}, /* IdSel 14 slot 0 */ + { 39, 39, 38, 37, 36}, /* IdSel 15 slot 1 */ + { 43, 43, 42, 41, 40}, /* IdSel 16 slot 2 */ + { 35, 35, 34, 33, 32}, /* IdSel 17 slot 3 */ +}; + const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5; + int irq = COMMON_TABLE_LOOKUP; + + return irq; +} + static void __init dp264_pci_fixup(void) { @@ -304,6 +328,14 @@ SMC669_Init(); } +static void __init +webbrick_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(webbrick_map_irq, common_swizzle); + SMC669_Init(); +} + /* * The System Vectors @@ -353,5 +385,27 @@ pci_fixup: monet_pci_fixup, kill_arch: generic_kill_arch, }; -/* No alpha_mv alias for monet, since we compile it in unconditionally + +struct alpha_machine_vector webbrick_mv __initmv = { + vector_name: "Webbrick", + DO_EV6_MMU, + DO_DEFAULT_RTC, + DO_TSUNAMI_IO, + DO_TSUNAMI_BUS, + machine_check: tsunami_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 64, + irq_probe_mask: _PROBE_MASK(64), + update_irq_hw: dp264_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: dp264_device_interrupt, + + init_arch: tsunami_init_arch, + init_irq: dp264_init_irq, + init_pit: generic_init_pit, + pci_fixup: webbrick_pci_fixup, + kill_arch: generic_kill_arch, +}; +/* No alpha_mv alias for webbrick, since we compile it in unconditionally with DP264; setup_arch knows how to cope. */ diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c --- v2.2.0-pre6/linux/arch/alpha/kernel/sys_rawhide.c Wed Sep 9 14:51:04 1998 +++ linux/arch/alpha/kernel/sys_rawhide.c Sun Jan 10 09:59:59 1999 @@ -159,7 +159,7 @@ static void __init rawhide_pci_fixup(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + layout_all_busses(DEFAULT_IO_BASE, RAWHIDE_DEFAULT_MEM_BASE); common_pci_fixup(rawhide_map_irq, common_swizzle); } diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c --- v2.2.0-pre6/linux/arch/alpha/kernel/sys_ruffian.c Mon Dec 28 15:00:52 1998 +++ linux/arch/alpha/kernel/sys_ruffian.c Sat Jan 9 19:08:27 1999 @@ -82,7 +82,7 @@ * then all the PCI slots/INTXs (12-31) * flash(5) :DWH: */ - pld &= 0x00000000ffffff9fUL; /* was ffff7f */ + pld &= 0x00000000ffffff9fUL; /* was ffff7f */ /* * Now for every possible bit set, work through them and call @@ -118,12 +118,12 @@ } else { handle_irq(j, j, regs); } - } else { /* if not an ISA int */ + } else { /* if not an ISA int */ handle_irq(16 + i, 16 + i, regs); } - *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); - *(vulp)PYXIS_INT_REQ; /* read to force the write */ + *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); + *(vulp)PYXIS_INT_REQ; /* read to force the write */ } } @@ -222,7 +222,7 @@ pyxis_enable_errors(); if (!pyxis_srm_window_setup()) { - printk("ruffian_init_arch: Skipping window register rewrites." + printk("ruffian_init_arch: Skipping window register rewrites." "\n... Trust DeskStation firmware!\n"); } pyxis_finish_init_arch(); @@ -233,7 +233,10 @@ { /* Ruffian depends on the system timer established in MILO! */ request_region(0x70, 0x10, "timer"); - init_pit_rest(); + + outb(0xb6, 0x43); /* pit counter 2: speaker */ + outb(0x31, 0x42); + outb(0x13, 0x42); } static void diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_rx164.c linux/arch/alpha/kernel/sys_rx164.c --- v2.2.0-pre6/linux/arch/alpha/kernel/sys_rx164.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_rx164.c Sun Jan 10 09:59:59 1999 @@ -0,0 +1,237 @@ +/* + * linux/arch/alpha/kernel/sys_rx164.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the RX164 (PCA56+POLARIS). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +rx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + unsigned int temp; + pcibios_write_config_dword(0, 0, 0x74, ~mask >> 16); + pcibios_read_config_dword(0, 0, 0x74, &temp); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ +#if 0 + if (irq >= 16) { + if (unmask_p) + cserve_ena(irq - 16); + else + cserve_dis(irq - 16); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +#endif +} + +static void +rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + unsigned long pic; + + /* + * It seems to me that the probability of two or more *device* + * interrupts occurring at almost exactly the same time is + * pretty low. So why pay the price of checking for + * additional interrupts here if the common case can be + * handled so much easier? + */ + /* + * The first read of the PIC gives you *all* interrupting lines. + * Therefore, read the mask register and and out those lines + * not enabled. Note that some documentation has 21 and a1 + * write only. This is not true. + */ + pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */ + pic &= ~alpha_irq_mask; /* apply mask */ + pic &= 0xFFFB; /* mask out cascade & hibits */ + + while (pic) { + int j = ffz(~pic); + pic &= pic - 1; + handle_irq(j, j, regs); + } +} + +static void +rx164_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + int i; + + /* Read the interrupt summary register. On Polaris, + * this is the DIRR register in PCI config space (offset 0x84) + */ + pld = 0; + pcibios_read_config_dword(0, 0, 0x84, (unsigned int *)&pld); + +#if 0 + printk("PLD 0x%lx\n", pld); +#endif + + if (pld & 0xffffffff00000000UL) pld &= 0x00000000ffffffffUL; + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 20) { + rx164_isa_device_interrupt(vector, regs); + } else { + handle_irq(16+i, 16+i, regs); + } + } +} + +static void +rx164_init_irq(void) +{ + unsigned int temp; + + STANDARD_INIT_IRQ_PROLOG; + + pcibios_write_config_dword(0, 0, 0x74, (~alpha_irq_mask >> 16)); + pcibios_read_config_dword(0, 0, 0x74, &temp); + + enable_irq(16 + 20); /* enable ISA interrupts */ + enable_irq(2); /* enable cascade */ +} +/* The RX164 changed its interrupt routing between pass1 and pass2... + * + * PASS1: + * + * Slot IDSEL INTA INTB INTC INTD + * 0 6 5 10 15 20 + * 1 7 4 9 14 19 + * 2 5 3 8 13 18 + * 3 9 2 7 12 17 + * 4 10 1 6 11 16 + * + * PASS2: + * Slot IDSEL INTA INTB INTC INTD + * 0 5 1 7 12 17 + * 1 6 2 8 13 18 + * 2 8 3 9 14 19 + * 3 9 4 10 15 20 + * 4 10 5 11 16 6 + * + */ + +/* + * IdSel + * 5 32 bit PCI option slot 0 + * 6 64 bit PCI option slot 1 + * 7 PCI-ISA bridge + * 7 64 bit PCI option slot 2 + * 9 32 bit PCI option slot 3 + * 10 PCI-PCI bridge + * + */ + +static int __init +rx164_map_irq(struct pci_dev *dev, int slot, int pin) +{ +#if 0 + char irq_tab_pass1[6][5] = { + /*INT INTA INTB INTC INTD */ + { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */ + { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */ + { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */ + { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */ + { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */ + { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */ + }; +#endif + char irq_tab[6][5] = { + /*INT INTA INTB INTC INTD */ + { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */ + { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */ + { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */ + { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */ + { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */ + { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */ + }; + const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; + /* JRP - Need to figure out how to distinguish pass1 from pass2, + * and use the correct table... + */ + return COMMON_TABLE_LOOKUP; +} + +void __init +rx164_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(rx164_map_irq, common_swizzle); +} + + +/* + * The System Vector + */ + +#define POLARIS_IACK_SC POLARIS_IACK_BASE /* hack, move to header */ + +struct alpha_machine_vector rx164_mv __initmv = { + vector_name: "RX164", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_POLARIS_IO, + DO_POLARIS_BUS, + machine_check: polaris_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 40, + irq_probe_mask: _PROBE_MASK(40), + update_irq_hw: rx164_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: rx164_device_interrupt, + + init_arch: polaris_init_arch, + init_irq: rx164_init_irq, + init_pit: generic_init_pit, + pci_fixup: rx164_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(rx164) diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.2.0-pre6/linux/arch/alpha/kernel/time.c Mon Dec 28 15:00:52 1998 +++ linux/arch/alpha/kernel/time.c Sat Jan 9 19:08:27 1999 @@ -158,43 +158,28 @@ * drivers depend on them being initialized (e.g., joystick driver). */ -/* It is (normally) only counter 0 that presents config problems, so - provide this support function to do the rest of the job. */ - -void inline -init_pit_rest(void) -{ -#if 0 - /* Leave refresh timer alone---nobody should depend on a - particular value anyway. */ - outb(0x54, 0x43); /* counter 1: refresh timer */ - outb(0x18, 0x41); -#endif - - outb(0xb6, 0x43); /* counter 2: speaker */ - outb(0x31, 0x42); - outb(0x13, 0x42); -} - #ifdef CONFIG_RTC -static inline void +void rtc_init_pit (void) { unsigned char control; - /* Setup interval timer if /dev/rtc is being used */ + /* Turn off RTC interrupts before /dev/rtc is initialized */ + control = CMOS_READ(RTC_CONTROL); + control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); + CMOS_WRITE(control, RTC_CONTROL); + (void) CMOS_READ(RTC_INTR_FLAGS); + + request_region(0x40, 0x20, "timer"); /* reserve pit */ + + /* Setup interval timer. */ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb(LATCH & 0xff, 0x40); /* LSB */ outb(LATCH >> 8, 0x40); /* MSB */ - request_region(0x40, 0x20, "timer"); /* reserve pit */ - /* Turn off RTC interrupts before /dev/rtc is initialized */ - control = CMOS_READ(RTC_CONTROL); - control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); - CMOS_WRITE(control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - init_pit_rest(); + outb(0xb6, 0x43); /* pit counter 2: speaker */ + outb(0x31, 0x42); + outb(0x13, 0x42); } #endif @@ -203,7 +188,7 @@ { unsigned char x; - /* Reset periodic interrupt frequency. */ + /* Reset periodic interrupt frequency. */ x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; if (x != 0x26 && x != 0x19 && x != 0x06) { printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x); @@ -218,36 +203,26 @@ x &= ~(RTC_AIE | RTC_UIE); CMOS_WRITE(x, RTC_CONTROL); } - CMOS_READ(RTC_INTR_FLAGS); + (void) CMOS_READ(RTC_INTR_FLAGS); request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */ - /* Turn off the PIT. */ - outb(0x36, 0x43); /* counter 0: system timer */ + outb(0x36, 0x43); /* pit counter 0: system timer */ outb(0x00, 0x40); outb(0x00, 0x40); - init_pit_rest(); + outb(0xb6, 0x43); /* pit counter 2: speaker */ + outb(0x31, 0x42); + outb(0x13, 0x42); } -/* This probably isn't Right, but it is what the old code did. */ -#if defined(CONFIG_RTC) -# define init_pit rtc_init_pit -#else -# define init_pit alpha_mv.init_pit -#endif - - void time_init(void) { - void (*irq_handler)(int, void *, struct pt_regs *); + void (*irq_handler)(int, void *, struct pt_regs *); unsigned int year, mon, day, hour, min, sec, cc1, cc2; unsigned long cycle_freq; - /* Initialize the timers. */ - init_pit(); - /* * The Linux interpretation of the CMOS clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the @@ -322,8 +297,8 @@ state.partial_tick = 0L; /* setup timer */ - irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL)) + irq_handler = timer_interrupt; + if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL)) panic("Could not allocate timer IRQ!"); } diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c --- v2.2.0-pre6/linux/arch/i386/kernel/ioport.c Thu May 7 22:51:46 1998 +++ linux/arch/i386/kernel/ioport.c Mon Jan 11 15:02:52 1999 @@ -58,7 +58,7 @@ if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32)) return -EINVAL; - if (!capable(CAP_SYS_RAWIO)) + if (turn_on && !capable(CAP_SYS_RAWIO)) return -EPERM; /* * If it's the first ioperm() call in this thread's lifetime, set the @@ -91,11 +91,15 @@ { struct pt_regs * regs = (struct pt_regs *) &unused; unsigned int level = regs->ebx; + unsigned int old = (regs->eflags >> 12) & 3; if (level > 3) return -EINVAL; - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; + /* Trying to gain more privileges? */ + if (level > old) { + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + } regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12); return 0; } diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.2.0-pre6/linux/arch/i386/kernel/process.c Fri Jan 8 22:36:00 1999 +++ linux/arch/i386/kernel/process.c Sat Jan 9 00:07:41 1999 @@ -778,17 +778,19 @@ newsp = regs.ecx; if (!newsp) newsp = regs.esp; - return do_fork(clone_flags, newsp, ®s); + return do_fork(clone_flags & ~CLONE_VFORK, newsp, ®s); } asmlinkage int sys_vfork(struct pt_regs regs) { - int child; + int child; + struct semaphore sem = MUTEX_LOCKED; - child = do_fork(CLONE_VM | SIGCHLD, regs.esp, ®s); + current->vfork_sem = &sem; + child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s); if (child > 0) - sleep_on(¤t->vfork_sleep); + down(&sem); return child; } diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.2.0-pre6/linux/arch/i386/kernel/ptrace.c Fri Jan 8 22:36:01 1999 +++ linux/arch/i386/kernel/ptrace.c Tue Jan 12 12:03:53 1999 @@ -67,33 +67,6 @@ return 0; } -extern int _stext, _etext; -static void print_child_state(struct task_struct *task) -{ - unsigned int * stack = (unsigned int *) task->tss.esp; - int count = 40; - - printk("Process: %s (stack=%p, task=%p)\n", task->comm, stack, task); - for (;;) { - unsigned int data; - if ((unsigned int) stack < (unsigned int) task) - break; - if ((unsigned int) stack >= 2*PAGE_SIZE + (unsigned int) task) - break; - data = *stack; - stack++; - if (data < (unsigned long) &_stext) - continue; - if (data >= (unsigned long) &_etext) - continue; - printk("[<%08x>] ", data); - if (--count) - continue; - break; - } - printk("\n"); -} - /* * This routine gets a long from any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, @@ -400,7 +373,6 @@ read_unlock(&tasklist_lock); /* FIXME!!! */ if (!child) goto out; -print_child_state(child); ret = -EPERM; if (pid == 1) /* you may not mess with init */ goto out; diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.2.0-pre6/linux/drivers/block/floppy.c Thu Nov 12 16:21:18 1998 +++ linux/drivers/block/floppy.c Sun Jan 10 09:59:59 1999 @@ -4154,6 +4154,7 @@ fdc_state[1].address = FDC2; #endif + fdc = 0; /* reset fdc in case of unexpected interrupt */ if (floppy_grab_irq_and_dma()){ del_timer(&fd_timeout); blk_dev[MAJOR_NR].request_fn = NULL; diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.2.0-pre6/linux/drivers/block/genhd.c Thu Jan 7 15:11:36 1999 +++ linux/drivers/block/genhd.c Fri Jan 8 22:54:17 1999 @@ -439,7 +439,7 @@ #ifdef CONFIG_BSD_DISKLABEL /* no bsd disklabel as a default */ kdev_t bsd_kdev = 0; - int bsd_maxpart; + int bsd_maxpart = BSD_MAXPARTITIONS; #endif #ifdef CONFIG_BLK_DEV_IDE int tested_for_xlate = 0; @@ -558,23 +558,15 @@ } #ifdef CONFIG_BSD_DISKLABEL /* tag first disklabel for late recognition */ - if (SYS_IND(p) == BSD_PARTITION) { + if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) { printk("!"); - if (!bsd_kdev) { + if (!bsd_kdev) bsd_kdev = MKDEV(hd->major, minor); - bsd_maxpart = BSD_MAXPARTITIONS; - } } else if (SYS_IND(p) == OPENBSD_PARTITION) { printk("!"); if (!bsd_kdev) { bsd_kdev = MKDEV(hd->major, minor); bsd_maxpart = OPENBSD_MAXPARTITIONS; - } - } else if (SYS_IND(p) == NETBSD_PARTITION) { - printk("!"); - if (!bsd_kdev) { - bsd_kdev = MKDEV(hd->major, minor); - bsd_maxpart = BSD_MAXPARTITIONS; } } #endif diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.2.0-pre6/linux/drivers/char/epca.c Thu Dec 31 10:28:59 1998 +++ linux/drivers/char/epca.c Sat Jan 9 19:16:43 1999 @@ -2363,10 +2363,10 @@ eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART)); } - /* Get the channel the event occured on */ + /* Get the channel the event occurred on */ channel = eventbuf[0]; - /* Get the actual event code that occured */ + /* Get the actual event code that occurred */ event = eventbuf[1]; /* ---------------------------------------------------------------- diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c --- v2.2.0-pre6/linux/drivers/char/lp_m68k.c Fri Jan 1 12:58:20 1999 +++ linux/drivers/char/lp_m68k.c Sat Jan 9 19:16:43 1999 @@ -531,7 +531,7 @@ * (un-)register for hardware drivers * tab is an inititalised lp_struct, dev the desired minor * if dev < 0, let the driver choose the first free minor - * if sucessful return the minor, else -1 + * if successful return the minor, else -1 */ int register_parallel(struct lp_struct *tab, int dev) { diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.2.0-pre6/linux/drivers/char/pc_keyb.c Mon Dec 28 15:00:52 1998 +++ linux/drivers/char/pc_keyb.c Tue Jan 12 10:14:40 1999 @@ -55,6 +55,7 @@ #endif static void kbd_write(int address, int data); +static unsigned char handle_kbd_event(void); spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; @@ -101,16 +102,15 @@ static inline void kb_wait(void) { unsigned long timeout = KBC_TIMEOUT; - unsigned char status; do { - status = inb_p(KBD_STATUS_REG); - if (status & KBD_STAT_OBF) { - if (status & KBD_STAT_MOUSE_OBF) - inb_p(KBD_DATA_REG); /* Flush. */ - } + /* + * "handle_kbd_event()" will handle any incoming events + * while we wait - keypresses or mouse movement. + */ + unsigned char status = handle_kbd_event(); - if (! (inb_p(KBD_STATUS_REG) & KBD_STAT_IBF)) + if (! (status & KBD_STAT_IBF)) return; mdelay(1); timeout--; @@ -256,25 +256,6 @@ e0_keys[scancode - 128]; } -#if DISABLE_KBD_DURING_INTERRUPTS -static inline void send_cmd(unsigned char c) -{ - unsigned long flags; - - spin_lock_irqsave(&kbd_controller_lock, flags); - kb_wait(); - outb(c, KBD_CNTL_REG); - spin_unlock_irqrestore(&kbd_controller_lock, flags); -} - -/* #define disable_keyboard() do { send_cmd(KBD_CCMD_KBD_DISABLE); kb_wait(); } while (0) */ -#define disable_keyboard() send_cmd(KBD_CCMD_KBD_DISABLE) -#define enable_keyboard() send_cmd(KBD_CCMD_KBD_ENABLE) -#else -#define disable_keyboard() /* nothing */ -#define enable_keyboard() /* nothing */ -#endif - static int do_acknowledge(unsigned char scancode) { if (reply_expected) { @@ -419,16 +400,17 @@ return 0200; } -static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) +/* + * This reads the keyboard status port, and does the + * appropriate action. + * + * It requires that we hold the keyboard controller + * spinlock. + */ +static unsigned char handle_kbd_event(void) { - unsigned long flags; - unsigned char status; - - disable_keyboard(); - spin_lock_irqsave(&kbd_controller_lock, flags); - kbd_pt_regs = regs; + unsigned char status = inb(KBD_STATUS_REG); - status = inb(KBD_STATUS_REG); while (status & KBD_STAT_OBF) { unsigned char scancode; @@ -459,8 +441,19 @@ status = inb(KBD_STATUS_REG); } + return status; +} + + +static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + + kbd_pt_regs = regs; + + spin_lock_irqsave(&kbd_controller_lock, flags); + handle_kbd_event(); spin_unlock_irqrestore(&kbd_controller_lock, flags); - enable_keyboard(); } /* diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c --- v2.2.0-pre6/linux/drivers/char/radio-aimslab.c Wed Aug 26 11:37:37 1998 +++ linux/drivers/char/radio-aimslab.c Sun Jan 10 22:28:14 1999 @@ -101,6 +101,7 @@ outb(0x48, io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ outb(0xd0, io); /* volume steady, off */ + dev->curvol = 0; /* track the volume state! */ return 0; } diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.2.0-pre6/linux/drivers/char/vt.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/char/vt.c Sun Jan 10 22:56:43 1999 @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.2.0-pre6/linux/drivers/net/3c59x.c Fri Jan 8 22:36:06 1999 +++ linux/drivers/net/3c59x.c Sat Jan 9 19:16:43 1999 @@ -86,9 +86,7 @@ #include -#if (LINUX_VERSION_CODE >= 0x20100) -char kernel_version[] = UTS_RELEASE; -#else +#if (LINUX_VERSION_CODE <= 0x20100) #ifndef __alpha__ #define ioremap(a,b) \ (((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b)) diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.2.0-pre6/linux/drivers/net/epic100.c Fri Jan 1 12:58:20 1999 +++ linux/drivers/net/epic100.c Sat Jan 9 19:16:43 1999 @@ -58,10 +58,8 @@ #endif #include -#include #include #include -#include #include #include #include @@ -77,7 +75,6 @@ #include /* Processor type for cache alignment. */ #include #include -#include #include #include @@ -125,11 +122,10 @@ I. Board Compatibility -This device driver is designed for the SMC "EPCI/100", the SMC +This device driver is designed for the SMC "EPIC/100", the SMC single-chip Ethernet controllers for PCI. This chip is used on the SMC EtherPower II boards. - II. Board-specific settings PCI bus devices are configured by the system at boot time, so no jumpers @@ -144,9 +140,10 @@ IVb. References -http://www.smc.com/components/catalog/smc83c170.html +http://www.smsc.com/main/datasheets/83c171.pdf +http://www.smsc.com/main/datasheets/83c175.pdf http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html -http://www.national.com/pf/DP/DP83840.html +http://www.national.com/pf/DP/DP83840A.html IVc. Errata @@ -162,6 +159,7 @@ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; + struct chip_info { const char *name; u16 vendor_id, device_id, device_id_mask, pci_flags; @@ -221,7 +219,7 @@ const char *product_name; struct device *next_module; - /* Rx and Rx rings here so that they remain paragraph aligned. */ + /* Tx and Rx rings here so that they remain paragraph aligned. */ struct epic_rx_desc rx_ring[RX_RING_SIZE]; struct epic_tx_desc tx_ring[TX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ @@ -930,7 +928,7 @@ #if defined(__i386__) /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n", dev->name); dev->interrupt = 0; /* Avoid halting machine. */ return; diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.2.0-pre6/linux/drivers/net/hp100.c Fri Jan 8 22:36:07 1999 +++ linux/drivers/net/hp100.c Mon Jan 11 10:55:29 1999 @@ -2798,7 +2798,7 @@ if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break; } while (time_after(time, jiffies)); - if ( time_before_eq(jiffies, time) ) /* no signal->no logout */ + if ( time_after_eq(jiffies, time) ) /* no signal->no logout */ return 0; /* Drop the VG Link by clearing the link up cmd and load addr.*/ @@ -2813,7 +2813,7 @@ } while(time_after(time, jiffies)); #ifdef HP100_DEBUG - if (time_before_eq(jiffies, time)) + if (time_after_eq(jiffies, time)) printk("hp100: %s: down_vg_link: Link does not go down?\n", dev->name); #endif diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v2.2.0-pre6/linux/drivers/net/tulip.c Thu Jan 7 15:11:37 1999 +++ linux/drivers/net/tulip.c Sun Jan 10 09:59:59 1999 @@ -104,9 +104,6 @@ #define NEW_MULTICAST #include #endif -#if (LINUX_VERSION_CODE >= 0x20100) -char kernel_version[] = UTS_RELEASE; -#endif #ifdef SA_SHIRQ #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) #else @@ -465,7 +462,7 @@ #endif for (;pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; - u32 pci_ioaddr; + unsigned long pci_ioaddr = 0; int chip_idx = 0; if (pcibios_find_class @@ -503,7 +500,7 @@ pci_ioaddr &= ~3; if (tulip_debug > 2) - printk(KERN_DEBUG "Found %s at I/O %#x.\n", + printk(KERN_DEBUG "Found %s at I/O %#lx.\n", tulip_tbl[chip_idx].chip_name, pci_ioaddr); if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size)) diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c --- v2.2.0-pre6/linux/drivers/scsi/AM53C974.c Sun Jun 7 11:16:33 1998 +++ linux/drivers/scsi/AM53C974.c Mon Jan 11 13:46:47 1999 @@ -756,7 +756,7 @@ (search->irq != instance->irq) || (search == instance)); search = search->next); if (!search) { - if (request_irq(instance->irq, do_AM53C974_intr, SA_INTERRUPT, "AM53C974", NULL)) { + if (request_irq(instance->irq, do_AM53C974_intr, SA_SHIRQ, "AM53C974", instance)) { printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq); scsi_unregister(instance); return 0; @@ -2458,7 +2458,7 @@ */ int AM53C974_release(struct Scsi_Host *shp) { - free_irq(shp->irq, NULL); + free_irq(shp->irq, shp); scsi_unregister(shp); return 0; } diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v2.2.0-pre6/linux/drivers/scsi/aha152x.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/scsi/aha152x.c Sat Jan 9 19:16:43 1999 @@ -247,7 +247,7 @@ C/H/S addressing. The number of cylinders/heads/sectors is called geometry and is required - as base for requests in C/H/S adressing. SCSI only knows about the + as base for requests in C/H/S addressing. SCSI only knows about the total capacity of disks in blocks (sectors). Therefore the SCSI BIOS/DOS driver has to calculate a logical/virtual @@ -276,7 +276,7 @@ extended translation. This means that the BIOS uses 255 for heads, 63 for sectors and then divides the capacity of the disk by 255*63 (about 8 MB), as soon it sees a disk greater than 1 GB. That results - in a maximum of about 8 GB adressable diskspace in the partition table + in a maximum of about 8 GB addressable diskspace in the partition table (but there are already bigger disks out there today). To make it even more complicated the translation mode might/might diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.2.0-pre6/linux/drivers/scsi/aic7xxx.c Thu Jan 7 15:11:37 1999 +++ linux/drivers/scsi/aic7xxx.c Sun Jan 10 12:42:42 1999 @@ -354,7 +354,7 @@ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.9" +#define AIC7XXX_C_VERSION "5.1.10" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -9116,19 +9116,22 @@ { case AHC_AIC7870: /* 3840 / 3985 */ case AHC_AIC7880: /* 3840 UW / 3985 UW */ - switch(PCI_SLOT(temp_p->pci_device_fn)) + if(temp_p->flags & AHC_MULTI_CHANNEL) { - case 5: - temp_p->flags |= AHC_CHNLB; - break; - case 8: - temp_p->flags |= AHC_CHNLB; - break; - case 12: - temp_p->flags |= AHC_CHNLC; - break; - default: - break; + switch(PCI_SLOT(temp_p->pci_device_fn)) + { + case 5: + temp_p->flags |= AHC_CHNLB; + break; + case 8: + temp_p->flags |= AHC_CHNLB; + break; + case 12: + temp_p->flags |= AHC_CHNLC; + break; + default: + break; + } } break; @@ -10999,11 +11002,13 @@ * entirely and avoids getting a bogus dead command back through the * mid-level code due to too many retries. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132) if ( flags & SCSI_RESET_SYNCHRONOUS ) { cmd->result = DID_BUS_BUSY << 16; cmd->done(cmd); } +#endif p->flags &= ~AHC_IN_RESET; /* * We can't rely on run_waiting_queues to unpause the sequencer for diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/atari_dma_emul.c linux/drivers/scsi/atari_dma_emul.c --- v2.2.0-pre6/linux/drivers/scsi/atari_dma_emul.c Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/atari_dma_emul.c Sat Jan 9 19:16:43 1999 @@ -429,7 +429,7 @@ if (eff_addr == &hades_psdm_reg) { /* - * Bus error occured while reading the pseudo + * Bus error occurred while reading the pseudo * DMA register. Time out. */ diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.2.0-pre6/linux/drivers/scsi/gdth.c Mon Dec 28 15:00:52 1998 +++ linux/drivers/scsi/gdth.c Mon Jan 11 10:17:20 1999 @@ -2,7 +2,7 @@ * GDT ISA/EISA/PCI Disk Array Controller driver for Linux * * * * gdth.c * - * Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner * + * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner * * * * * * * @@ -20,27 +20,49 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.1.61 * + * Tested with Linux 1.2.13, ..., 2.1.131 * * * * $Log: gdth.c,v $ - * Revision 1.3 1998/02/25 23:52:32 ecd - * Final round of PCI device driver patches by Martin Mares. + * Revision 1.17 1998/12/17 15:58:11 achim + * Command line parameters implemented + * Changes for Alpha platforms + * PCI controller scan changed + * SMP support improved (spin_lock_irqsave(),...) + * New async. events, new scan/reserve commands included * - * 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.16 1998/09/28 16:08:46 achim + * GDT_PCIMPR: DPMEM remapping, if required + * mdelay() added * - * 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.15 1998/06/03 14:54:06 achim + * gdth_delay(), gdth_flush() implemented + * Bugfix: gdth_release() changed + * + * Revision 1.14 1998/05/22 10:01:17 achim + * mj: pcibios_strerror() removed + * Improved SMP support (if version >= 2.1.95) + * gdth_halt(): halt_called flag added (if version < 2.1) + * + * Revision 1.13 1998/04/16 09:14:57 achim + * Reserve drives (for raw service) implemented + * New error handling code enabled + * Get controller name from board_info() IOCTL + * Final round of PCI device driver patches by Martin Mares + * + * Revision 1.12 1998/03/03 09:32:37 achim + * Fibre channel controller support added + * + * Revision 1.11 1998/01/27 16:19:14 achim + * SA_SHIRQ added + * add_timer()/del_timer() instead of GDTH_TIMER + * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER + * New error handling included * * Revision 1.10 1997/10/31 12:29:57 achim * Read heads/sectors from host drive * * Revision 1.9 1997/09/04 10:07:25 achim - * IO-mapping with virt_to_bus(), readb(), writeb(), ... + * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ... * register_reboot_notifier() to get a notify on shutdown used * * Revision 1.8 1997/04/02 12:14:30 achim @@ -72,9 +94,49 @@ * Revision 1.1 1996/04/11 07:35:57 achim * Initial revision * - * - * $Id: gdth.c,v 1.4 1998/04/15 14:35:26 mj Exp $ ************************************************************************/ +#ident "$Id: gdth.c,v 1.17 1998/12/17 15:58:11 achim Exp $" + +/* All GDT Disk Array Controllers are fully supported by this driver. + * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the + * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete + * list of all controller types. + * + * If you have one or more GDT3000/3020 EISA controllers with + * controller BIOS disabled, you have to set the IRQ values with the + * command line option "gdth=irq1,irq2,...", where the irq1,irq2,... are + * the IRQ values for the EISA controllers. + * + * After the optional list of IRQ values, other possible + * command line options are: + * disable:Y disable driver + * disable:N enable driver + * reserve_mode:0 reserve no drives for the raw service + * reserve_mode:1 reserve all not init., removable drives + * reserve_mode:2 reserve all not init. drives + * reserve_list:h,b,t,l,h,b,t,l,... reserve particular drive(s) with + * h- controller no., b- channel no., + * t- target ID, l- LUN + * reverse_scan:Y reverse scan order for PCI controllers + * reverse_scan:N scan PCI controllers like BIOS + * max_ids:x x - target ID count per channel (1..MAXID) + * rescan:Y rescan all channels/IDs + * rescan:N use all devices found until now + * + * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N, + * max_ids:127,rescan:N". + * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". + * + * When loading the gdth driver as a module, the same options are available. + * You can set the IRQs with "IRQ=...". However, the syntax to specify the + * options changes slightly. You must replace all ',' between options + * with ' ' and all ':' with '=' and you must use + * '1' in place of 'Y' and '0' in place of 'N'. + * + * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 + * max_ids=127 rescan=0" + * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". + */ #ifdef MODULE #include @@ -85,6 +147,7 @@ #include #include #include +#include #include #include #include @@ -101,7 +164,9 @@ #include #include #include +#if LINUX_VERSION_CODE >= 0x02015F #include +#endif #if LINUX_VERSION_CODE >= 0x010300 #include @@ -116,33 +181,34 @@ #if LINUX_VERSION_CODE >= 0x010346 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs); -static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs); #else static void gdth_interrupt(int irq,struct pt_regs *regs); #endif static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); static int gdth_async_event(int hanum,int service); +static void gdth_log_event(gdth_evt_data *dvr); static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority); static void gdth_next(int hanum); static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b); -static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b); -static gdth_evt_str *gdth_store_event(ushort source, ushort idx, - gdth_evt_data *evt); -static int gdth_read_event(int handle, gdth_evt_str *estr); -static void gdth_readapp_event(unchar application, gdth_evt_str *estr); +static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp); +static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, + ushort idx, gdth_evt_data *evt); +static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr); +static void gdth_readapp_event(gdth_ha_str *ha, unchar application, + gdth_evt_str *estr); static void gdth_clear_events(void); static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count); -static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp, - unchar b,ulong *flags); +static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp); static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive); static int gdth_search_eisa(ushort eisa_adr); -static int gdth_search_isa(ulong bios_adr); -static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr); +static int gdth_search_isa(ulong32 bios_adr); +static int gdth_search_pci(gdth_pci_str *pcistr); +static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt); static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha); -static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha); +static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha); static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha); static void gdth_enable_int(int hanum); @@ -150,38 +216,28 @@ static int gdth_test_busy(int hanum); static int gdth_get_cmd_index(int hanum); static void gdth_release_event(int hanum); -static int gdth_wait(int hanum,int index,ulong time); -static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1, - ulong p2,ulong p3); +static int gdth_wait(int hanum,int index,ulong32 time); +static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, + ulong32 p2,ulong32 p3); static int gdth_search_drives(int hanum); static void *gdth_mmap(ulong paddr, ulong size); static void gdth_munmap(void *addr); static const char *gdth_ctr_name(int hanum); + +static void gdth_flush(int hanum); #if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); #else +static int halt_called = FALSE; void gdth_halt(void); #endif #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; extern int sys_syslog(int,char*,int); -#define LOGEN sys_syslog(7,NULL,0); -#define WAITSEC(a) mdelay((a)*1000) - -#ifdef SLOWMOTION_GDTH -#define SLOWM WAITSEC(2) -#undef INIT_RETRIES -#undef INIT_TIMEOUT -#undef POLL_TIMEOUT -#define INIT_RETRIES 15 -#define INIT_TIMEOUT 150 -#define POLL_TIMEOUT 150 -#else -#define SLOWM -#endif +#define LOGEN sys_syslog(7,NULL,0) #ifdef __SERIAL__ #define MAX_SERBUF 160 @@ -245,14 +301,14 @@ return i; } -#define TRACE(a) {if (DebugState==1) {ser_printk a; SLOWM}} -#define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a; SLOWM}} -#define TRACE3(a) {if (DebugState!=0) {ser_printk a; SLOWM}} +#define TRACE(a) {if (DebugState==1) {ser_printk a;}} +#define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}} +#define TRACE3(a) {if (DebugState!=0) {ser_printk a;}} #else /* !__SERIAL__ */ -#define TRACE(a) {if (DebugState==1) {LOGEN;printk a; SLOWM}} -#define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a; SLOWM}} -#define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a; SLOWM}} +#define TRACE(a) {if (DebugState==1) {LOGEN;printk a;}} +#define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}} +#define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a;}} #endif #else /* !DEBUG */ @@ -262,70 +318,77 @@ #endif #ifdef GDTH_STATISTICS -static ulong max_rq=0, max_index=0, max_sg=0; -static ulong act_ints=0, act_ios=0, act_stats=0, act_rq=0; -#define GDTH_TIMER 31 /* see linux/timer.h ! */ +static ulong32 max_rq=0, max_index=0, max_sg=0; +static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0; +static struct timer_list gdth_timer; #endif #define PTR2USHORT(a) (ushort)(ulong)(a) -#define JIFFYWAIT(a) {ulong gdtjf;gdtjf=jiffies+(a);while(time_before(jiffies,gdtjf));} #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) #define INDEX_OK(i,t) ((i)hostdata)) #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext) #define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext) -#define DMADATA(a) (&((gdth_ext_str *)((a)->hostdata))->dmaext) #if LINUX_VERSION_CODE < 0x010300 static void *gdth_mmap(ulong paddr, ulong size) { if (paddr >= high_memory) - return NULL; + return NULL; else - return (void *)paddr; + return (void *)paddr; } static void gdth_munmap(void *addr) { } -inline ulong virt_to_phys(volatile void *addr) +inline ulong32 virt_to_phys(volatile void *addr) { - return (ulong)addr; + return (ulong32)addr; } -inline void *phys_to_virt(ulong addr) +inline void *phys_to_virt(ulong32 addr) { return (void *)addr; } -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define readb(addr) (*(volatile unchar *)(addr)) -#define readw(addr) (*(volatile ushort *)(addr)) -#define readl(addr) (*(volatile ulong *)(addr)) -#define writeb(b,addr) (*(volatile unchar *)(addr) = (b)) -#define writew(b,addr) (*(volatile ushort *)(addr) = (b)) -#define writel(b,addr) (*(volatile ulong *)(addr) = (b)) -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#define gdth_readb(addr) (*(volatile unchar *)(addr)) +#define gdth_readw(addr) (*(volatile ushort *)(addr)) +#define gdth_readl(addr) (*(volatile ulong32 *)(addr)) +#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b)) +#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b)) +#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b)) +#define memset_io(a,b,c) memset((void *)(a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) +#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) + +#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f) #elif LINUX_VERSION_CODE < 0x020100 static int remapped = FALSE; static void *gdth_mmap(ulong paddr, ulong size) { if ( paddr >= high_memory) { - remapped = TRUE; - return vremap(paddr, size); + remapped = TRUE; + return vremap(paddr, size); } else { - return (void *)paddr; + return (void *)paddr; } } static void gdth_munmap(void *addr) { if (remapped) - vfree(addr); + vfree(addr); remapped = FALSE; } +#define gdth_readb(addr) readb((ulong)(addr)) +#define gdth_readw(addr) readw((ulong)(addr)) +#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) +#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) +#define gdth_writew(b,addr) writew((b),(ulong)(addr)) +#define gdth_writel(b,addr) writel((b),(ulong)(addr)) + #else static void *gdth_mmap(ulong paddr, ulong size) { @@ -335,6 +398,12 @@ { return iounmap(addr); } +#define gdth_readb(addr) readb((ulong)(addr)) +#define gdth_readw(addr) readw((ulong)(addr)) +#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) +#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) +#define gdth_writew(b,addr) writew((b),(ulong)(addr)) +#define gdth_writel(b,addr) writel((b),(ulong)(addr)) #endif @@ -345,19 +414,14 @@ static int wait_index,wait_hanum; /* gdth_wait() */ static int gdth_ctr_count = 0; /* controller count */ static int gdth_ctr_vcount = 0; /* virt. ctr. count */ +static int gdth_ctr_released = 0; /* gdth_release() */ static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */ static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */ static unchar gdth_write_through = FALSE; /* write through */ -static char *gdth_ioctl_tab[4][MAXHA]; /* ioctl buffer */ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; static int eoldidx; -static struct { - Scsi_Cmnd *cmnd; /* pending request */ - ushort service; /* service */ -} gdth_cmd_tab[GDTH_MAXCMDS][MAXHA]; /* table of pend. requests */ - #define DIN 1 /* IN data direction */ #define DOU 2 /* OUT data direction */ #define DNO DIN /* no data transfer */ @@ -381,17 +445,34 @@ DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN }; -/* LILO params: gdth= - * - * Where: is any of the valid IRQs for EISA controllers (10,11,12,14) - * Sets the IRQ of the GDT3000/3020 EISA controller to this value, - * if the IRQ can not automat. detect (controller BIOS disabled) - * See gdth_init_eisa() - * - * You can use the command line gdth=0 to disable the driver - */ -static unchar irqs[MAXHA] = {0xff}; -static unchar disable_gdth_scan = FALSE; +/* __initfunc, __initdata macros */ +#if LINUX_VERSION_CODE >= 0x020126 +#include +#else +#define __initfunc(A) A +#define __initdata +#define __init +#endif + +#if LINUX_VERSION_CODE >= 0x02015F +#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) +#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) +#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) + +#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags) +#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) +#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) +#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) +#else +#define GDTH_INIT_LOCK_HA(ha) do {} while (0) +#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) +#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) + +#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) +#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) +#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) +#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) +#endif /* /proc support */ #if LINUX_VERSION_CODE >= 0x010300 @@ -411,11 +492,63 @@ }; #endif + +/* LILO and modprobe/insmod parameters */ +/* IRQ list for GDT3000/3020 EISA controllers */ +static int irq[MAXHA] __initdata = +{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; +/* disable driver flag */ +static int disable __initdata = 0; +/* reserve flag */ +static int reserve_mode __initdata = 1; +/* reserve list */ +static int reserve_list[MAX_RES_ARGS] __initdata = +{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; +/* scan order for PCI controllers */ +static int reverse_scan __initdata = 0; +/* max. IDs per channel */ +static int max_ids = MAXID; +/* rescan all IDs */ +static int rescan = 0; + +#ifdef MODULE +#if LINUX_VERSION_CODE >= 0x02011A +/* parameters for modprobe/insmod */ +MODULE_PARM(irq, "i"); +MODULE_PARM(disable, "i"); +MODULE_PARM(reserve_mode, "i"); +MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i"); +MODULE_PARM(reverse_scan, "i"); +MODULE_PARM(max_ids, "i"); +MODULE_PARM(rescan, "i"); +MODULE_AUTHOR("Achim Leubner"); +#endif +#endif + + +static void gdth_delay(int milliseconds) +{ + if (milliseconds == 0) { + udelay(1); + } else { +#if LINUX_VERSION_CODE >= 0x020168 + mdelay(milliseconds); +#else + int i; + for (i = 0; i < milliseconds; ++i) + udelay(1000); +#endif + } +} + /* controller search and initialization functions */ -static int gdth_search_eisa(ushort eisa_adr) +__initfunc (static int gdth_search_eisa(ushort eisa_adr)) { - ulong id; + ulong32 id; TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr)); id = inl(eisa_adr+ID0REG); @@ -431,99 +564,181 @@ } -static int gdth_search_isa(ulong bios_adr) +__initfunc (static int gdth_search_isa(ulong32 bios_adr)) { void *addr; - ulong id; + ulong32 id; - TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr)); - if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) { - id = readl(addr); - gdth_munmap(addr); - if (id == GDT2_ID) /* GDT2000 */ - return 1; + TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); + if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { + id = gdth_readl(addr); + gdth_munmap(addr); + if (id == GDT2_ID) /* GDT2000 */ + return 1; } return 0; } -static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr) +__initfunc (static int gdth_search_pci(gdth_pci_str *pcistr)) { + ulong32 base0, base1, base2; + ushort device_id, cnt; +#if LINUX_VERSION_CODE >= 0x2015C + struct pci_dev *pdev; +#else int error; - ulong base0,base1,base2; - - TRACE(("gdth_search_pci() device_id %d, index %d\n", - device_id,index)); - - if (!pci_present()) - return 0; - - if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index, - &pcistr->bus,&pcistr->device_fn)) - return 0; + ushort idx; +#endif + + TRACE(("gdth_search_pci()\n")); - /* 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 %d reading configuration space", error); - return -1; - } - pcistr->irq = pdev->irq; - } -#else + cnt = 0; + for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; + ++device_id) { + if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 && + device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP) + continue; +#if LINUX_VERSION_CODE >= 0x2015C + pdev = NULL; + while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) + != NULL) { + if (cnt >= MAXHA) + return cnt; + /* GDT PCI controller found, resources are already in pdev */ + pcistr[cnt].pdev = pdev; + pcistr[cnt].device_id = device_id; + pcistr[cnt].bus = pdev->bus->number; + pcistr[cnt].device_fn = pdev->devfn; + pcistr[cnt].irq = pdev->irq; + base0 = pdev->base_address[0]; + base1 = pdev->base_address[1]; + base2 = pdev->base_address[2]; + if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ + device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY) + continue; + pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; + } else { /* GDT6110, GDT6120, .. */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base2 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base1 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_IO) + continue; + pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; + } + TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n", + pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), + pcistr[cnt].irq, pcistr[cnt].dpmem)); + cnt++; + } +#else + idx = 0; + while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++, + &pcistr[cnt].bus,&pcistr[cnt].device_fn)) { + if (cnt >= MAXHA) + return cnt; + /* GDT PCI ctr. found, now read resources from config space */ #if LINUX_VERSION_CODE >= 0x010300 #define GDTH_BASEP (int *) #else #define GDTH_BASEP #endif - if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, - PCI_ROM_ADDRESS, - GDTH_BASEP&pcistr->bios)) || - (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn, - PCI_INTERRUPT_LINE,&pcistr->irq))) { - printk("GDT-PCI: error %d reading configuration space", error); - return -1; - } + if ((error = pcibios_read_config_dword(pcistr[cnt].bus, + pcistr[cnt].device_fn, + PCI_BASE_ADDRESS_0, + GDTH_BASEP&base0)) || + (error = pcibios_read_config_dword(pcistr[cnt].bus, + pcistr[cnt].device_fn, + PCI_BASE_ADDRESS_1, + GDTH_BASEP&base1)) || + (error = pcibios_read_config_dword(pcistr[cnt].bus, + pcistr[cnt].device_fn, + PCI_BASE_ADDRESS_2, + GDTH_BASEP&base2)) || + (error = pcibios_read_config_byte(pcistr[cnt].bus, + pcistr[cnt].device_fn, + PCI_INTERRUPT_LINE, + &pcistr[cnt].irq))) { + printk("GDT-PCI: error %d reading configuration space", error); + continue; + } + pcistr[cnt].device_id = device_id; + if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ + device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY) + continue; + pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; + } else { /* GDT6110, GDT6120, .. */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base2 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base1 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_IO) + continue; + pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; + } + TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n", + pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), + pcistr[cnt].irq, pcistr[cnt].dpmem)); + cnt++; + } #endif + } + return cnt; +} - pcistr->device_id = device_id; - if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */ - device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY) - return -1; - pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO) - return -1; - pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr->io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - return 1; + +__initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt)) +{ + gdth_pci_str temp; + int i, changed; + + TRACE(("gdth_sort_pci() cnt %d\n",cnt)); + if (cnt == 0) + return; + + do { + changed = FALSE; + for (i = 0; i < cnt-1; ++i) { + if (!reverse_scan) { + if ((pcistr[i].bus > pcistr[i+1].bus) || + (pcistr[i].bus == pcistr[i+1].bus && + PCI_SLOT(pcistr[i].device_fn) > + PCI_SLOT(pcistr[i+1].device_fn))) { + temp = pcistr[i]; + pcistr[i] = pcistr[i+1]; + pcistr[i+1] = temp; + changed = TRUE; + } + } else { + if ((pcistr[i].bus < pcistr[i+1].bus) || + (pcistr[i].bus == pcistr[i+1].bus && + PCI_SLOT(pcistr[i].device_fn) < + PCI_SLOT(pcistr[i+1].device_fn))) { + temp = pcistr[i]; + pcistr[i] = pcistr[i+1]; + pcistr[i+1] = temp; + changed = TRUE; + } + } + } + } while (changed); } -static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha) +__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)) { - ulong retries,id; + ulong32 retries,id; unchar prot_ver,eisacf,i,irq_found; TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr)); @@ -535,14 +750,14 @@ outb(0xff,eisa_adr+LDOORREG); retries = INIT_RETRIES; - JIFFYWAIT(2); + gdth_delay(20); while (inb(eisa_adr+EDOORREG) != 0xff) { if (--retries == 0) { printk("GDT-EISA: Initialization error (DEINIT failed)\n"); return 0; } - mdelay(1); - TRACE2(("wait for DEINIT: retries=%ld\n",retries)); + gdth_delay(1); + TRACE2(("wait for DEINIT: retries=%d\n",retries)); } prot_ver = inb(eisa_adr+MAILBOXREG); outb(0xff,eisa_adr+EDOORREG); @@ -551,7 +766,7 @@ return 0; } ha->bmic = eisa_adr; - ha->brd_phys = (ulong)eisa_adr >> 12; + ha->brd_phys = (ulong32)eisa_adr >> 12; outl(0,eisa_adr+MAILBOXREG); outl(0,eisa_adr+MAILBOXREG+4); @@ -565,76 +780,82 @@ outl(1,eisa_adr+MAILBOXREG+8); outb(0xfe,eisa_adr+LDOORREG); retries = INIT_RETRIES; - JIFFYWAIT(2); + gdth_delay(20); while (inb(eisa_adr+EDOORREG) != 0xfe) { if (--retries == 0) { printk("GDT-EISA: Initialization error (get IRQ failed)\n"); return 0; } - mdelay(1); + gdth_delay(1); } ha->irq = inb(eisa_adr+MAILBOXREG); outb(0xff,eisa_adr+EDOORREG); TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq)); - /* check the result */ - if (ha->irq == 0) { - TRACE2(("Unknown IRQ, check IRQ table from cmd line !\n")); - for (i=0,irq_found=FALSE; iirq = irqs[i]; - irqs[i] = 0; - printk("GDT-EISA: Can not detect controller IRQ,\n"); - printk("Use IRQ setting from command line (IRQ = %d)\n", - ha->irq); - } else { - printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n"); - printk("the controller BIOS or use command line parameters\n"); - return 0; - } - } + /* check the result */ + if (ha->irq == 0) { + TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n")); + for (i = 0, irq_found = FALSE; + i < MAXHA && irq[i] != 0xff; ++i) { + if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) { + irq_found = TRUE; + break; + } + } + if (irq_found) { + ha->irq = irq[i]; + irq[i] = 0; + printk("GDT-EISA: Can not detect controller IRQ,\n"); + printk("Use IRQ setting from command line (IRQ = %d)\n", + ha->irq); + } else { + printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n"); + printk("the controller BIOS or use command line parameters\n"); + return 0; + } + } } else { eisacf = inb(eisa_adr+EISAREG) & 7; if (eisacf > 4) /* level triggered */ eisacf -= 4; ha->irq = gdth_irq_tab[eisacf]; ha->type = GDT_EISA; - ha->stype= id; + ha->stype = id; } return 1; } -static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha) +__initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) { register gdt2_dpram_str *dp2_ptr; int i; unchar irq_drq,prot_ver; - ulong retries; + ulong32 retries; - TRACE(("gdth_init_isa() bios adr. %lx\n",bios_adr)); + TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr)); ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str)); if (ha->brd == NULL) { - printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); - return 0; + printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); + return 0; } dp2_ptr = (gdt2_dpram_str *)ha->brd; - writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ + gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); + if (gdth_readl(&dp2_ptr->u) != 0) { + printk("GDT-PCI: Initialization error (DPMEM write error)\n"); + gdth_munmap(ha->brd); + return 0; + } /* disable board interrupts, read DRQ and IRQ */ - writeb(0xff, &dp2_ptr->io.irqdel); - writeb(0x00, &dp2_ptr->io.irqen); - writeb(0x00, &dp2_ptr->u.ic.S_Status); - writeb(0x00, &dp2_ptr->u.ic.Cmd_Index); + gdth_writeb(0xff, &dp2_ptr->io.irqdel); + gdth_writeb(0x00, &dp2_ptr->io.irqen); + gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status); + gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index); - irq_drq = readb(&dp2_ptr->io.rq); + irq_drq = gdth_readb(&dp2_ptr->io.rq); for (i=0; i<3; ++i) { if ((irq_drq & 1)==0) break; @@ -642,7 +863,7 @@ } ha->drq = gdth_drq_tab[i]; - irq_drq = readb(&dp2_ptr->io.rq) >> 3; + irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3; for (i=1; i<5; ++i) { if ((irq_drq & 1)==0) break; @@ -651,25 +872,25 @@ ha->irq = gdth_irq_tab[i]; /* deinitialize services */ - writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]); - writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx); - writeb(0, &dp2_ptr->io.event); + gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]); + gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(0, &dp2_ptr->io.event); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) { + gdth_delay(20); + while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]); - writeb(0, &dp2_ptr->u.ic.Status); - writeb(0xff, &dp2_ptr->io.irqdel); + prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp2_ptr->u.ic.Status); + gdth_writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } @@ -679,83 +900,84 @@ ha->brd_phys = bios_adr >> 4; /* special request to controller BIOS */ - writel(0x00, &dp2_ptr->u.ic.S_Info[0]); - writel(0x00, &dp2_ptr->u.ic.S_Info[1]); - writel(0x01, &dp2_ptr->u.ic.S_Info[2]); - writel(0x00, &dp2_ptr->u.ic.S_Info[3]); - writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx); - writeb(0, &dp2_ptr->io.event); + gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]); + gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]); + gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]); + gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(0, &dp2_ptr->io.event); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { + gdth_delay(20); + while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - writeb(0, &dp2_ptr->u.ic.Status); - writeb(0xff, &dp2_ptr->io.irqdel); + gdth_writeb(0, &dp2_ptr->u.ic.Status); + gdth_writeb(0xff, &dp2_ptr->io.irqdel); return 1; } -static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) +__initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) { register gdt6_dpram_str *dp6_ptr; register gdt6c_dpram_str *dp6c_ptr; register gdt6m_dpram_str *dp6m_ptr; - ulong retries; + ulong32 retries; unchar prot_ver; + int i, found = FALSE; TRACE(("gdth_init_pci()\n")); ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8); - ha->stype = (ulong)pcistr->device_id; + ha->stype = (ulong32)pcistr->device_id; ha->irq = pcistr->irq; - if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000 or GDT6000B */ + if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str)); - if (ha->brd == NULL) { - printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - return 0; - } + ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } dp6_ptr = (gdt6_dpram_str *)ha->brd; /* reset interface area */ memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); - if (readl(&dp6_ptr->u) != 0) { + if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } /* disable board interrupts, deinit services */ - writeb(0xff, &dp6_ptr->io.irqdel); - writeb(0x00, &dp6_ptr->io.irqen);; - writeb(0x00, &dp6_ptr->u.ic.S_Status); - writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); - - writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); - writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); - writeb(0, &dp6_ptr->io.event); + gdth_writeb(0xff, &dp6_ptr->io.irqdel); + gdth_writeb(0x00, &dp6_ptr->io.irqen);; + gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status); + gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); + + gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); + gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) { + gdth_delay(20); + while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]); - writeb(0, &dp6_ptr->u.ic.S_Status); - writeb(0xff, &dp6_ptr->io.irqdel); + prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp6_ptr->u.ic.S_Status); + gdth_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } @@ -763,41 +985,41 @@ ha->ic_all_size = sizeof(dp6_ptr->u); /* special command to controller BIOS */ - writel(0x00, &dp6_ptr->u.ic.S_Info[0]); - writel(0x00, &dp6_ptr->u.ic.S_Info[1]); - writel(0x01, &dp6_ptr->u.ic.S_Info[2]); - writel(0x00, &dp6_ptr->u.ic.S_Info[3]); - writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); - writeb(0, &dp6_ptr->io.event); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); + gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); + gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { + gdth_delay(20); + while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - writeb(0, &dp6_ptr->u.ic.S_Status); - writeb(0xff, &dp6_ptr->io.irqdel); + gdth_writeb(0, &dp6_ptr->u.ic.S_Status); + gdth_writeb(0xff, &dp6_ptr->io.irqdel); - } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, GDT6120, .. */ - ha->plx = (gdt6c_plx_regs *)pcistr->io; - TRACE2(("init_pci_new() dpmem %lx io %lx irq %d\n", - pcistr->dpmem,(ulong)ha->plx,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); - if (ha->brd == NULL) { - printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - gdth_munmap(ha->brd); - return 0; - } + } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ + ha->plx = (gdt6c_plx_regs *)pcistr->io; + TRACE2(("init_pci_new() dpmem %lx irq %d\n", + pcistr->dpmem,ha->irq)); + ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + gdth_munmap(ha->brd); + return 0; + } dp6c_ptr = (gdt6c_dpram_str *)ha->brd; /* reset interface area */ memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); - if (readl(&dp6c_ptr->u) != 0) { + if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } @@ -805,29 +1027,29 @@ outb(0x00,PTR2USHORT(&ha->plx->control1)); outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); - writeb(0x00, &dp6c_ptr->u.ic.S_Status); - writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); + gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); + gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); - writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); - writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); + gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); + gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { + gdth_delay(20); + while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]); - writeb(0, &dp6c_ptr->u.ic.Status); + prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } @@ -835,68 +1057,106 @@ ha->ic_all_size = sizeof(dp6c_ptr->u); /* special command to controller BIOS */ - writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); - writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); - writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); - writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); - writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); + gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); + gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { + gdth_delay(20); + while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - writeb(0, &dp6c_ptr->u.ic.S_Status); + gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); } else { /* MPR */ - TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); - if (ha->brd == NULL) { - printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - return 0; - } + TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); + ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + /* check and reset interface area */ dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - /* reset interface area */ - memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u)); - if (readl(&dp6m_ptr->u) != 0) { - printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); - return 0; + gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) { + printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n", + (int)pcistr->dpmem); + found = FALSE; + for (i = 0xC8000; i < 0xE8000; i += 0x4000) { + gdth_munmap(ha->brd); + ha->brd = gdth_mmap(i, sizeof(ushort)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + if (gdth_readw(ha->brd) != 0xffff) { + TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); + continue; + } + gdth_munmap(ha->brd); +#if LINUX_VERSION_CODE >= 0x2015C + pci_write_config_dword(pcistr->pdev, + PCI_BASE_ADDRESS_0, i); +#else + pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, + PCI_BASE_ADDRESS_0, i); +#endif + ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) { + printk("GDT-PCI: Use free address at 0x%x\n", i); + found = TRUE; + break; + } + } + if (!found) { + printk("GDT-PCI: No free address found!\n"); + gdth_munmap(ha->brd); + return 0; + } } + memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u)); /* disable board interrupts, deinit services */ - writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, - &dp6m_ptr->i960r.edoor_en_reg); - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(0x00, &dp6m_ptr->u.ic.S_Status); - writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index); - - writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]); - writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx); - writeb(1, &dp6m_ptr->i960r.ldoor_reg); + gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, + &dp6m_ptr->i960r.edoor_en_reg); + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status); + gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index); + + gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]); + gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { + gdth_delay(20); + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]); - writeb(0, &dp6m_ptr->u.ic.S_Status); + prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } @@ -904,23 +1164,23 @@ ha->ic_all_size = sizeof(dp6m_ptr->u); /* special command to controller BIOS */ - writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); - writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); - writel(0x01, &dp6m_ptr->u.ic.S_Info[2]); - writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); - writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); - writeb(1, &dp6m_ptr->i960r.ldoor_reg); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); + gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); + gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; - JIFFYWAIT(2); - while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { + gdth_delay(20); + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + gdth_munmap(ha->brd); return 0; } - mdelay(1); + gdth_delay(1); } - writeb(0, &dp6m_ptr->u.ic.S_Status); + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); } return 1; @@ -929,7 +1189,7 @@ /* controller protocol functions */ -static void gdth_enable_int(int hanum) +__initfunc (static void gdth_enable_int(int hanum)) { gdth_ha_str *ha; ulong flags; @@ -939,9 +1199,7 @@ TRACE(("gdth_enable_int() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); - - save_flags(flags); - cli(); + GDTH_LOCK_HA(ha, flags); if (ha->type == GDT_EISA) { outb(0xff, ha->bmic + EDOORREG); @@ -949,24 +1207,24 @@ outb(0x01, ha->bmic + EINTENABREG); } else if (ha->type == GDT_ISA) { dp2_ptr = (gdt2_dpram_str *)ha->brd; - writeb(1, &dp2_ptr->io.irqdel); - writeb(0, &dp2_ptr->u.ic.Cmd_Index); - writeb(1, &dp2_ptr->io.irqen); + gdth_writeb(1, &dp2_ptr->io.irqdel); + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); + gdth_writeb(1, &dp2_ptr->io.irqen); } else if (ha->type == GDT_PCI) { dp6_ptr = (gdt6_dpram_str *)ha->brd; - writeb(1, &dp6_ptr->io.irqdel); - writeb(0, &dp6_ptr->u.ic.Cmd_Index); - writeb(1, &dp6_ptr->io.irqen); + gdth_writeb(1, &dp6_ptr->io.irqdel); + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); + gdth_writeb(1, &dp6_ptr->io.irqen); } else if (ha->type == GDT_PCINEW) { outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x03, PTR2USHORT(&ha->plx->control1)); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, - &dp6m_ptr->i960r.edoor_en_reg); + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, + &dp6m_ptr->i960r.edoor_en_reg); } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } @@ -976,7 +1234,7 @@ int i; TRACE(("gdth_get_status() irq %d ctr_count %d\n", - irq,gdth_ctr_count)); + irq,gdth_ctr_count)); *pIStatus = 0; for (i=0; itype == GDT_EISA) *pIStatus = inb((ushort)ha->bmic + EDOORREG); else if (ha->type == GDT_ISA) - *pIStatus = readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index); + *pIStatus = + gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCI) - *pIStatus = readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index); + *pIStatus = + gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCINEW) *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); else if (ha->type == GDT_PCIMPR) - *pIStatus = readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg); + *pIStatus = + gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg); if (*pIStatus) return i; /* board found */ @@ -1012,13 +1273,14 @@ if (ha->type == GDT_EISA) gdtsema0 = (int)inb(ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) - gdtsema0 = (int)readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) - gdtsema0 = (int)readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCINEW) gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg)); else if (ha->type == GDT_PCIMPR) - gdtsema0 = (int)readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + gdtsema0 = + (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); return (gdtsema0 & 1); } @@ -1033,10 +1295,10 @@ ha = HADATA(gdth_ctr_tab[hanum]); for (i=0; ipccb->RequestBuffer; - gdth_cmd_tab[i][hanum].service = ha->pccb->Service; - ha->pccb->CommandIndex = (ulong)i+2; + if (ha->cmd_tab[i].cmnd == UNUSED_CMND) { + ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer; + ha->cmd_tab[i].service = ha->pccb->Service; + ha->pccb->CommandIndex = (ulong32)i+2; return (i+2); } } @@ -1051,17 +1313,17 @@ TRACE(("gdth_set_sema0() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->type == GDT_EISA) + if (ha->type == GDT_EISA) { outb(1, ha->bmic + SEMA0REG); - else if (ha->type == GDT_ISA) - writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); - else if (ha->type == GDT_PCI) - writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); - else if (ha->type == GDT_PCINEW) + } else if (ha->type == GDT_ISA) { + gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + } else if (ha->type == GDT_PCI) { + gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->sema0_reg)); - else if (ha->type == GDT_PCIMPR) - writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); - + } else if (ha->type == GDT_PCIMPR) { + gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + } } @@ -1096,31 +1358,31 @@ /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { dp2_ptr = (gdt2_dpram_str *)ha->brd; - writew(dp_offset + DPMEM_COMMAND_OFFSET, - &dp2_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, - &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); - memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + &dp2_ptr->u.ic.comm_queue[cmd_no].offset); + gdth_writew((ushort)cmd_ptr->Service, + &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); + memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCI) { dp6_ptr = (gdt6_dpram_str *)ha->brd; - writew(dp_offset + DPMEM_COMMAND_OFFSET, - &dp6_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, - &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + &dp6_ptr->u.ic.comm_queue[cmd_no].offset); + gdth_writew((ushort)cmd_ptr->Service, + &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCINEW) { dp6c_ptr = (gdt6c_dpram_str *)ha->brd; - writew(dp_offset + DPMEM_COMMAND_OFFSET, - &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, - &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); - memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); + gdth_writew((ushort)cmd_ptr->Service, + &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); + memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - writew(dp_offset + DPMEM_COMMAND_OFFSET, - &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, - &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id); + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); + gdth_writew((ushort)cmd_ptr->Service, + &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } } @@ -1130,21 +1392,23 @@ { register gdth_ha_str *ha; + TRACE(("gdth_release_event() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); + #ifdef GDTH_STATISTICS - ulong i,j; - for (i=0,j=0; jcmd_tab[j].cmnd != UNUSED_CMND) + ++i; + } + if (max_index < i) { + max_index = i; + TRACE3(("GDT: max_index = %d\n",(ushort)i)); + } } #endif - TRACE(("gdth_release_event() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->pccb->OpCode == GDT_INIT) ha->pccb->Service |= 0x80; @@ -1152,23 +1416,24 @@ outb(ha->pccb->Service, ha->bmic + LDOORREG); if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */ outl((ulong)ha->pccb, ha->bmic + MAILBOXREG); - } else if (ha->type == GDT_ISA) - writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); - else if (ha->type == GDT_PCI) - writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event); - else if (ha->type == GDT_PCINEW) + } else if (ha->type == GDT_ISA) { + gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); + } else if (ha->type == GDT_PCI) { + gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event); + } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->ldoor_reg)); - else if (ha->type == GDT_PCIMPR) - writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg); + } else if (ha->type == GDT_PCIMPR) { + gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg); + } } -static int gdth_wait(int hanum,int index,ulong time) +static int gdth_wait(int hanum,int index,ulong32 time) { gdth_ha_str *ha; int answer_found = FALSE; - TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time)); + TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time)); ha = HADATA(gdth_ctr_tab[hanum]); if (index == 0) @@ -1177,7 +1442,7 @@ gdth_from_wait = TRUE; do { #if LINUX_VERSION_CODE >= 0x010346 - gdth_interrupt((int)ha->irq,NULL,NULL); + gdth_interrupt((int)ha->irq,ha,NULL); #else gdth_interrupt((int)ha->irq,NULL); #endif @@ -1185,19 +1450,19 @@ answer_found = TRUE; break; } - mdelay(1); + gdth_delay(1); } while (--time); gdth_from_wait = FALSE; while (gdth_test_busy(hanum)) - udelay(1); + gdth_delay(0); return (answer_found); } -static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1, - ulong p2,ulong p3) +static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, + ulong32 p2,ulong32 p3) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; @@ -1234,21 +1499,21 @@ cmd_ptr->u.raw.direction = p1; cmd_ptr->u.raw.bus = (unchar)p2; cmd_ptr->u.raw.target = (unchar)p3; - cmd_ptr->u.raw.lun = 0; + cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); } ha->cmd_len = sizeof(gdth_cmd_str); ha->cmd_offs_dpmem = 0; ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); - JIFFYWAIT(2); + gdth_delay(20); if (!gdth_wait(hanum,index,INIT_TIMEOUT)) { printk("GDT: Initialization error (timeout service %d)\n",service); return 0; } if (ha->status != S_BSY || --retries == 0) break; - mdelay(1); + gdth_delay(1); } return (ha->status != S_OK ? 0:1); @@ -1257,14 +1522,14 @@ /* search for devices */ -static int gdth_search_drives(int hanum) +__initfunc (static int gdth_search_drives(int hanum)) { register gdth_ha_str *ha; - ushort cdev_cnt,i; - unchar b,t,pos_found; - ulong drv_cyls, drv_hds, drv_secs; - ulong bus_no; + ushort cdev_cnt, i; + ulong32 drv_cyls, drv_hds, drv_secs; + ulong32 bus_no; gdth_getch_str *chn; + gdth_iochan_str *ioc; TRACE(("gdth_search_drives() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); @@ -1292,45 +1557,76 @@ /* initialize cache service after mountall */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); - return 0; + printk("GDT: Initialization error cache service (code %d)\n", + ha->status); + return 0; } TRACE2(("gdth_search_drives() CACHES. init. after mountall\n")); cdev_cnt = (ushort)ha->info; - /* detect number of SCSI buses */ - chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]); - for (bus_no=0; bus_nochannel_no = bus_no; - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, - SCSI_CHAN_CNT | L_CTRL_PATTERN, - IO_CHANNEL | INVALID_CHANNEL, - sizeof(gdth_getch_str))) { - if (bus_no == 0) { - printk("GDT: Error detecting SCSI channel count (0x%x)\n", - ha->status); - return 0; - } - break; - } - if (chn->siop_id < MAXID) - ha->id[bus_no][chn->siop_id].type = SIOP_DTYP; - } - ha->bus_cnt = (unchar)bus_no; - TRACE2(("gdth_search_drives() %d SCSI channels\n",ha->bus_cnt)); + /* detect number of buses - try new IOCTL */ + ioc = (gdth_iochan_str *)ha->pscratch; + ioc->version = 0xffffffff; + ioc->list_entries = MAXBUS; + ioc->first_chan = 0; + ioc->last_chan = MAXBUS-1; + ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]); + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC, + INVALID_CHANNEL,sizeof(gdth_iochan_str))) { + TRACE2(("GET_IOCHAN_DESC supported!\n")); + ha->bus_cnt = ioc->chan_count; + for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { + if (ioc->list[bus_no].proc_id < MAXID) + ha->bus_id[bus_no] = ioc->list[bus_no].proc_id; + else + ha->bus_id[bus_no] = 0xff; + } + } else { + /* old method */ + chn = (gdth_getch_str *)ha->pscratch; + for (bus_no = 0; bus_no < MAXBUS; ++bus_no) { + chn->channel_no = bus_no; + if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + SCSI_CHAN_CNT | L_CTRL_PATTERN, + IO_CHANNEL | INVALID_CHANNEL, + sizeof(gdth_getch_str))) { + if (bus_no == 0) { + printk("GDT: Error detecting channel count (0x%x)\n", + ha->status); + return 0; + } + break; + } + if (chn->siop_id < MAXID) + ha->bus_id[bus_no] = chn->siop_id; + else + ha->bus_id[bus_no] = 0xff; + } + ha->bus_cnt = (unchar)bus_no; + } + TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt)); /* read cache configuration */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, - INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); - return 0; - } - ha->cpar = ((gdth_cinfo_str *)DMADATA(gdth_ctr_tab[hanum]))->cpar; - TRACE2(("gdth_search_drives() cinfo: vs %lx sta %d str %d dw %d b %d\n", - ha->cpar.version,ha->cpar.state,ha->cpar.strategy, - ha->cpar.write_back,ha->cpar.block_size)); + INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { + printk("GDT: Initialization error cache service (code %d)\n", + ha->status); + return 0; + } + ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; + TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n", + ha->cpar.version,ha->cpar.state,ha->cpar.strategy, + ha->cpar.write_back,ha->cpar.block_size)); + + /* read board info, fill ctr_name[] */ + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO, + INVALID_CHANNEL,sizeof(gdth_binfo_str))) { + TRACE2(("BOARD_INFO supported!\n")); + strcpy(ha->ctr_name, ((gdth_binfo_str *)ha->pscratch)->type_string); + } else { + strcpy(ha->ctr_name, gdth_ctr_name(hanum)); + } + TRACE2(("Controller name: %s\n",ha->ctr_name)); /* initialize raw service */ if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) { @@ -1345,10 +1641,9 @@ if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER, 0,0)) { TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n")); - if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) - { - TRACE2(("gdth_search_dr(): get feat RAWSERVICE %ld\n", - ha->info)); + if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { + TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", + ha->info)); ha->raw_feat = (ushort)ha->info; } } @@ -1358,20 +1653,31 @@ SCATTER_GATHER,0)) { TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n")); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { - TRACE2(("gdth_search_dr(): get feat CACHESERV. %ld\n", - ha->info)); + TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", + ha->info)); ha->cache_feat = (ushort)ha->info; } } - /* scanning for raw devices */ - for (b=0; bbus_cnt; ++b) { - for (t=0; tid[b][t].type != SIOP_DTYP && - gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) { - ha->id[b][t].type = RAW_DTYP; - } + /* reserve drives for raw service */ + if (reserve_mode != 0) { + gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL, + reserve_mode == 1 ? 1 : 3, 0, 0); + TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", + ha->status)); + } + for (i = 0; i < MAX_RES_ARGS; i += 4) { + if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt && + reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) { + TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n", + reserve_list[i], reserve_list[i+1], + reserve_list[i+2], reserve_list[i+3])); + if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, + reserve_list[i+1], reserve_list[i+2] | + (reserve_list[i+3] << 8))) { + printk("GDT: Error raw service (RESERVE, code %d)\n", + ha->status); + } } } @@ -1379,63 +1685,49 @@ for (i=0; ibus_cnt; ++b) { - for (t=0; tid[b][t].type == EMPTY_DTYP) { - pos_found = TRUE; - break; - } - } - if (pos_found) - break; - } - TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n", - i,b,t)); + /* static relation between host drive number and Bus/ID */ + TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n", + i,ha->bus_cnt,i)); - ha->id[b][t].type = CACHE_DTYP; - ha->id[b][t].devtype = 0; - ha->id[b][t].size = ha->info; - ha->id[b][t].hostdrive = i; + ha->hdr[i].present = TRUE; + ha->hdr[i].size = ha->info; /* evaluate mapping (sectors per head, heads per cylinder) */ - ha->id[b][t].size &= ~SECS32; - if (ha->info2 == 0) { - drv_cyls = ha->id[b][t].size /HEADS/SECS; - if (drv_cyls <= MAXCYLS) { - drv_hds = HEADS; - drv_secs= SECS; - } else { /* too high for 64*32 */ - drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS; - if (drv_cyls <= MAXCYLS) { - drv_hds = MEDHEADS; - drv_secs= MEDSECS; - } else { /* too high for 127*63 */ - drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS; - drv_hds = BIGHEADS; - drv_secs= BIGSECS; - } - } + ha->hdr[i].size &= ~SECS32; + if (ha->info2 == 0) { + drv_cyls = ha->hdr[i].size /HEADS/SECS; + if (drv_cyls <= MAXCYLS) { + drv_hds = HEADS; + drv_secs= SECS; + } else { /* too high for 64*32 */ + drv_cyls = ha->hdr[i].size /MEDHEADS/MEDSECS; + if (drv_cyls <= MAXCYLS) { + drv_hds = MEDHEADS; + drv_secs= MEDSECS; + } else { /* too high for 127*63 */ + drv_cyls = ha->hdr[i].size /BIGHEADS/BIGSECS; + drv_hds = BIGHEADS; + drv_secs= BIGSECS; + } + } } else { - drv_hds = ha->info2 & 0xff; - drv_secs = (ha->info2 >> 8) & 0xff; - drv_cyls = ha->id[b][t].size /drv_hds/drv_secs; - } - ha->id[b][t].heads = (unchar)drv_hds; - ha->id[b][t].secs = (unchar)drv_secs; + drv_hds = ha->info2 & 0xff; + drv_secs = (ha->info2 >> 8) & 0xff; + drv_cyls = ha->hdr[i].size /drv_hds/drv_secs; + } + ha->hdr[i].heads = (unchar)drv_hds; + ha->hdr[i].secs = (unchar)drv_secs; /* round size */ - ha->id[b][t].size = drv_cyls * drv_hds * drv_secs; - TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n", - i,ha->id[b][t].size,drv_hds,drv_secs)); + ha->hdr[i].size = drv_cyls * drv_hds * drv_secs; + TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n", + i,ha->hdr[i].size,drv_hds,drv_secs)); /* get informations about device */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i, 0,0)) { - TRACE(("gdth_search_dr() cache drive %d devtype %ld\n", + TRACE(("gdth_search_dr() cache drive %d devtype %d\n", i,ha->info)); - ha->id[b][t].devtype = (ushort)ha->info; + ha->hdr[i].devtype = (ushort)ha->info; } } } @@ -1456,12 +1748,11 @@ unchar b, t; TRACE(("gdth_putq() priority %d\n",priority)); - save_flags(flags); - cli(); - ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); + scp->SCp.this_residual = (int)priority; - gdth_update_timeout(scp, scp->timeout * 6); + gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); #if LINUX_VERSION_CODE >= 0x020000 b = scp->channel; #else @@ -1469,9 +1760,12 @@ #endif t = scp->target; #if LINUX_VERSION_CODE >= 0x010300 - if (priority >= DEFAULT_PRI && ha->id[b][t].lock) { - TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(scp, 0); + if (priority >= DEFAULT_PRI) { + if ((b < ha->bus_cnt && ha->raw[b].lock) || + (b == ha->bus_cnt && ha->hdr[t].lock)) { + TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } #endif @@ -1489,7 +1783,7 @@ pscp->SCp.ptr = (char *)scp; scp->SCp.ptr = (char *)nscp; } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); #ifdef GDTH_STATISTICS flags = 0; @@ -1507,18 +1801,18 @@ register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; - unchar b, t, next_cmd, firsttime; - ushort hdrive; + unchar b, t, firsttime; + unchar this_cmd, next_cmd; ulong flags; int cmd_index; TRACE(("gdth_next() hanum %d\n",hanum)); - save_flags(flags); - cli(); - ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); + ha->cmd_cnt = ha->cmd_offs_dpmem = 0; - next_cmd = firsttime = TRUE; + this_cmd = firsttime = TRUE; + next_cmd = gdth_polling ? FALSE:TRUE; cmd_index = 0; for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { @@ -1530,105 +1824,173 @@ b = NUMDATA(nscp->host)->busnum; #endif t = nscp->target; - if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) { + if (nscp->SCp.this_residual >= DEFAULT_PRI) { + if ((b < ha->bus_cnt && ha->raw[b].lock) || + (b == ha->bus_cnt && ha->hdr[t].lock)) + continue; + } - if (firsttime) { - if (gdth_test_busy(hanum)) { /* controller busy ? */ - TRACE(("gdth_next() controller %d busy !\n",hanum)); - if (!gdth_polling) { - restore_flags(flags); - return; + if (firsttime) { + if (gdth_test_busy(hanum)) { /* controller busy ? */ + TRACE(("gdth_next() controller %d busy !\n",hanum)); + if (!gdth_polling) { + GDTH_UNLOCK_HA(ha, flags); + return; + } + while (gdth_test_busy(hanum)) + gdth_delay(1); + } + firsttime = FALSE; + } + + if (nscp->SCp.phase == -1) { + nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */ + if (nscp->cmnd[0] == TEST_UNIT_READY) { + TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", + nscp->channel, nscp->target, nscp->lun)); + /* TEST_UNIT_READY -> set scan mode */ + if ((ha->scan_mode & 0x0f) == 0) { + if (nscp->channel == 0 && nscp->target == 0 && + nscp->lun == 0) { + ha->scan_mode |= 1; + TRACE2(("Scan mode: 0x%x\n", ha->scan_mode)); + } + } else if ((ha->scan_mode & 0x0f) == 1) { + if (nscp->channel == 0 && + ((nscp->target == 0 && nscp->lun == 1) || + (nscp->target == 1 && nscp->lun == 0))) { + nscp->SCp.Status = GDT_SCAN_START; + nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8); + ha->scan_mode = 0x12; + TRACE2(("Scan mode: 0x%x (SCAN_START)\n", + ha->scan_mode)); + } else { + ha->scan_mode &= 0x10; + TRACE2(("Scan mode: 0x%x\n", ha->scan_mode)); + } + } else if (ha->scan_mode == 0x12) { + if (b == ha->bus_cnt) { + nscp->SCp.Status = GDT_SCAN_END; + ha->scan_mode &= 0x10; + TRACE2(("Scan mode: 0x%x (SCAN_END)\n", + ha->scan_mode)); } - while (gdth_test_busy(hanum)) - mdelay(1); } - firsttime = FALSE; } + } + + if (nscp->SCp.Status != -1) { + if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) { + cmd_index=gdth_fill_raw_cmd(hanum,nscp,b); + next_cmd = FALSE; + } + } else #if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done == gdth_scsi_done) { - if (!(cmd_index=gdth_special_cmd(hanum,nscp,b))) - next_cmd = FALSE; - } else -#endif - if (ha->id[b][t].type != CACHE_DTYP) { - if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) - next_cmd = FALSE; - } else { - hdrive = ha->id[b][t].hostdrive; - switch (nscp->cmnd[0]) { - case TEST_UNIT_READY: - case INQUIRY: - case REQUEST_SENSE: - case READ_CAPACITY: - case VERIFY: - case START_STOP: - case MODE_SENSE: - TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], - nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], - nscp->cmnd[4],nscp->cmnd[5])); - gdth_internal_cache_cmd(hanum,nscp,b,&flags); - break; + if (nscp->done == gdth_scsi_done) { + if (!(cmd_index=gdth_special_cmd(hanum,nscp))) + this_cmd = FALSE; + next_cmd = FALSE; + } else +#endif + if (b < ha->bus_cnt) { + if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) { + this_cmd = FALSE; + } + } else if (!ha->hdr[nscp->target].present || nscp->lun != 0) { + TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n", + nscp->cmnd[0], b, nscp->target, nscp->lun)); + nscp->result = DID_BAD_TARGET << 16; + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); + } else { + switch (nscp->cmnd[0]) { + case TEST_UNIT_READY: + case INQUIRY: + case REQUEST_SENSE: + case READ_CAPACITY: + case VERIFY: + case START_STOP: + case MODE_SENSE: + TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], + nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], + nscp->cmnd[4],nscp->cmnd[5])); + if (gdth_internal_cache_cmd(hanum,nscp)) { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); + } + break; - case ALLOW_MEDIUM_REMOVAL: - TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], - nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], - nscp->cmnd[4],nscp->cmnd[5])); - if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) { - TRACE2(("Prevent r. nonremov. drive->do nothing\n")); - nscp->result = DID_OK << 16; - restore_flags( flags ); + case ALLOW_MEDIUM_REMOVAL: + TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], + nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], + nscp->cmnd[4],nscp->cmnd[5])); + if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) { + TRACE(("Prevent r. nonremov. drive->do nothing\n")); + nscp->result = DID_OK << 16; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; + else { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ nscp->scsi_done(nscp); - save_flags( flags ); - cli(); - } else { - nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0; - TRACE2(("Prevent/allow r. %d rem. drive %d\n", - nscp->cmnd[4],nscp->cmnd[3])); - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive))) - next_cmd = FALSE; + GDTH_LOCK_HA(ha,flags); } - break; - - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive))) - next_cmd = FALSE; - break; + } else { + nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0; + TRACE(("Prevent/allow r. %d rem. drive %d\n", + nscp->cmnd[4],nscp->cmnd[3])); + if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + this_cmd = FALSE; + } + break; + + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + this_cmd = FALSE; + break; - default: - TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], + default: + TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); - printk("GDT: Unknown SCSI command 0x%x to cache service !\n", + printk("GDT: Unknown SCSI command 0x%x to cache service !\n", nscp->cmnd[0]); - nscp->result = DID_ABORT << 16; - restore_flags( flags ); - nscp->scsi_done( nscp ); - save_flags( flags ); - cli(); - break; + nscp->result = DID_ABORT << 16; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; + else { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); } - } - - if (!next_cmd) - break; - if (nscp == ha->req_first) - ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr; - else - pscp->SCp.ptr = nscp->SCp.ptr; - if (gdth_polling) break; + } } + + if (!this_cmd) + break; + if (nscp == ha->req_first) + ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr; + else + pscp->SCp.ptr = nscp->SCp.ptr; + if (!next_cmd) + break; } if (ha->cmd_cnt > 0) { gdth_release_event(hanum); } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) @@ -1664,11 +2026,9 @@ } } -static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp, - unchar b,ulong *flags) +static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) { register gdth_ha_str *ha; - ushort hdrive; unchar t; gdth_inq_data inq; gdth_rdcap_data rdc; @@ -1677,77 +2037,73 @@ ha = HADATA(gdth_ctr_tab[hanum]); t = scp->target; - hdrive = ha->id[b][t].hostdrive; TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", - scp->cmnd[0],hdrive)); - - if (scp->lun !=0) - scp->result = DID_BAD_TARGET << 16; - else { - switch (scp->cmnd[0]) { - case TEST_UNIT_READY: - case VERIFY: - case START_STOP: - TRACE2(("Test/Verify/Start hdrive %d\n",hdrive)); - break; - - case INQUIRY: - TRACE2(("Inquiry hdrive %d devtype %d\n", - hdrive,ha->id[b][t].devtype)); - inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK; - /* you can here set all disks to removable, if you want to do - a flush using the ALLOW_MEDIUM_REMOVAL command */ - inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00; - inq.version = 2; - inq.resp_aenc = 2; - inq.add_length= 32; - strcpy(inq.vendor,"ICP "); - sprintf(inq.product,"Host Drive #%02d",hdrive); - strcpy(inq.revision," "); - gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); - break; - - case REQUEST_SENSE: - TRACE2(("Request sense hdrive %d\n",hdrive)); - sd.errorcode = 0x70; - sd.segno = 0x00; - sd.key = NO_SENSE; - sd.info = 0; - sd.add_length= 0; - gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); - break; - - case MODE_SENSE: - TRACE2(("Mode sense hdrive %d\n",hdrive)); - memset((char*)&mpd,0,sizeof(gdth_modep_data)); - mpd.hd.data_length = sizeof(gdth_modep_data); - mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0; - mpd.hd.bd_length = sizeof(mpd.bd); - mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; - mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; - mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); - gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); - break; - - case READ_CAPACITY: - TRACE2(("Read capacity hdrive %d\n",hdrive)); - rdc.last_block_no = ntohl(ha->id[b][t].size-1); - rdc.block_length = ntohl(SECTOR_SIZE); - gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data)); - break; + scp->cmnd[0],t)); - default: - TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); - break; - } - scp->result = DID_OK << 16; + switch (scp->cmnd[0]) { + case TEST_UNIT_READY: + case VERIFY: + case START_STOP: + TRACE2(("Test/Verify/Start hdrive %d\n",t)); + break; + + case INQUIRY: + TRACE2(("Inquiry hdrive %d devtype %d\n", + t,ha->hdr[t].devtype)); + inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK; + /* you can here set all disks to removable, if you want to do + a flush using the ALLOW_MEDIUM_REMOVAL command */ + inq.modif_rmb = ha->hdr[t].devtype&1 ? 0x80:0x00; + inq.version = 2; + inq.resp_aenc = 2; + inq.add_length= 32; + strcpy(inq.vendor,"ICP "); + sprintf(inq.product,"Host Drive #%02d",t); + strcpy(inq.revision," "); + gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); + break; + + case REQUEST_SENSE: + TRACE2(("Request sense hdrive %d\n",t)); + sd.errorcode = 0x70; + sd.segno = 0x00; + sd.key = NO_SENSE; + sd.info = 0; + sd.add_length= 0; + gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); + break; + + case MODE_SENSE: + TRACE2(("Mode sense hdrive %d\n",t)); + memset((char*)&mpd,0,sizeof(gdth_modep_data)); + mpd.hd.data_length = sizeof(gdth_modep_data); + mpd.hd.dev_par = (ha->hdr[t].devtype&2) ? 0x80:0; + mpd.hd.bd_length = sizeof(mpd.bd); + mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; + mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; + mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); + gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); + break; + + case READ_CAPACITY: + TRACE2(("Read capacity hdrive %d\n",t)); + rdc.last_block_no = ntohl(ha->hdr[t].size-1); + rdc.block_length = ntohl(SECTOR_SIZE); + gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data)); + break; + + default: + TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); + break; } + scp->result = DID_OK << 16; - restore_flags(*flags); - scp->scsi_done(scp); - save_flags(*flags); - cli(); - return 1; + if (!scp->SCp.have_data_in) + scp->SCp.have_data_in++; + else + return 1; + + return 0; } static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) @@ -1804,25 +2160,26 @@ cmdp->u.cache.sg_canz = 0; } else { if (scp->cmd_len != 6) { - cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]); - cmdp->u.cache.BlockCnt= (ulong)ntohs(*(ushort*)&scp->cmnd[7]); + cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]); + cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]); } else { - cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[0]) & 0x001fffffUL; + cmdp->u.cache.BlockNo = + ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL; cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; } if (scp->use_sg) { - cmdp->u.cache.DestAddr= -1UL; + cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; for (i=0; iuse_sg; ++i,++sl) { cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.cache.sg_lst[i].sg_len = (ulong)sl->length; + cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; } - cmdp->u.cache.sg_canz = (ulong)i; + cmdp->u.cache.sg_canz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong)i) { - max_sg = (ulong)i; + if (max_sg < (ulong32)i) { + max_sg = (ulong32)i; TRACE3(("GDT: max_sg = %d\n",i)); } #endif @@ -1830,9 +2187,10 @@ cmdp->u.cache.sg_lst[i].sg_len = 0; } else { if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache.DestAddr = -1UL; + cmdp->u.cache.DestAddr = 0xffffffff; cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer); + cmdp->u.cache.sg_lst[0].sg_ptr = + virt_to_bus(scp->request_buffer); cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; cmdp->u.cache.sg_lst[1].sg_len = 0; } else { @@ -1841,12 +2199,12 @@ } } } - TRACE(("cache cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n", - cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, - cmdp->u.cache.sg_lst[0].sg_ptr, - cmdp->u.cache.sg_lst[0].sg_len)); - TRACE(("cache cmd: cmd %d blockno. %ld, blockcnt %ld\n", - cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, + cmdp->u.cache.sg_lst[0].sg_ptr, + cmdp->u.cache.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); /* evaluate command size, check space */ ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + @@ -1858,7 +2216,7 @@ if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) > ha->ic_all_size) { TRACE2(("gdth_fill_cache() DPMEM overflow\n")); - gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND; + ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND; return 0; } } @@ -1882,7 +2240,7 @@ l = scp->lun; cmdp = ha->pccb; TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n", - scp->cmnd[0],b,t,l)); + scp->cmnd[0],b,t,l)); if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; @@ -1899,61 +2257,73 @@ gdth_set_sema0(hanum); /* fill command */ - cmdp->OpCode = GDT_WRITE; /* always */ - cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.reserved = 0; - cmdp->u.raw.mdisc_time = 0; - cmdp->u.raw.mcon_time = 0; - cmdp->u.raw.clen = scp->cmd_len; - cmdp->u.raw.target = t; - cmdp->u.raw.lun = l; - cmdp->u.raw.bus = b; - cmdp->u.raw.priority = 0; - cmdp->u.raw.link_p = NULL; - cmdp->u.raw.sdlen = scp->request_bufflen; - cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer); - cmdp->u.raw.direction = - gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN; - memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + if (scp->SCp.Status != -1) { + cmdp->OpCode = scp->SCp.Status; /* special raw cmd. */ + cmdp->BoardNode = LOCALBOARD; + cmdp->u.raw.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw.direction)); - if (scp->use_sg) { - cmdp->u.raw.sdata = -1UL; - sl = (struct scatterlist *)scp->request_buffer; - for (i=0; iuse_sg; ++i,++sl) { - cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.raw.sg_lst[i].sg_len = (ulong)sl->length; - } - cmdp->u.raw.sg_ranz = (ulong)i; + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); + } else { + cmdp->OpCode = GDT_WRITE; /* always */ + cmdp->BoardNode = LOCALBOARD; + cmdp->u.raw.reserved = 0; + cmdp->u.raw.mdisc_time = 0; + cmdp->u.raw.mcon_time = 0; + cmdp->u.raw.clen = scp->cmd_len; + cmdp->u.raw.target = t; + cmdp->u.raw.lun = l; + cmdp->u.raw.bus = b; + cmdp->u.raw.priority = 0; + cmdp->u.raw.link_p = NULL; + cmdp->u.raw.sdlen = scp->request_bufflen; + cmdp->u.raw.sense_len = 16; + cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer); + cmdp->u.raw.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN; + memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + + if (scp->use_sg) { + cmdp->u.raw.sdata = 0xffffffff; + sl = (struct scatterlist *)scp->request_buffer; + for (i=0; iuse_sg; ++i,++sl) { + cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + } + cmdp->u.raw.sg_ranz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong)i) { - max_sg = (ulong)i; - TRACE3(("GDT: max_sg = %d\n",i)); - } + if (max_sg < (ulong32)i) { + max_sg = (ulong32)i; + TRACE3(("GDT: max_sg = %d\n",i)); + } #endif - if (iu.raw.sg_lst[i].sg_len = 0; - } else { - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw.sdata = -1UL; - cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer); - cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw.sg_lst[1].sg_len = 0; + if (iu.raw.sg_lst[i].sg_len = 0; } else { - cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer); - cmdp->u.raw.sg_ranz= 0; + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz= 1; + cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sg_ranz= 0; + } } - } - TRACE(("raw cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n", - cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, - cmdp->u.raw.sg_lst[0].sg_ptr, - cmdp->u.raw.sg_lst[0].sg_len)); + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, + cmdp->u.raw.sg_lst[0].sg_ptr, + cmdp->u.raw.sg_lst[0].sg_len)); - /* evaluate command size, check space */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + - (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + + (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + } + /* check space */ if (ha->cmd_len & 3) ha->cmd_len += (4 - (ha->cmd_len & 3)); @@ -1961,7 +2331,7 @@ if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) > ha->ic_all_size) { TRACE2(("gdth_fill_raw() DPMEM overflow\n")); - gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND; + ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND; return 0; } } @@ -1971,7 +2341,7 @@ return cmd_index; } -static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b) +static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp) { register gdth_ha_str *ha; register gdth_cmd_str *cmdp; @@ -2000,13 +2370,16 @@ /* evaluate command size, check space */ if (cmdp->OpCode == GDT_IOCTL) { TRACE2(("IOCTL\n")); - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong); + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32); } else if (cmdp->Service == CACHESERVICE) { TRACE2(("cache command %d\n",cmdp->OpCode)); - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); } else if (cmdp->Service == SCSIRAWSERVICE) { TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0])); - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); } if (ha->cmd_len & 3) @@ -2016,7 +2389,7 @@ if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) > ha->ic_all_size) { TRACE2(("gdth_special_cmd() DPMEM overflow\n")); - gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND; + ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND; return 0; } } @@ -2028,8 +2401,8 @@ /* Controller event handling functions */ -static gdth_evt_str *gdth_store_event(ushort source, ushort idx, - gdth_evt_data *evt) +static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, + ushort idx, gdth_evt_data *evt) { gdth_evt_str *e; ulong flags; @@ -2039,8 +2412,7 @@ if (source == 0) /* no source -> no event */ return 0; - save_flags(flags); - cli(); + GDTH_LOCK_HA(ha, flags); if (ebuffer[elastidx].event_source == source && ebuffer[elastidx].event_idx == idx && !memcmp((char *)&ebuffer[elastidx].event_data.eu, @@ -2068,19 +2440,18 @@ e->same_count = 1; e->event_data = *evt; } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); return e; } -static int gdth_read_event(int handle, gdth_evt_str *estr) +static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr) { gdth_evt_str *e; int eindex; ulong flags; TRACE2(("gdth_read_event() handle %d\n", handle)); - save_flags(flags); - cli(); + GDTH_LOCK_HA(ha, flags); if (handle == -1) eindex = eoldidx; else @@ -2088,7 +2459,7 @@ estr->event_source = 0; if (eindex >= MAX_EVENTS) { - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); return eindex; } e = &ebuffer[eindex]; @@ -2101,11 +2472,12 @@ } memcpy(estr, e, sizeof(gdth_evt_str)); } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); return eindex; } -static void gdth_readapp_event(unchar application, gdth_evt_str *estr) +static void gdth_readapp_event(gdth_ha_str *ha, + unchar application, gdth_evt_str *estr) { gdth_evt_str *e; int eindex; @@ -2113,8 +2485,7 @@ unchar found = FALSE; TRACE2(("gdth_readapp_event() app. %d\n", application)); - save_flags(flags); - cli(); + GDTH_LOCK_HA(ha, flags); eindex = eoldidx; for (;;) { e = &ebuffer[eindex]; @@ -2134,35 +2505,21 @@ memcpy(estr, e, sizeof(gdth_evt_str)); else estr->event_source = 0; - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } static void gdth_clear_events() { - ulong flags; - TRACE(("gdth_clear_events()")); - save_flags(flags); - cli(); eoldidx = elastidx = 0; ebuffer[0].event_source = 0; - restore_flags(flags); } /* SCSI interface functions */ #if LINUX_VERSION_CODE >= 0x010346 -static void do_gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - gdth_interrupt(irq, dev_id, regs); - spin_unlock_irqrestore(&io_request_lock, flags); -} - static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) #else static void gdth_interrupt(int irq,struct pt_regs *regs) @@ -2173,11 +2530,12 @@ gdt6_dpram_str *dp6_ptr; gdt2_dpram_str *dp2_ptr; Scsi_Cmnd *scp; - int hanum; + int hanum, rval; unchar IStatus; ushort CmdStatus, Service = 0; - ulong InfoBytes, InfoBytes2 = 0; + ulong32 InfoBytes, InfoBytes2 = 0; gdth_evt_data dvr; + ulong flags = 0; TRACE(("gdth_interrupt() IRQ %d\n",irq)); @@ -2188,6 +2546,8 @@ } } + if (!gdth_polling) + GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags); wait_index = 0; /* search controller */ @@ -2195,6 +2555,8 @@ /* TRACE2(("gdth_interrupt(): Spurious interrupt received\n")); */ + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); return; } @@ -2204,63 +2566,63 @@ ha = HADATA(gdth_ctr_tab[hanum]); if (ha->type == GDT_EISA) { - if (IStatus & 0x80) { /* error flag */ + if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; CmdStatus = inw(ha->bmic + MAILBOXREG+8); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus)); - if (IStatus == ASYNCINDEX) { /* async. event ? */ + if (IStatus == ASYNCINDEX) { /* async. event ? */ Service = inw(ha->bmic + MAILBOXREG+10); InfoBytes2 = inl(ha->bmic + MAILBOXREG+4); } - } else /* no error */ + } else /* no error */ CmdStatus = S_OK; InfoBytes = inl(ha->bmic + MAILBOXREG+12); - if (gdth_polling) /* init. -> more info */ - InfoBytes2 = inl(ha->bmic + MAILBOXREG+4); - outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ - outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ + if (gdth_polling) /* init. -> more info */ + InfoBytes2 = inl(ha->bmic + MAILBOXREG+4); + outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ + outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ } else if (ha->type == GDT_ISA) { dp2_ptr = (gdt2_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ + if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - CmdStatus = readw(&dp2_ptr->u.ic.Status); + CmdStatus = gdth_readw(&dp2_ptr->u.ic.Status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus)); - if (IStatus == ASYNCINDEX) { /* async. event ? */ - Service = readw(&dp2_ptr->u.ic.Service); - InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]); + if (IStatus == ASYNCINDEX) { /* async. event ? */ + Service = gdth_readw(&dp2_ptr->u.ic.Service); + InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); } - } else /* no error */ + } else /* no error */ CmdStatus = S_OK; - InfoBytes = readl(&dp2_ptr->u.ic.Info[0]); - if (gdth_polling) /* init. -> more info */ - InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]); - writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ - writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */ - writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ + InfoBytes = gdth_readl(&dp2_ptr->u.ic.Info[0]); + if (gdth_polling) /* init. -> more info */ + InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); + gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */ + gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ } else if (ha->type == GDT_PCI) { dp6_ptr = (gdt6_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ + if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - CmdStatus = readw(&dp6_ptr->u.ic.Status); + CmdStatus = gdth_readw(&dp6_ptr->u.ic.Status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus)); if (IStatus == ASYNCINDEX) { /* async. event ? */ - Service = readw(&dp6_ptr->u.ic.Service); - InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]); + Service = gdth_readw(&dp6_ptr->u.ic.Service); + InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); } - } else /* no error */ + } else /* no error */ CmdStatus = S_OK; - InfoBytes = readl(&dp6_ptr->u.ic.Info[0]); - if (gdth_polling) /* init. -> more info */ - InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]); - writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ - writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */ - writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ + InfoBytes = gdth_readl(&dp6_ptr->u.ic.Info[0]); + if (gdth_polling) /* init. -> more info */ + InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); + gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */ + gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ } else if (ha->type == GDT_PCINEW) { - if (IStatus & 0x80) { /* error flag */ + if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; CmdStatus = inw(PTR2USHORT(&ha->plx->status)); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus)); - if (IStatus == ASYNCINDEX) { /* async. event ? */ + if (IStatus == ASYNCINDEX) { /* async. event ? */ Service = inw(PTR2USHORT(&ha->plx->service)); InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1])); } @@ -2268,34 +2630,36 @@ CmdStatus = S_OK; InfoBytes = inl(PTR2USHORT(&ha->plx->info[0])); - if (gdth_polling) /* init. -> more info */ - InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1])); + if (gdth_polling) /* init. -> more info */ + InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1])); outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ + if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - CmdStatus = readw(&dp6m_ptr->i960r.status); + CmdStatus = gdth_readw(&dp6m_ptr->i960r.status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus)); - if (IStatus == ASYNCINDEX) { /* async. event ? */ - Service = readw(&dp6m_ptr->i960r.service); - InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]); + if (IStatus == ASYNCINDEX) { /* async. event ? */ + Service = gdth_readw(&dp6m_ptr->i960r.service); + InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]); } - } else /* no error */ + } else /* no error */ CmdStatus = S_OK; - InfoBytes = readl(&dp6m_ptr->i960r.info[0]); - if (gdth_polling) /* init. -> more info */ - InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]); - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(0, &dp6m_ptr->i960r.sema1_reg); + InfoBytes = gdth_readl(&dp6m_ptr->i960r.info[0]); + if (gdth_polling) /* init. -> more info */ + InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]); + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } else { TRACE2(("gdth_interrupt() unknown controller type\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); return; } - TRACE(("gdth_interrupt() index %d stat %d info %ld\n", - IStatus,CmdStatus,InfoBytes)); + TRACE(("gdth_interrupt() index %d stat %d info %d\n", + IStatus,CmdStatus,InfoBytes)); ha->status = CmdStatus; ha->info = InfoBytes; ha->info2 = InfoBytes2; @@ -2308,31 +2672,51 @@ if (IStatus == ASYNCINDEX) { TRACE2(("gdth_interrupt() async. event\n")); gdth_async_event(hanum,Service); - } else { - if (IStatus == SPEZINDEX) { - TRACE2(("Service unknown or not initialized !\n")); - dvr.size = sizeof(dvr.eu.driver); - dvr.eu.driver.ionode = hanum; - gdth_store_event(ES_DRIVER, 4, &dvr); - return; - } - scp = gdth_cmd_tab[IStatus-2][hanum].cmnd; - Service = gdth_cmd_tab[IStatus-2][hanum].service; - gdth_cmd_tab[IStatus-2][hanum].cmnd = UNUSED_CMND; - if (scp == UNUSED_CMND) { - TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); - dvr.size = sizeof(dvr.eu.driver); - dvr.eu.driver.ionode = hanum; - dvr.eu.driver.index = IStatus; - gdth_store_event(ES_DRIVER, 1, &dvr); - return; - } - if (scp == INTERNAL_CMND) { - TRACE(("gdth_interrupt() answer to internal command\n")); - return; - } - TRACE(("gdth_interrupt() sync. status\n")); - gdth_sync_event(hanum,Service,IStatus,scp); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + gdth_next(hanum); + return; + } + + if (IStatus == SPEZINDEX) { + TRACE2(("Service unknown or not initialized !\n")); + dvr.size = sizeof(dvr.eu.driver); + dvr.eu.driver.ionode = hanum; + gdth_store_event(ha, ES_DRIVER, 4, &dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + return; + } + scp = ha->cmd_tab[IStatus-2].cmnd; + Service = ha->cmd_tab[IStatus-2].service; + ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; + if (scp == UNUSED_CMND) { + TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); + dvr.size = sizeof(dvr.eu.driver); + dvr.eu.driver.ionode = hanum; + dvr.eu.driver.index = IStatus; + gdth_store_event(ha, ES_DRIVER, 1, &dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + return; + } + if (scp == INTERNAL_CMND) { + TRACE(("gdth_interrupt() answer to internal command\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + return; + } + + TRACE(("gdth_interrupt() sync. status\n")); + rval = gdth_sync_event(hanum,Service,IStatus,scp); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + if (rval == 2) { + gdth_putq(hanum,scp,scp->SCp.this_residual); + } else if (rval == 1) { + GDTH_LOCK_SCSI_DONE(flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(flags); } gdth_next(hanum); } @@ -2348,13 +2732,14 @@ ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; - TRACE(("gdth_sync_event() scp %lx serv %d status %d\n", - (ulong)scp,service,ha->status)); + TRACE(("gdth_sync_event() serv %d status %d\n", + service,ha->status)); if (service == SCREENSERVICE) { msg = (gdth_msg_str *)ha->pscratch; - TRACE(("len: %ld, answer: %d, ext: %d, alen: %ld\n", - msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen)); + ha->scratch_busy = FALSE; + TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n", + msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen)); if (msg->msg_len) if (!(msg->msg_answer && msg->msg_ext)) { msg->msg_text[msg->msg_len] = '\0'; @@ -2363,7 +2748,7 @@ if (msg->msg_ext && !msg->msg_answer) { while (gdth_test_busy(hanum)) - udelay(1); + gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; gdth_get_cmd_index(hanum); @@ -2372,14 +2757,15 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.msg_handle= msg->msg_handle; - cmdp->u.screen.msg_addr = (ulong)msg; + cmdp->u.screen.msg_addr = virt_to_bus(msg); + ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) - + sizeof(ulong); + + sizeof(ulong32); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); - return 1; + return 0; } if (msg->msg_answer && msg->msg_alen) { @@ -2400,7 +2786,7 @@ } msg->msg_len = i; while (gdth_test_busy(hanum)) - udelay(1); + gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; gdth_get_cmd_index(hanum); @@ -2409,14 +2795,15 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.msg_handle= msg->msg_handle; - cmdp->u.screen.msg_addr = (ulong)msg; + cmdp->u.screen.msg_addr = virt_to_bus(msg); + ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) - + sizeof(ulong); + + sizeof(ulong32); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); - return 1; + return 0; } printk("\n"); @@ -2424,12 +2811,25 @@ scp->SCp.Message = (int)ha->status; /* cache or raw service */ if (ha->status == S_OK) { + if (scp->SCp.Status != -1) { + TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n", + scp->SCp.Status)); + scp->SCp.Status = -1; + scp->SCp.this_residual = HIGH_PRI; + return 2; + } scp->result = DID_OK << 16; } else if (ha->status == S_BSY) { TRACE2(("Controller busy -> retry !\n")); - gdth_putq(hanum,scp,DEFAULT_PRI); - return 1; + return 2; } else { + if (scp->SCp.Status != -1) { + TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n", + scp->SCp.Status, ha->status)); + scp->SCp.Status = -1; + scp->SCp.this_residual = HIGH_PRI; + return 2; + } if (service == CACHESERVICE) { memset((char*)scp->sense_buffer,0,16); scp->sense_buffer[0] = 0x70; @@ -2442,30 +2842,27 @@ dvr.eu.sync.service = service; dvr.eu.sync.status = ha->status; dvr.eu.sync.info = ha->info; - dvr.eu.sync.hostdrive = -#if LINUX_VERSION_CODE >= 0x020000 - ha->id[scp->channel][scp->target].hostdrive; -#else - ha->id[NUMDATA(scp->host)->busnum][scp->target].hostdrive; -#endif + dvr.eu.sync.hostdrive = scp->target; if (ha->status >= 0x8000) - gdth_store_event(ES_SYNC, 0, &dvr); + gdth_store_event(ha, ES_SYNC, 0, &dvr); else - gdth_store_event(ES_SYNC, service, &dvr); + gdth_store_event(ha, ES_SYNC, service, &dvr); } } else { - if (ha->status!=S_RAW_SCSI || ha->status==S_RAW_ILL) { + if (ha->status!=S_RAW_SCSI || ha->info>=0x100) { scp->result = DID_BAD_TARGET << 16; } else { scp->result = (DID_OK << 16) | ha->info; } } } - scp->SCp.have_data_in++; - scp->scsi_done(scp); + if (!scp->SCp.have_data_in) + scp->SCp.have_data_in++; + else + return 1; } - return 1; + return 0; } static char *async_cache_tab[] = { @@ -2587,15 +2984,40 @@ "GDT HA %u, Array Drive %u: expand restarted", /*58*/ "\005\000\002\006\002" "GDT HA %u, Array Drive %u: expand stopped", +/*59*/ "\005\000\002\010\002" + "GDT HA %u, Mirror Drive %u: drive build quited", +/*60*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity build quited", +/*61*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: drive rebuild quited", +/*62*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity verify started", +/*63*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity verify done", +/*64*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity verify failed", +/*65*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity error detected", +/*66*/ "\005\000\002\006\002" + "GDT HA %u, Array Drive %u: parity verify quited", +/*67*/ "\005\000\002\006\002" + "GDT HA %u, Host Drive %u reserved", +/*68*/ "\005\000\002\006\002" + "GDT HA %u, Host Drive %u mounted and released", +/*69*/ "\005\000\002\006\002" + "GDT HA %u, Host Drive %u released", +/*70*/ "\003\000\002" + "GDT HA %u, DRAM error detected and corrected with ECC", +/*71*/ "\003\000\002" + "GDT HA %u, Uncorrectable DRAM error detected with ECC", +/*72*/ "\011\000\002\012\001\013\001\014\001" + "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block", }; static int gdth_async_event(int hanum,int service) { - gdth_stackframe stack; gdth_evt_data dvr; - char *f = NULL; - int i,j; gdth_ha_str *ha; gdth_msg_str *msg; gdth_cmd_str *cmdp; @@ -2605,12 +3027,12 @@ cmdp= ha->pccb; msg = (gdth_msg_str *)ha->pscratch; TRACE2(("gdth_async_event() ha %d serv %d\n", - hanum,service)); + hanum,service)); if (service == SCREENSERVICE) { if (ha->status == MSG_REQUEST) { while (gdth_test_busy(hanum)) - udelay(1); + gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; cmd_index = gdth_get_cmd_index(hanum); @@ -2619,10 +3041,11 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.msg_addr = (ulong)msg; + cmdp->u.screen.msg_addr = virt_to_bus(msg); + ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) - + sizeof(ulong); + + sizeof(ulong32); ha->cmd_cnt = 0; gdth_copy_command(hanum); if (ha->type == GDT_EISA) @@ -2641,80 +3064,89 @@ dvr.eu.async.service = service; dvr.eu.async.status = ha->status; dvr.eu.async.info = ha->info; - *(ulong *)dvr.eu.async.scsi_coord = ha->info2; - gdth_store_event(ES_ASYNC, service, &dvr); + *(ulong32 *)dvr.eu.async.scsi_coord = ha->info2; + gdth_store_event(ha, ES_ASYNC, service, &dvr); + gdth_log_event( &dvr ); + } + return 1; +} - if (service==CACHESERVICE && INDEX_OK(ha->status,async_cache_tab)) { - TRACE2(("GDT: Async. event cache service, event no.: %d\n", - ha->status)); - - f = async_cache_tab[ha->status]; +static void gdth_log_event(gdth_evt_data *dvr) +{ + gdth_stackframe stack; + char *f = NULL; + int i,j; - /* i: parameter to push, j: stack element to fill */ - for (j=0,i=1; i < f[0]; i+=2) { - switch (f[i+1]) { - case 4: - stack.b[j++] = *(ulong*)&dvr.eu.stream[(int)f[i]]; - break; - case 2: - stack.b[j++] = *(ushort*)&dvr.eu.stream[(int)f[i]]; - break; - case 1: - stack.b[j++] = *(unchar*)&dvr.eu.stream[(int)f[i]]; - break; - default: - break; - } + TRACE2(("gdth_log_event()\n")); + if (dvr->eu.async.service == CACHESERVICE && + INDEX_OK(dvr->eu.async.status, async_cache_tab)) { + TRACE2(("GDT: Async. event cache service, event no.: %d\n", + dvr->eu.async.status)); + + f = async_cache_tab[dvr->eu.async.status]; + + /* i: parameter to push, j: stack element to fill */ + for (j=0,i=1; i < f[0]; i+=2) { + switch (f[i+1]) { + case 4: + stack.b[j++] = *(ulong32*)&dvr->eu.stream[(int)f[i]]; + break; + case 2: + stack.b[j++] = *(ushort*)&dvr->eu.stream[(int)f[i]]; + break; + case 1: + stack.b[j++] = *(unchar*)&dvr->eu.stream[(int)f[i]]; + break; + default: + break; } + } - printk(&f[f[0]],stack); printk("\n"); + printk(&f[(int)f[0]],stack); printk("\n"); - } else { - printk("GDT: Unknown async. event service %d event no. %d\n", - service,ha->status); - } + } else { + printk("GDT: Unknown async. event service %d event no. %d\n", + dvr->eu.async.service,dvr->eu.async.status); } - return 1; } #ifdef GDTH_STATISTICS -void gdth_timeout(void) +void gdth_timeout(ulong data) { - ulong flags,i; + ulong32 i; Scsi_Cmnd *nscp; gdth_ha_str *ha; + ulong flags; int hanum = 0; - save_flags(flags); - cli(); + ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); for (act_stats=0,i=0; icmd_tab[i].cmnd != UNUSED_CMND) ++act_stats; - ha = HADATA(gdth_ctr_tab[hanum]); for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr) ++act_rq; - TRACE2(("gdth_to(): ints %ld, ios %ld, act_stats %ld, act_rq %ld\n", + TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n", act_ints, act_ios, act_stats, act_rq)); act_ints = act_ios = 0; - timer_table[GDTH_TIMER].expires = jiffies + 30*HZ; - timer_active |= 1<= MAXHA) + break; if (gdth_search_isa(isa_bios)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); ha = HADATA(shp); @@ -2761,19 +3189,16 @@ continue; } /* controller found and initialized */ - printk("Configuring GDT-ISA HA at BIOS 0x%05lX IRQ %u DRQ %u\n", + printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", isa_bios,ha->irq,ha->drq); - save_flags(flags); - cli(); #if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL)) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) #else if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) #endif { printk("GDT-ISA: Unable to allocate IRQ\n"); - restore_flags(flags); scsi_unregister(shp); continue; } @@ -2784,7 +3209,6 @@ #else free_irq(ha->irq); #endif - restore_flags(flags); scsi_unregister(shp); continue; } @@ -2793,12 +3217,6 @@ shp->unchecked_isa_dma = 1; shp->irq = ha->irq; shp->dma_channel = ha->drq; - for (i=0; iid[0][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } hanum = gdth_ctr_count; gdth_ctr_tab[gdth_ctr_count++] = shp; gdth_ctr_vtab[gdth_ctr_vcount++] = shp; @@ -2807,61 +3225,56 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); - ha->pscratch = DMADATA(shp); + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ha->scratch_busy = FALSE; ha->req_first = NULL; - for (i=0; iid[i][j].type = EMPTY_DTYP; - ha->id[i][j].lock = 0; - } - } - restore_flags(flags); + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; - if (!gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; - --gdth_ctr_vcount; - save_flags(flags); - cli(); + --gdth_ctr_vcount; + if (ha->pscratch != NULL) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); #else free_irq(ha->irq); #endif - restore_flags(flags); scsi_unregister(shp); continue; } #if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = 8; - shp->max_lun = 8; - shp->max_channel = ha->bus_cnt - 1; + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; #else /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt; ++b) { + for (b=1; bbus_cnt+1; ++b) { shp = scsi_register(shtp,sizeof(gdth_num_str)); shp->unchecked_isa_dma = 1; shp->irq = ha->irq; shp->dma_channel = ha->drq; - for (i=0; iid[b][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } gdth_ctr_vtab[gdth_ctr_vcount++] = shp; NUMDATA(shp)->hanum = (ushort)hanum; NUMDATA(shp)->busnum = b; } #endif - + GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } } /* scanning for EISA controllers */ for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { + if (gdth_ctr_count >= MAXHA) + break; if (gdth_search_eisa(eisa_slot)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); ha = HADATA(shp); @@ -2873,134 +3286,117 @@ printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", eisa_slot>>12,ha->irq); - save_flags(flags); - cli(); #if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL)) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) #else if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) #endif { printk("GDT-EISA: Unable to allocate IRQ\n"); - restore_flags(flags); scsi_unregister(shp); continue; } shp->unchecked_isa_dma = 0; shp->irq = ha->irq; shp->dma_channel = 0xff; - for (i=0; iid[0][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } hanum = gdth_ctr_count; gdth_ctr_tab[gdth_ctr_count++] = shp; gdth_ctr_vtab[gdth_ctr_vcount++] = shp; NUMDATA(shp)->hanum = (ushort)hanum; NUMDATA(shp)->busnum= 0; - TRACE2(("EISA detect Bus 0: shp %lx hanum %d\n", - (ulong)shp,NUMDATA(shp)->hanum)); + TRACE2(("EISA detect Bus 0: hanum %d\n", + NUMDATA(shp)->hanum)); ha->pccb = CMDDATA(shp); - ha->pscratch = DMADATA(shp); + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ha->scratch_busy = FALSE; ha->req_first = NULL; - for (i=0; iid[i][j].type = EMPTY_DTYP; - ha->id[i][j].lock = 0; - } - } - restore_flags(flags); + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; - if (!gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; - --gdth_ctr_vcount; - save_flags(flags); - cli(); + --gdth_ctr_vcount; + if (ha->pscratch != NULL) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); #else free_irq(ha->irq); #endif - restore_flags(flags); scsi_unregister(shp); continue; } #if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = 8; - shp->max_lun = 8; - shp->max_channel = ha->bus_cnt - 1; + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; #else /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt; ++b) { + for (b=1; bbus_cnt+1; ++b) { shp = scsi_register(shtp,sizeof(gdth_num_str)); shp->unchecked_isa_dma = 0; shp->irq = ha->irq; shp->dma_channel = 0xff; - for (i=0; iid[b][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } gdth_ctr_vtab[gdth_ctr_vcount++] = shp; NUMDATA(shp)->hanum = (ushort)hanum; NUMDATA(shp)->busnum = b; - TRACE2(("EISA detect Bus %d: shp %lx hanum %d\n", - NUMDATA(shp)->busnum,(ulong)shp, - NUMDATA(shp)->hanum)); + TRACE2(("EISA detect Bus %d: shp %x hanum %d\n", + NUMDATA(shp)->busnum,(ulong32)shp, + NUMDATA(shp)->hanum)); } #endif - + GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } } /* scanning for PCI controllers */ - for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDT6x21RP2; ++device_id) { - if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 && - device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP) - continue; - for (index = 0; ; ++index) { - if (!gdth_search_pci(device_id,index,&pcistr)) - break; /* next device_id */ +#if LINUX_VERSION_CODE >= 0x2015C + if (pci_present()) +#else + if (pcibios_present()) +#endif + { + gdth_pci_str pcistr[MAXHA]; + + cnt = gdth_search_pci(pcistr); + gdth_sort_pci(pcistr,cnt); + for (ctr = 0; ctr < cnt; ++ctr) { + if (gdth_ctr_count >= MAXHA) + break; shp = scsi_register(shtp,sizeof(gdth_ext_str)); ha = HADATA(shp); - if (!gdth_init_pci(&pcistr,ha)) { + if (!gdth_init_pci(&pcistr[ctr],ha)) { scsi_unregister(shp); continue; } /* controller found and initialized */ printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr.bus,pcistr.device_fn>>3,ha->irq); + pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); - save_flags(flags); - cli(); #if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL)) + if (request_irq(ha->irq, gdth_interrupt, + SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) #else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) + if (request_irq(ha->irq, gdth_interrupt, + SA_INTERRUPT|SA_SHIRQ, "gdth")) #endif { printk("GDT-PCI: Unable to allocate IRQ\n"); - restore_flags(flags); scsi_unregister(shp); continue; } shp->unchecked_isa_dma = 0; shp->irq = ha->irq; shp->dma_channel = 0xff; - for (i=0; iid[0][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } hanum = gdth_ctr_count; gdth_ctr_tab[gdth_ctr_count++] = shp; gdth_ctr_vtab[gdth_ctr_vcount++] = shp; @@ -3009,55 +3405,48 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); - ha->pscratch = DMADATA(shp); + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ha->scratch_busy = FALSE; ha->req_first = NULL; - for (i=0; iid[i][j].type = EMPTY_DTYP; - ha->id[i][j].lock = 0; - } - } - restore_flags(flags); + ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; - if (!gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { printk("GDT-PCI: Error during device scan\n"); --gdth_ctr_count; - --gdth_ctr_vcount; - save_flags(flags); - cli(); + --gdth_ctr_vcount; + if (ha->pscratch != NULL) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); #else free_irq(ha->irq); #endif - restore_flags(flags); scsi_unregister(shp); continue; } #if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = 8; - shp->max_lun = 8; - shp->max_channel = ha->bus_cnt - 1; + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; #else /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt; ++b) { + for (b=1; bbus_cnt+1; ++b) { shp = scsi_register(shtp,sizeof(gdth_num_str)); shp->unchecked_isa_dma = 0; shp->irq = ha->irq; shp->dma_channel = 0xff; - for (i=0; iid[b][i].type==SIOP_DTYP) { - shp->this_id = i; - break; - } - } gdth_ctr_vtab[gdth_ctr_vcount++] = shp; NUMDATA(shp)->hanum = (ushort)hanum; NUMDATA(shp)->busnum = b; } #endif - + GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } } @@ -3065,13 +3454,15 @@ TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count)); if (gdth_ctr_count > 0) { #ifdef GDTH_STATISTICS - TRACE2(("gdth_detect(): Initializing timer !\n")); - timer_table[GDTH_TIMER].fn = gdth_timeout; - timer_table[GDTH_TIMER].expires = jiffies + HZ; - timer_active |= 1<= 0x020100 - register_reboot_notifier(&gdth_notifier); + register_reboot_notifier(&gdth_notifier); #endif } gdth_polling = FALSE; @@ -3081,13 +3472,15 @@ int gdth_release(struct Scsi_Host *shp) { - unsigned long flags; + int hanum; + gdth_ha_str *ha; TRACE2(("gdth_release()\n")); - - save_flags(flags); - cli(); if (NUMDATA(shp)->busnum == 0) { + hanum = NUMDATA(shp)->hanum; + ha = HADATA(gdth_ctr_tab[hanum]); + gdth_flush(hanum); + if (shp->irq) { #if LINUX_VERSION_CODE >= 0x010346 free_irq(shp->irq,NULL); @@ -3098,9 +3491,21 @@ if (shp->dma_channel != 0xff) { free_dma(shp->dma_channel); } + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + gdth_ctr_released++; + TRACE2(("gdth_release(): HA %d of %d\n", + gdth_ctr_released, gdth_ctr_count)); + + if (gdth_ctr_released == gdth_ctr_count) { +#ifdef GDTH_STATISTICS + del_timer(&gdth_timer); +#endif +#if LINUX_VERSION_CODE >= 0x020100 + unregister_reboot_notifier(&gdth_notifier); +#endif + } } - restore_flags(flags); scsi_unregister(shp); return 0; } @@ -3117,102 +3522,40 @@ if (ha->type == GDT_EISA) { switch (ha->stype) { case GDT3_ID: - return("GDT3000/3020 (EISA)"); + return("GDT3000/3020"); case GDT3A_ID: - return("GDT3000A/3020A/3050A (EISA)"); + return("GDT3000A/3020A/3050A"); case GDT3B_ID: - return("GDT3000B/3010A (EISA)"); + return("GDT3000B/3010A"); } } else if (ha->type == GDT_ISA) { - return("GDT2000/2020 (ISA)"); + return("GDT2000/2020"); } else if (ha->type == GDT_PCI) { switch (ha->stype) { case PCI_DEVICE_ID_VORTEX_GDT60x0: - return("GDT6000/6020/6050 (PCI)"); + return("GDT6000/6020/6050"); case PCI_DEVICE_ID_VORTEX_GDT6000B: - return("GDT6000B/6010 (PCI)"); - } - } else if (ha->type == GDT_PCINEW) { - switch (ha->stype) { - case PCI_DEVICE_ID_VORTEX_GDT6x10: - return("GDT6110/6510 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x20: - return("GDT6120/6520 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6530: - return("GDT6530 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6550: - return("GDT6550 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x17: - return("GDT6117/6517 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x27: - return("GDT6127/6527 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6537: - return("GDT6537 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6557: - return("GDT6557/6557-ECC (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x15: - return("GDT6115/6515 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x25: - return("GDT6125/6525 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6535: - return("GDT6535 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6555: - return("GDT6555/6555-ECC (PCI)"); - } - } else if (ha->type == GDT_PCIMPR) { - switch (ha->stype) { - case PCI_DEVICE_ID_VORTEX_GDT6x17RP: - return("GDT6117RP/GDT6517RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x27RP: - return("GDT6127RP/GDT6527RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6537RP: - return("GDT6537RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6557RP: - return("GDT6557RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x11RP: - return("GDT6111RP/GDT6511RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x21RP: - return("GDT6121RP/GDT6521RP (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x17RP1: - return("GDT6117RP1/GDT6517RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x27RP1: - return("GDT6127RP1/GDT6527RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6537RP1: - return("GDT6537RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6557RP1: - return("GDT6557RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x11RP1: - return("GDT6111RP1/GDT6511RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x21RP1: - return("GDT6121RP1/GDT6521RP1 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x17RP2: - return("GDT6117RP2/GDT6517RP2 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x27RP2: - return("GDT6127RP2/GDT6527RP2 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6537RP2: - return("GDT6537RP2 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6557RP2: - return("GDT6557RP2 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x11RP2: - return("GDT6111RP2/GDT6511RP2 (PCI)"); - case PCI_DEVICE_ID_VORTEX_GDT6x21RP2: - return("GDT6121RP2/GDT6521RP2 (PCI)"); + return("GDT6000B/6010"); } - } + } + /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */ + return(""); } const char *gdth_info(struct Scsi_Host *shp) { int hanum; - + gdth_ha_str *ha; + TRACE2(("gdth_info()\n")); hanum = NUMDATA(shp)->hanum; + ha = HADATA(gdth_ctr_tab[hanum]); - return (gdth_ctr_name(hanum)); + return ((const char *)ha->ctr_name); } - +/* old error handling */ int gdth_abort(Scsi_Cmnd *scp) { TRACE2(("gdth_abort() reason %d\n",scp->abort_reason)); @@ -3229,6 +3572,32 @@ return SCSI_RESET_PUNT; } +#if LINUX_VERSION_CODE >= 0x02015F +/* new error handling */ +int gdth_eh_abort(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_eh_abort()\n")); + return FAILED; +} + +int gdth_eh_device_reset(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_eh_device_reset()\n")); + return FAILED; +} + +int gdth_eh_bus_reset(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_eh_bus_reset()\n")); + return FAILED; +} + +int gdth_eh_host_reset(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_eh_host_reset()\n")); + return FAILED; +} +#endif #if LINUX_VERSION_CODE >= 0x010300 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) @@ -3236,18 +3605,36 @@ int gdth_bios_param(Disk *disk,int dev,int *ip) #endif { - unchar b, t; + unchar t; int hanum; gdth_ha_str *ha; + int drv_hds, drv_secs; hanum = NUMDATA(disk->device->host)->hanum; - b = disk->device->channel; t = disk->device->id; - TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); + TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", + hanum, disk->device->channel, t)); ha = HADATA(gdth_ctr_tab[hanum]); - ip[0] = ha->id[b][t].heads; - ip[1] = ha->id[b][t].secs; + if (ha->hdr[t].heads == 0) { + /* raw device: evaluate mapping (sectors per head, heads per cylinder) */ + if (disk->capacity /HEADS/SECS <= MAXCYLS) { + drv_hds = HEADS; + drv_secs= SECS; + } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) { + drv_hds = MEDHEADS; + drv_secs= MEDSECS; + } else { + drv_hds = BIGHEADS; + drv_secs= BIGSECS; + } + ha->hdr[t].heads = drv_hds; + ha->hdr[t].secs = drv_secs; + TRACE2(("gdth_bios_param(): raw device -> params evaluated\n")); + } + + ip[0] = ha->hdr[t].heads; + ip[1] = ha->hdr[t].secs; ip[2] = disk->capacity / ip[0] / ip[1]; TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n", @@ -3280,10 +3667,12 @@ int priority; TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n", - scp->cmnd[0],scp->target,scp->lun)); + scp->cmnd[0],scp->target,scp->lun)); scp->scsi_done = (void *)done; - scp->SCp.have_data_in = 0; + scp->SCp.have_data_in = 1; + scp->SCp.phase = -1; + scp->SCp.Status = -1; hanum = NUMDATA(scp->host)->hanum; #ifdef GDTH_STATISTICS ++act_ios; @@ -3299,6 +3688,52 @@ return 0; } +/* flush routine */ +static void gdth_flush(int hanum) +{ + int i; + gdth_ha_str *ha; + Scsi_Cmnd scp; + Scsi_Device sdev; + gdth_cmd_str gdtcmd; + char cmnd[12]; + + TRACE2(("gdth_flush() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = gdth_ctr_tab[hanum]; + sdev.id = sdev.host->this_id; + scp.cmd_len = 12; + scp.host = gdth_ctr_tab[hanum]; + scp.target = sdev.host->this_id; + scp.device = &sdev; + scp.use_sg = 0; + + for (i = 0; i < MAX_HDRIVES; ++i) { + if (ha->hdr[i].present) { + gdtcmd.BoardNode = LOCALBOARD; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_FLUSH; + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); + { + struct semaphore sem = MUTEX_LOCKED; + scp.request.rq_status = RQ_SCSI_BUSY; + scp.request.sem = &sem; + scp.SCp.this_residual = IOCTL_PRI; + GDTH_LOCK_SCSI_DOCMD(); + scsi_do_cmd(&scp, cmnd, &gdtcmd, + sizeof(gdth_cmd_str), gdth_scsi_done, + 30*HZ, 1); + GDTH_UNLOCK_SCSI_DOCMD(); + down(&sem); + } + } + } +} /* shutdown routine */ #if LINUX_VERSION_CODE >= 0x020100 @@ -3307,23 +3742,32 @@ void gdth_halt(void) #endif { - int hanum, i, j; - gdth_ha_str *ha; + int hanum; +#ifndef __alpha__ Scsi_Cmnd scp; Scsi_Device sdev; gdth_cmd_str gdtcmd; char cmnd[12]; +#endif #if LINUX_VERSION_CODE >= 0x020100 TRACE2(("gdth_halt() event %d\n",event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) - return NOTIFY_DONE; + return NOTIFY_DONE; #else TRACE2(("gdth_halt()\n")); + if (halt_called) { + TRACE2(("already called\n")); + return; + } + halt_called = TRUE; #endif printk("GDT: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { - ha = HADATA(gdth_ctr_tab[hanum]); + gdth_flush(hanum); + +#ifndef __alpha__ + /* controller reset */ memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); sdev.host = gdth_ctr_tab[hanum]; @@ -3334,32 +3778,6 @@ scp.device = &sdev; scp.use_sg = 0; - /* flush */ - for (i = 0; i < MAXBUS; ++i) { - for (j = 0; j < MAXID; ++j) { - if (ha->id[i][j].type == CACHE_DTYP) { - gdtcmd.BoardNode = LOCALBOARD; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; - TRACE2(("gdth_halt(): flush ha %d drive %d\n", - hanum, ha->id[i][j].hostdrive)); - { - struct semaphore sem = MUTEX_LOCKED; - scp.request.rq_status = RQ_SCSI_BUSY; - scp.request.sem = &sem; - scsi_do_cmd(&scp, cmnd, &gdtcmd, - sizeof(gdth_cmd_str), gdth_scsi_done, - 30*HZ, 1); - down(&sem); - } - } - } - } - - /* controller reset */ gdtcmd.BoardNode = LOCALBOARD; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; @@ -3368,16 +3786,20 @@ struct semaphore sem = MUTEX_LOCKED; scp.request.rq_status = RQ_SCSI_BUSY; scp.request.sem = &sem; + scp.SCp.this_residual = IOCTL_PRI; + GDTH_LOCK_SCSI_DOCMD(); scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str), gdth_scsi_done, 10*HZ, 1); + GDTH_UNLOCK_SCSI_DOCMD(); down(&sem); } +#endif } printk("Done.\n"); #ifdef GDTH_STATISTICS - timer_active &= ~(1<= 0x020100 unregister_reboot_notifier(&gdth_notifier); @@ -3387,35 +3809,69 @@ /* called from init/main.c */ -void gdth_setup(char *str,int *ints) +__initfunc (void gdth_setup(char *str,int *ints)) { - static size_t setup_idx = 0; + int i, argc; + char *cur_str, *argv; - TRACE2(("gdth_setup() str %s ints[0] %d ints[1] %d\n", - str ? str:"NULL", ints[0], - ints[0] ? ints[1]:0)); + TRACE2(("gdth_setup() str %s ints[0] %d\n", + str ? str:"NULL", ints ? ints[0]:0)); - if (setup_idx >= MAXHA) { - printk("GDT: gdth_setup() called too many times. Bad LILO params ?\n"); - return; - } - if (ints[0] != 1) { - printk("GDT: Illegal command line !\n"); - printk("Usage: gdth=\n"); - printk("Where: : valid EISA controller IRQ (10,11,12,14)\n"); - printk(" or 0 to disable controller driver\n"); - return; - } - if (ints[1] == 10 || ints[1] == 11 || ints[1] == 12 || ints[1] == 14) { - irqs[setup_idx++] = ints[1]; - irqs[setup_idx] = 0xff; - return; + /* read irq[] from ints[] */ + if (ints) { + argc = ints[0]; + if (argc > 0) { + if (argc > MAXHA) + argc = MAXHA; + for (i = 0; i < argc; ++i) + irq[i] = ints[i+1]; + } } - if (ints[1] == 0) { - disable_gdth_scan = TRUE; - return; + + /* analyse string */ + argv = str; + while (argv && (cur_str = strchr(argv, ':'))) { + int val = 0, c = *++cur_str; + + if (c == 'n' || c == 'N') + val = 0; + else if (c == 'y' || c == 'Y') + val = 1; + else + val = (int)simple_strtoul(cur_str, NULL, 0); + + if (!strncmp(argv, "disable:", 8)) + disable = val; + else if (!strncmp(argv, "reserve_mode:", 13)) + reserve_mode = val; + else if (!strncmp(argv, "reverse_scan:", 13)) + reverse_scan = val; + else if (!strncmp(argv, "max_ids:", 8)) + max_ids = val; + else if (!strncmp(argv, "rescan:", 7)) + rescan = val; + else if (!strncmp(argv, "reserve_list:", 13)) { + reserve_list[0] = val; + for (i = 1; i < MAX_RES_ARGS; i++) { + cur_str = strchr(cur_str, ','); + if (!cur_str) + break; + if (!isdigit((int)*++cur_str)) { + --cur_str; + break; + } + reserve_list[i] = + (int)simple_strtoul(cur_str, NULL, 0); + } + if (!cur_str) + break; + argv = ++cur_str; + continue; + } + + if ((argv = strchr(argv, ','))) + ++argv; } - printk("GDT: Invalid IRQ (%d) specified\n",ints[1]); } @@ -3423,4 +3879,3 @@ Scsi_Host_Template driver_template = GDTH; #include "scsi_module.c" #endif - diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h --- v2.2.0-pre6/linux/drivers/scsi/gdth.h Fri Jul 31 17:07:59 1998 +++ linux/drivers/scsi/gdth.h Mon Jan 11 10:35:50 1999 @@ -4,13 +4,13 @@ /* * Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux * - * gdth.h Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner + * gdth.h Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner * See gdth.c for further informations and * below for supported controller types * * * - * $Id: gdth.h,v 1.9 1997/11/04 09:55:42 achim Exp $ + * $Id: gdth.h,v 1.16 1998/12/17 15:54:53 achim Exp $ */ #include @@ -29,9 +29,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "1.02" +#define GDTH_VERSION_STR "1.10" #define GDTH_VERSION 1 -#define GDTH_SUBVERSION 2 +#define GDTH_SUBVERSION 10 /* protocol version */ #define PROTOCOL_VERSION 1 @@ -48,11 +48,13 @@ #define GDT3B_ID 0x0330941c /* GDT3000B/3010A */ /* GDT_ISA */ #define GDT2_ID 0x0120941c /* GDT2000/2020 */ + /* vendor ID, device IDs (PCI) */ /* these defines should already exist in */ #ifndef PCI_VENDOR_ID_VORTEX #define PCI_VENDOR_ID_VORTEX 0x1119 /* PCI controller vendor ID */ #endif + #ifndef PCI_DEVICE_ID_VORTEX_GDT60x0 /* GDT_PCI */ #define PCI_DEVICE_ID_VORTEX_GDT60x0 0 /* GDT6000/6020/6050 */ @@ -83,22 +85,44 @@ /* GDT_MPR, RP series, narrow/ultra SCSI */ #define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x104 /* GDT6111RP/GDT6511RP */ #define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x105 /* GDT6121RP/GDT6521RP */ -/* GDT_MPR, RP1 series, wide/ultra SCSI */ -#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1 0x110 /* GDT6117RP1/GDT6517RP1 */ -#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1 0x111 /* GDT6127RP1/GDT6527RP1 */ -#define PCI_DEVICE_ID_VORTEX_GDT6537RP1 0x112 /* GDT6537RP1 */ -#define PCI_DEVICE_ID_VORTEX_GDT6557RP1 0x113 /* GDT6557RP1 */ -/* GDT_MPR, RP1 series, narrow/ultra SCSI */ -#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1 0x114 /* GDT6111RP1/GDT6511RP1 */ -#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1 0x115 /* GDT6121RP1/GDT6521RP1 */ -/* GDT_MPR, RP2 series, wide/ultra SCSI */ -#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2 0x120 /* GDT6117RP2/GDT6517RP2 */ -#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2 0x121 /* GDT6127RP2/GDT6527RP2 */ -#define PCI_DEVICE_ID_VORTEX_GDT6537RP2 0x122 /* GDT6537RP2 */ -#define PCI_DEVICE_ID_VORTEX_GDT6557RP2 0x123 /* GDT6557RP2 */ -/* GDT_MPR, RP2 series, narrow/ultra SCSI */ -#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2 0x124 /* GDT6111RP2/GDT6511RP2 */ -#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2 0x125 /* GDT6121RP2/GDT6521RP2 */ +#endif +#ifndef PCI_DEVICE_ID_VORTEX_GDT6x17RD +/* GDT_MPR, RD series, wide/ultra SCSI */ +#define PCI_DEVICE_ID_VORTEX_GDT6x17RD 0x110 /* GDT6117RD/GDT6517RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x27RD 0x111 /* GDT6127RD/GDT6527RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6537RD 0x112 /* GDT6537RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6557RD 0x113 /* GDT6557RD */ +/* GDT_MPR, RD series, narrow/ultra SCSI */ +#define PCI_DEVICE_ID_VORTEX_GDT6x11RD 0x114 /* GDT6111RD/GDT6511RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x21RD 0x115 /* GDT6121RD/GDT6521RD */ +/* GDT_MPR, RD series, wide/ultra2 SCSI */ +#define PCI_DEVICE_ID_VORTEX_GDT6x18RD 0x118 /* GDT6118RD/GDT6518RD/ + GDT6618RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x28RD 0x119 /* GDT6128RD/GDT6528RD/ + GDT6628RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x38RD 0x11A /* GDT6538RD/GDT6638RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x58RD 0x11B /* GDT6558RD/GDT6658RD */ +/* GDT_MPR, RN series (64-bit PCI), wide/ultra2 SCSI */ +#define PCI_DEVICE_ID_VORTEX_GDT7x18RN 0x168 /* GDT7118RN/GDT7518RN/ + GDT7618RN */ +#define PCI_DEVICE_ID_VORTEX_GDT7x28RN 0x169 /* GDT7128RN/GDT7528RN/ + GDT7628RN */ +#define PCI_DEVICE_ID_VORTEX_GDT7x38RN 0x16A /* GDT7538RN/GDT7638RN */ +#define PCI_DEVICE_ID_VORTEX_GDT7x58RN 0x16B /* GDT7558RN/GDT7658RN */ +#endif + +#ifndef PCI_DEVICE_ID_VORTEX_GDT6x19RD +/* GDT_MPR, RD series, Fibre Channel */ +#define PCI_DEVICE_ID_VORTEX_GDT6x19RD 0x210 /* GDT6519RD/GDT6619RD */ +#define PCI_DEVICE_ID_VORTEX_GDT6x29RD 0x211 /* GDT6529RD/GDT6629RD */ +/* GDT_MPR, RN series (64-bit PCI), Fibre Channel */ +#define PCI_DEVICE_ID_VORTEX_GDT7x19RN 0x260 /* GDT7519RN/GDT7619RN */ +#define PCI_DEVICE_ID_VORTEX_GDT7x29RN 0x261 /* GDT7529RN/GDT7629RN */ +#endif + +#ifndef PCI_DEVICE_ID_VORTEX_GDTMAXRP +/* GDT_MPR, last device ID */ +#define PCI_DEVICE_ID_VORTEX_GDTMAXRP 0x2ff #endif /* limits */ @@ -106,12 +130,14 @@ #define GDTH_MAXCMDS 124 #define GDTH_MAXC_P_L 16 /* max. cmds per lun */ #define MAXOFFSETS 128 -#define MAXHA 8 -#define MAXID 8 +#define MAXHA 16 +#define MAXID 127 #define MAXLUN 8 -#define MAXBUS 5 +#define MAXBUS 6 #define MAX_HDRIVES 35 /* max. host drive count */ #define MAX_EVENTS 100 /* event buffer count */ +#define MAX_RES_ARGS 40 /* device reservation, + must be a multiple of 4 */ #define MAXCYLS 1024 #define HEADS 64 #define SECS 32 /* mapping 64*32 */ @@ -126,12 +152,6 @@ #define SCREEN_CMND ((Scsi_Cmnd *)-3) #define SPECIAL_SCP(p) (p==UNUSED_CMND || p==INTERNAL_CMND || p==SCREEN_CMND) -/* device types */ -#define EMPTY_DTYP 0 -#define CACHE_DTYP 1 -#define RAW_DTYP 2 -#define SIOP_DTYP 3 /* the SCSI processor */ - /* controller services */ #define SCSIRAWSERVICE 3 #define CACHESERVICE 9 @@ -144,14 +164,15 @@ #define MSG_REQUEST 0 /* async. event: message */ /* cacheservice defines */ -#define SECTOR_SIZE 0x200 /* always 512 bytes per sector */ +#define SECTOR_SIZE 0x200 /* always 512 bytes per sec. */ /* DPMEM constants */ +#define DPMEM_MAGIC 0xC0FFEE11 #define IC_HEADER_BYTES 48 #define IC_QUEUE_BYTES 4 #define DPMEM_COMMAND_OFFSET IC_HEADER_BYTES+IC_QUEUE_BYTES*MAXOFFSETS -/* service commands */ +/* cache/raw service commands */ #define GDT_INIT 0 /* service initialization */ #define GDT_READ 1 /* read command */ #define GDT_WRITE 2 /* write command */ @@ -163,16 +184,27 @@ #define GDT_UNMOUNT 11 /* unmount cache device */ #define GDT_SET_FEAT 12 /* set feat. (scatter/gather) */ #define GDT_GET_FEAT 13 /* get features */ -#define GDT_RESERVE 14 /* reserve dev. to raw service */ #define GDT_WRITE_THR 16 /* write through */ +#define GDT_READ_THR 17 /* read through */ #define GDT_EXT_INFO 18 /* extended info */ #define GDT_RESET 19 /* controller reset */ +/* additional raw service commands */ +#define GDT_RESERVE 14 /* reserve dev. to raw serv. */ +#define GDT_RELEASE 15 /* release device */ +#define GDT_RESERVE_ALL 16 /* reserve all devices */ +#define GDT_RELEASE_ALL 17 /* release all devices */ +#define GDT_RESET_BUS 18 /* reset bus */ +#define GDT_SCAN_START 19 /* start device scan */ +#define GDT_SCAN_END 20 /* stop device scan */ + /* IOCTL command defines */ #define SCSI_CHAN_CNT 5 /* subfunctions */ +#define GET_IOCHAN_DESC 0x5e #define L_CTRL_PATTERN 0x20000000L #define CACHE_INFO 4 #define CACHE_CONFIG 5 +#define BOARD_INFO 0x28 #define IO_CHANNEL 0x00020000L /* channels */ #define INVALID_CHANNEL 0x0000ffffL @@ -200,6 +232,7 @@ /* priorities */ #define DEFAULT_PRI 0x20 #define IOCTL_PRI 0x10 +#define HIGH_PRI 0x08 /* data directions */ #define DATA_IN 0x01000000L /* data from target */ @@ -211,7 +244,7 @@ #define SEMA0REG 0x0c8a /* command semaphore */ #define SEMA1REG 0x0c8b /* status semaphore */ #define LDOORREG 0x0c8d /* local doorbell */ -#define EDENABREG 0x0c8e /* EISA system doorbell enable */ +#define EDENABREG 0x0c8e /* EISA system doorbell enab. */ #define EDOORREG 0x0c8f /* EISA system doorbell */ #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ #define EISAREG 0x0cc0 /* EISA configuration */ @@ -221,119 +254,160 @@ #define SCATTER_GATHER 1 /* s/g feature */ #define GDTH_MAXSG 32 /* max. s/g elements */ #define SECS32 0x1f /* round capacity */ -#define BIOS_ID_OFFS 0x10 /* offset contr. ID in ISABIOS */ +#define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */ #define LOCALBOARD 0 /* board node always 0 */ #define ASYNCINDEX 0 /* cmd index async. event */ #define SPEZINDEX 1 /* cmd index unknown service */ #define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */ -/* typedefs */ - -#pragma pack(1) -typedef struct { - char buffer[GDTH_SCRATCH]; /* scratch buffer */ -} gdth_scratch_str; +/* typedefs */ +typedef u32 ulong32; +#define PACKED __attribute__((packed)) /* screenservice message */ typedef struct { - ulong msg_handle; /* message handle */ - ulong msg_len; /* size of message */ - ulong msg_alen; /* answer length */ + ulong32 msg_handle; /* message handle */ + ulong32 msg_len; /* size of message */ + ulong32 msg_alen; /* answer length */ unchar msg_answer; /* answer flag */ unchar msg_ext; /* more messages */ unchar msg_reserved[2]; char msg_text[MSGLEN+2]; /* the message text */ -} gdth_msg_str; +} PACKED gdth_msg_str; /* get channel count IOCTL */ typedef struct { - ulong channel_no; /* number of channel */ - ulong drive_cnt; /* number of drives */ + ulong32 channel_no; /* number of channel */ + ulong32 drive_cnt; /* number of drives */ unchar siop_id; /* SCSI processor ID */ unchar siop_state; /* SCSI processor state */ -} gdth_getch_str; +} PACKED gdth_getch_str; + +/* get raw channel count IOCTL (NEW!) */ +typedef struct { + ulong32 version; /* version of information (-1UL: newest) */ + unchar list_entries; /* list entry count */ + unchar first_chan; /* first channel number */ + unchar last_chan; /* last channel number */ + unchar chan_count; /* (R) channel count */ + ulong32 list_offset; /* offset of list[0] */ + struct { + unchar proc_id; /* processor id */ + unchar proc_defect; /* defect ? */ + unchar reserved[2]; + } PACKED list[MAXBUS]; +} PACKED gdth_iochan_str; /* cache info/config IOCTL */ typedef struct { - ulong version; /* firmware version */ + ulong32 version; /* firmware version */ ushort state; /* cache state (on/off) */ ushort strategy; /* cache strategy */ ushort write_back; /* write back state (on/off) */ ushort block_size; /* cache block size */ -} gdth_cpar_str; +} PACKED gdth_cpar_str; typedef struct { - ulong csize; /* cache size */ - ulong read_cnt; /* read/write counter */ - ulong write_cnt; - ulong tr_hits; /* hits */ - ulong sec_hits; - ulong sec_miss; /* misses */ -} gdth_cstat_str; + ulong32 csize; /* cache size */ + ulong32 read_cnt; /* read/write counter */ + ulong32 write_cnt; + ulong32 tr_hits; /* hits */ + ulong32 sec_hits; + ulong32 sec_miss; /* misses */ +} PACKED gdth_cstat_str; typedef struct { gdth_cpar_str cpar; gdth_cstat_str cstat; -} gdth_cinfo_str; +} PACKED gdth_cinfo_str; + +/* board info IOCTL */ +typedef struct { + ulong32 ser_no; /* serial no. */ + unchar oem_id[2]; /* OEM ID */ + ushort ep_flags; /* eprom flags */ + ulong32 proc_id; /* processor ID */ + ulong32 memsize; /* memory size (bytes) */ + unchar mem_banks; /* memory banks */ + unchar chan_type; /* channel type */ + unchar chan_count; /* channel count */ + unchar rdongle_pres; /* dongle present? */ + ulong32 epr_fw_ver; /* (eprom) firmware version */ + ulong32 upd_fw_ver; /* (update) firmware version */ + ulong32 upd_revision; /* update revision */ + char type_string[16]; /* controller name */ + char raid_string[16]; /* RAID firmware name */ + unchar update_pres; /* update present? */ + unchar xor_pres; /* XOR engine present? */ + unchar prom_type; /* ROM type (eprom/flash) */ + unchar prom_count; /* number of ROM devices */ + ulong32 dup_pres; /* duplexing module present? */ + ulong32 chan_pres; /* number of expansion chn. */ + ulong32 mem_pres; /* memory expansion inst. ? */ + unchar ft_bus_system; /* fault bus supported? */ + unchar subtype_valid; /* board_subtype valid? */ + unchar board_subtype; /* subtype/hardware level */ + unchar ramparity_pres; /* RAM parity check hardware? */ +} PACKED gdth_binfo_str; /* scatter/gather element */ typedef struct { - ulong sg_ptr; /* address */ - ulong sg_len; /* length */ -} gdth_sg_str; + ulong32 sg_ptr; /* address */ + ulong32 sg_len; /* length */ +} PACKED gdth_sg_str; /* command structure */ typedef struct { - ulong BoardNode; /* board node (always 0) */ - ulong CommandIndex; /* command number */ + ulong32 BoardNode; /* board node (always 0) */ + ulong32 CommandIndex; /* command number */ ushort OpCode; /* the command (READ,..) */ union { struct { ushort DeviceNo; /* number of cache drive */ - ulong BlockNo; /* block number */ - ulong BlockCnt; /* block count */ - ulong DestAddr; /* dest. addr. (if s/g: -1) */ - ulong sg_canz; /* s/g element count */ + ulong32 BlockNo; /* block number */ + ulong32 BlockCnt; /* block count */ + ulong32 DestAddr; /* dest. addr. (if s/g: -1) */ + ulong32 sg_canz; /* s/g element count */ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ - } cache; /* cache service cmd. str. */ + } PACKED cache; /* cache service cmd. str. */ struct { ushort param_size; /* size of p_param buffer */ - ulong subfunc; /* IOCTL function */ - ulong channel; /* device */ - ulong p_param; /* buffer */ - } ioctl; /* IOCTL command structure */ + ulong32 subfunc; /* IOCTL function */ + ulong32 channel; /* device */ + ulong32 p_param; /* buffer */ + } PACKED ioctl; /* IOCTL command structure */ struct { ushort reserved; - ulong msg_handle; /* message handle */ - ulong msg_addr; /* message buffer address */ - } screen; /* screen service cmd. str. */ + ulong32 msg_handle; /* message handle */ + ulong32 msg_addr; /* message buffer address */ + } PACKED screen; /* screen service cmd. str. */ struct { ushort reserved; - ulong direction; /* data direction */ - ulong mdisc_time; /* disc. time (0: no timeout)*/ - ulong mcon_time; /* connect time(0: no to.) */ - ulong sdata; /* dest. addr. (if s/g: -1) */ - ulong sdlen; /* data length (bytes) */ - ulong clen; /* SCSI cmd. length(6,10,12) */ + ulong32 direction; /* data direction */ + ulong32 mdisc_time; /* disc. time (0: no timeout)*/ + ulong32 mcon_time; /* connect time(0: no to.) */ + ulong32 sdata; /* dest. addr. (if s/g: -1) */ + ulong32 sdlen; /* data length (bytes) */ + ulong32 clen; /* SCSI cmd. length(6,10,12) */ unchar cmd[12]; /* SCSI command */ unchar target; /* target ID */ unchar lun; /* LUN */ unchar bus; /* SCSI bus number */ unchar priority; /* only 0 used */ - ulong sense_len; /* sense data length */ - ulong sense_data; /* sense data addr. */ + ulong32 sense_len; /* sense data length */ + ulong32 sense_data; /* sense data addr. */ struct raw *link_p; /* linked cmds (not supp.) */ - ulong sg_ranz; /* s/g element count */ + ulong32 sg_ranz; /* s/g element count */ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ - } raw; /* raw service cmd. struct. */ + } PACKED raw; /* raw service cmd. struct. */ } u; /* additional variables */ unchar Service; /* controller service */ ushort Status; /* command result */ - ulong Info; /* additional information */ + ulong32 Info; /* additional information */ Scsi_Cmnd *RequestBuffer; /* request buffer */ -} gdth_cmd_str; +} PACKED gdth_cmd_str; /* controller event structure */ #define ES_ASYNC 1 @@ -347,40 +421,40 @@ struct { ushort ionode; ushort service; - ulong index; - } driver; + ulong32 index; + } PACKED driver; struct { ushort ionode; ushort service; ushort status; - ulong info; + ulong32 info; unchar scsi_coord[3]; - } async; + } PACKED async; struct { ushort ionode; ushort service; ushort status; - ulong info; + ulong32 info; ushort hostdrive; unchar scsi_coord[3]; unchar sense_key; - } sync; + } PACKED sync; struct { - ulong l1, l2, l3, l4; - } test; + ulong32 l1, l2, l3, l4; + } PACKED test; } eu; -} gdth_evt_data; +} PACKED gdth_evt_data; typedef struct { - ulong first_stamp; - ulong last_stamp; + ulong32 first_stamp; + ulong32 last_stamp; ushort same_count; ushort event_source; ushort event_idx; unchar application; unchar reserved; gdth_evt_data event_data; -} gdth_evt_str; +} PACKED gdth_evt_str; /* DPRAM structures */ @@ -390,32 +464,32 @@ unchar S_Cmd_Indx; /* special command */ unchar volatile S_Status; /* status special command */ ushort reserved1; - ulong S_Info[4]; /* add. info special command */ + ulong32 S_Info[4]; /* add. info special command */ unchar volatile Sema0; /* command semaphore */ unchar reserved2[3]; unchar Cmd_Index; /* command number */ unchar reserved3[3]; ushort volatile Status; /* command status */ ushort Service; /* service(for async.events) */ - ulong Info[2]; /* additional info */ + ulong32 Info[2]; /* additional info */ struct { ushort offset; /* command offs. in the DPRAM*/ ushort serv_id; /* service */ - } comm_queue[MAXOFFSETS]; /* command queue */ - ulong bios_reserved[2]; + } PACKED comm_queue[MAXOFFSETS]; /* command queue */ + ulong32 bios_reserved[2]; unchar gdt_dpr_cmd[1]; /* commands */ -} gdt_dpr_if; +} PACKED gdt_dpr_if; /* SRAM structure PCI controllers */ typedef struct { - ulong magic; /* controller ID from BIOS */ + ulong32 magic; /* controller ID from BIOS */ ushort need_deinit; /* switch betw. BIOS/driver */ unchar switch_support; /* see need_deinit */ unchar padding[9]; unchar os_used[16]; /* OS code per service */ unchar unused[28]; unchar fw_magic; /* contr. ID from firmware */ -} gdt_pci_sram; +} PACKED gdt_pci_sram; /* SRAM structure EISA controllers (but NOT GDT3000/3020) */ typedef struct { @@ -423,7 +497,7 @@ ushort need_deinit; /* switch betw. BIOS/driver */ unchar switch_support; /* see need_deinit */ unchar padding; -} gdt_eisa_sram; +} PACKED gdt_eisa_sram; /* DPRAM ISA controllers */ @@ -431,12 +505,12 @@ union { struct { unchar bios_used[0x3c00-32]; /* 15KB - 32Bytes BIOS */ - ulong magic; /* controller (EISA) ID */ + ulong32 magic; /* controller (EISA) ID */ ushort need_deinit; /* switch betw. BIOS/driver */ unchar switch_support; /* see need_deinit */ unchar padding[9]; unchar os_used[16]; /* OS code per service */ - } dp_sram; + } PACKED dp_sram; unchar bios_area[0x4000]; /* 16KB reserved for BIOS */ } bu; union { @@ -450,8 +524,8 @@ unchar irqdel; /* acknowledge board int. */ unchar volatile Sema1; /* status semaphore */ unchar rq; /* IRQ/DRQ configuration */ - } io; -} gdt2_dpram_str; + } PACKED io; +} PACKED gdt2_dpram_str; /* DPRAM PCI controllers */ typedef struct { @@ -470,8 +544,8 @@ unchar unused3[3]; unchar irqdel; /* acknowledge board int. */ unchar unused4[3]; - } io; -} gdt6_dpram_str; + } PACKED io; +} PACKED gdt6_dpram_str; /* PLX register structure (new PCI controllers) */ typedef struct { @@ -482,7 +556,7 @@ unchar unused2[2]; ushort volatile status; /* command status */ ushort service; /* service */ - ulong info[2]; /* additional info */ + ulong32 info[2]; /* additional info */ unchar unused3[0x10]; unchar ldoor_reg; /* PCI to local doorbell */ unchar unused4[3]; @@ -491,7 +565,7 @@ unchar control0; /* control0 register(unused) */ unchar control1; /* board interrupts enable */ unchar unused6[0x16]; -} gdt6c_plx_regs; +} PACKED gdt6c_plx_regs; /* DPRAM new PCI controllers */ typedef struct { @@ -500,7 +574,7 @@ unchar if_area[0x4000-sizeof(gdt_pci_sram)]; } u; gdt_pci_sram gdt6sr; /* SRAM structure */ -} gdt6c_dpram_str; +} PACKED gdt6c_dpram_str; /* i960 register structure (PCI MPR controllers) */ typedef struct { @@ -511,15 +585,15 @@ unchar unused3; ushort volatile status; /* command status */ ushort service; /* service */ - ulong info[2]; /* additional info */ + ulong32 info[2]; /* additional info */ unchar ldoor_reg; /* PCI to local doorbell */ unchar unused4[11]; unchar volatile edoor_reg; /* local to PCI doorbell */ unchar unused5[7]; unchar edoor_en_reg; /* board interrupts enable */ unchar unused6[27]; - ulong unused7[1004]; /* size: 4 KB */ -} gdt6m_i960_regs; + ulong32 unused7[1004]; /* size: 4 KB */ +} PACKED gdt6m_i960_regs; /* DPRAM PCI MPR controllers */ typedef struct { @@ -529,58 +603,71 @@ unchar if_area[0x3000-sizeof(gdt_pci_sram)]; } u; gdt_pci_sram gdt6sr; /* SRAM structure */ -} gdt6m_dpram_str; +} PACKED gdt6m_dpram_str; /* PCI resources */ typedef struct { - ushort device_id; /* device ID (0,..,9) */ - unchar bus; /* PCI bus */ - unchar device_fn; /* PCI device/function no. */ - ulong dpmem; /* DPRAM address */ - ulong io; /* IO address */ - ulong io_mm; /* IO address mem. mapped */ - ulong bios; /* BIOS address */ - unchar irq; /* IRQ */ +#if LINUX_VERSION_CODE >= 0x02015C + struct pci_dev *pdev; +#endif + ushort device_id; /* device ID (0,..,9) */ + unchar bus; /* PCI bus */ + unchar device_fn; /* PCI device/function no. */ + ulong dpmem; /* DPRAM address */ + ulong io; /* IO address */ + ulong io_mm; /* IO address mem. mapped */ + unchar irq; /* IRQ */ } gdth_pci_str; /* controller information structure */ typedef struct { - unchar bus_cnt; /* SCSI bus count */ - unchar type; /* controller class */ + ushort type; /* controller class */ ushort raw_feat; /* feat. raw service (s/g,..) */ - ulong stype; /* controller subtype */ + ulong32 stype; /* controller subtype */ ushort cache_feat; /* feat. cache serv. (s/g,..) */ - ushort bmic; /* BMIC address (EISA) */ - void *brd; /* DPRAM address */ - ulong brd_phys; /* slot number/BIOS address */ + ushort bmic; /* BMIC address (EISA) */ + void *brd; /* DPRAM address */ + ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ gdth_cmd_str *pccb; /* address command structure */ - gdth_scratch_str *pscratch; + char *pscratch; /* scratch (DMA) buffer */ + unchar scratch_busy; /* in use? */ + unchar scan_mode; /* current scan mode */ unchar irq; /* IRQ */ unchar drq; /* DRQ (ISA controllers) */ ushort status; /* command status */ - ulong info; - ulong info2; /* additional info */ + ulong32 info; + ulong32 info2; /* additional info */ Scsi_Cmnd *req_first; /* top of request queue */ struct { - unchar type; /* device type */ + unchar present; /* host drive present? */ + unchar lock; /* drive locked? (hot plug) */ unchar heads; /* mapping */ unchar secs; - unchar lock; /* drive locked ? (hot plug) */ - ushort hostdrive; /* host drive number */ ushort devtype; /* further information */ - ulong size; /* capacity */ - } id[MAXBUS][MAXID]; + ulong32 size; /* capacity */ + } hdr[MAXID]; /* host drives */ + struct { + unchar lock; /* channel locked? (hot plug) */ + } raw[MAXBUS]; /* raw devices */ + struct { + Scsi_Cmnd *cmnd; /* pending request */ + ushort service; /* service */ + } cmd_tab[GDTH_MAXCMDS]; /* table of pend. requests */ + unchar bus_cnt; /* SCSI bus count */ + unchar tid_cnt; /* Target ID count */ + unchar bus_id[MAXBUS]; /* IOP IDs */ ushort cmd_cnt; /* command count in DPRAM */ ushort cmd_len; /* length of actual command */ ushort cmd_offs_dpmem; /* actual offset in DPRAM */ ushort ic_all_size; /* sizeof DPRAM interf. area */ - unchar reserved; - unchar mode; /* information from /proc */ - ushort param_size; gdth_cpar_str cpar; /* controller cache par. */ + char ctr_name[16]; /* controller name */ +#if LINUX_VERSION_CODE >= 0x02015F + spinlock_t smp_lock; +#endif } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ @@ -594,7 +681,6 @@ gdth_num_str numext; /* must be the first element */ gdth_ha_str haext; gdth_cmd_str cmdext; - gdth_scratch_str dmaext; } gdth_ext_str; @@ -611,27 +697,27 @@ unchar vendor[8]; unchar product[16]; unchar revision[4]; -} gdth_inq_data; +} PACKED gdth_inq_data; /* READ_CAPACITY data format */ typedef struct { - ulong last_block_no; - ulong block_length; -} gdth_rdcap_data; + ulong32 last_block_no; + ulong32 block_length; +} PACKED gdth_rdcap_data; /* REQUEST_SENSE data format */ typedef struct { unchar errorcode; unchar segno; unchar key; - ulong info; + ulong32 info; unchar add_length; - ulong cmd_info; + ulong32 cmd_info; unchar adsc; unchar adsq; unchar fruc; unchar key_spec[3]; -} gdth_sense_data; +} PACKED gdth_sense_data; /* MODE_SENSE data format */ typedef struct { @@ -640,20 +726,20 @@ unchar med_type; unchar dev_par; unchar bd_length; - } hd; + } PACKED hd; struct { unchar dens_code; unchar block_count[3]; unchar reserved; unchar block_length[3]; - } bd; -} gdth_modep_data; + } PACKED bd; +} PACKED gdth_modep_data; +/* stack frame */ typedef struct { - ulong b[10]; /* 32 bit compiler ! */ -} gdth_stackframe; + ulong b[10]; /* 32/64 bit compiler ! */ +} PACKED gdth_stackframe; -#pragma pack() /* function prototyping */ @@ -669,27 +755,82 @@ #endif const char *gdth_info(struct Scsi_Host *); - +#if LINUX_VERSION_CODE >= 0x02015F int gdth_bios_param(Disk *,kdev_t,int *); extern struct proc_dir_entry proc_scsi_gdth; int gdth_proc_info(char *,char **,off_t,int,int,int); -#define GDTH { proc_dir: &proc_scsi_gdth, \ - proc_info: gdth_proc_info, \ - name: "GDT SCSI Disk Array Controller", \ - detect: gdth_detect, \ - release: gdth_release, \ - info: gdth_info, \ - command: gdth_command, \ - queuecommand: gdth_queuecommand, \ - abort: gdth_abort, \ - reset: gdth_reset, \ - bios_param: gdth_bios_param, \ - can_queue: GDTH_MAXCMDS, \ - this_id: -1, \ - sg_tablesize: GDTH_MAXSG, \ - cmd_per_lun: GDTH_MAXC_P_L, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING} +int gdth_eh_abort(Scsi_Cmnd *scp); +int gdth_eh_device_reset(Scsi_Cmnd *scp); +int gdth_eh_bus_reset(Scsi_Cmnd *scp); +int gdth_eh_host_reset(Scsi_Cmnd *scp); +#define GDTH { proc_dir: &proc_scsi_gdth, \ + proc_info: gdth_proc_info, \ + name: "GDT SCSI Disk Array Controller",\ + detect: gdth_detect, \ + release: gdth_release, \ + info: gdth_info, \ + command: gdth_command, \ + queuecommand: gdth_queuecommand, \ + eh_abort_handler: gdth_eh_abort, \ + eh_device_reset_handler: gdth_eh_device_reset, \ + eh_bus_reset_handler: gdth_eh_bus_reset, \ + eh_host_reset_handler: gdth_eh_host_reset, \ + abort: gdth_abort, \ + reset: gdth_reset, \ + bios_param: gdth_bios_param, \ + can_queue: GDTH_MAXCMDS, \ + this_id: -1, \ + sg_tablesize: GDTH_MAXSG, \ + cmd_per_lun: GDTH_MAXC_P_L, \ + present: 0, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* use new error code */ } +#elif LINUX_VERSION_CODE >= 0x010300 +int gdth_bios_param(Disk *,kdev_t,int *); +extern struct proc_dir_entry proc_scsi_gdth; +int gdth_proc_info(char *,char **,off_t,int,int,int); +#define GDTH { NULL, NULL, \ + &proc_scsi_gdth, \ + gdth_proc_info, \ + "GDT SCSI Disk Array Controller", \ + gdth_detect, \ + gdth_release, \ + gdth_info, \ + gdth_command, \ + gdth_queuecommand, \ + gdth_abort, \ + gdth_reset, \ + NULL, \ + gdth_bios_param, \ + GDTH_MAXCMDS, \ + -1, \ + GDTH_MAXSG, \ + GDTH_MAXC_P_L, \ + 0, \ + 1, \ + ENABLE_CLUSTERING} +#else +int gdth_bios_param(Disk *,int,int *); +#define GDTH { NULL, NULL, \ + "GDT SCSI Disk Array Controller", \ + gdth_detect, \ + gdth_release, \ + gdth_info, \ + gdth_command, \ + gdth_queuecommand, \ + gdth_abort, \ + gdth_reset, \ + NULL, \ + gdth_bios_param, \ + GDTH_MAXCMDS, \ + -1, \ + GDTH_MAXSG, \ + GDTH_MAXC_P_L, \ + 0, \ + 1, \ + ENABLE_CLUSTERING} +#endif #endif diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_ioctl.h linux/drivers/scsi/gdth_ioctl.h --- v2.2.0-pre6/linux/drivers/scsi/gdth_ioctl.h Tue Nov 4 09:17:30 1997 +++ linux/drivers/scsi/gdth_ioctl.h Mon Jan 11 10:17:20 1999 @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.1 1997/02/21 08:07:27 achim Exp $ + * $Id: gdth_ioctl.h,v 1.2 1998/12/17 15:42:49 achim Exp $ */ /* IOCTLs */ @@ -16,12 +16,12 @@ #define GDTIOCTL_LOCKCHN (GDTIOCTL_MASK | 7) /* lock channel */ #define GDTIOCTL_EVENT (GDTIOCTL_MASK | 8) /* read controller events */ -#define GDTIOCTL_MAGIC 0x06030f07UL +#define GDTIOCTL_MAGIC 0xaffe0001UL /* IOCTL structure (write) */ typedef struct { - ulong magic; /* IOCTL magic */ + ulong32 magic; /* IOCTL magic */ ushort ioctl; /* IOCTL */ ushort ionode; /* controller number */ ushort service; /* controller service */ @@ -43,14 +43,15 @@ struct { int erase; /* erase event ? */ int handle; + unchar evt[34]; /* event structure */ } event; } iu; } gdth_iowr_str; /* IOCTL structure (read) */ typedef struct { - ulong size; /* buffer size */ - ulong status; /* IOCTL error code */ + ulong32 size; /* buffer size */ + ulong32 status; /* IOCTL error code */ union { struct { unchar data[1]; /* data */ @@ -76,7 +77,7 @@ } ctrcnt; struct { int handle; - unchar evt[32]; /* event structure */ + unchar evt[34]; /* event structure */ } event; } iu; } gdth_iord_str; diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c --- v2.2.0-pre6/linux/drivers/scsi/gdth_proc.c Mon Feb 23 18:12:07 1998 +++ linux/drivers/scsi/gdth_proc.c Mon Jan 11 10:17:20 1999 @@ -1,5 +1,5 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.6 1997/10/31 10:36:24 achim Exp $ + * $Id: gdth_proc.c,v 1.11 1998/12/17 15:52:35 achim Exp $ */ #include "gdth_ioctl.h" @@ -10,7 +10,7 @@ int hanum,busnum,i; TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n", - length,hostno,offset,inout)); + length,hostno,(int)offset,inout)); for (i=0; ihost_no == hostno) @@ -69,7 +69,7 @@ { int orig_length, drive, wb_mode; char cmnd[12]; - int i, j, found; + int i, found; gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; @@ -96,28 +96,28 @@ } else { printk("GDT: Flushing all host drives .. "); } - for (i = 0; i < MAXBUS; ++i) { - for (j = 0; j < MAXID; ++j) { - if (ha->id[i][j].type == CACHE_DTYP) { - if (drive != -1 && - ha->id[i][j].hostdrive != (ushort)drive) - continue; - found = TRUE; - gdtcmd.BoardNode = LOCALBOARD; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; - { - struct semaphore sem = MUTEX_LOCKED; - scp.request.rq_status = RQ_SCSI_BUSY; - scp.request.sem = &sem; - scsi_do_cmd(&scp, cmnd, &gdtcmd, - sizeof(gdth_cmd_str), gdth_scsi_done, - 30*HZ, 1); - down(&sem); - } + for (i = 0; i < MAX_HDRIVES; ++i) { + if (ha->hdr[i].present) { + if (drive != -1 && i != drive) + continue; + found = TRUE; + gdtcmd.BoardNode = LOCALBOARD; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_FLUSH; + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + { + struct semaphore sem = MUTEX_LOCKED; + scp.request.rq_status = RQ_SCSI_BUSY; + scp.request.sem = &sem; + scp.SCp.this_residual = IOCTL_PRI; + GDTH_LOCK_SCSI_DOCMD(); + scsi_do_cmd(&scp, cmnd, &gdtcmd, + sizeof(gdth_cmd_str), gdth_scsi_done, + 30*HZ, 1); + GDTH_UNLOCK_SCSI_DOCMD(); + down(&sem); } } } @@ -179,8 +179,11 @@ struct semaphore sem = MUTEX_LOCKED; scp.request.rq_status = RQ_SCSI_BUSY; scp.request.sem = &sem; + scp.SCp.this_residual = IOCTL_PRI; + GDTH_LOCK_SCSI_DOCMD(); scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str), gdth_scsi_done, 30*HZ, 1); + GDTH_UNLOCK_SCSI_DOCMD(); down(&sem); } kfree( pcpar ); @@ -195,15 +198,13 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) { char cmnd[12]; - int id; - unchar i, j, k, found; + unchar i, j; gdth_ha_str *ha; gdth_iowr_str *piowr; gdth_iord_str *piord; gdth_cmd_str *pcmd; - ulong *ppadd; - ulong add_size, flags; - + ulong32 *ppadd, add_size; + ulong flags; TRACE2(("gdth_set_bin_info() ha %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); @@ -228,7 +229,7 @@ add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE; if (ha->cache_feat & SCATTER_GATHER) { ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr; - pcmd->u.cache.DestAddr = -1UL; + pcmd->u.cache.DestAddr = 0xffffffff; pcmd->u.cache.sg_lst[0].sg_len = add_size; pcmd->u.cache.sg_canz = 1; } else { @@ -239,7 +240,7 @@ add_size = pcmd->u.raw.sdlen; if (ha->raw_feat & SCATTER_GATHER) { ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr; - pcmd->u.raw.sdata = -1UL; + pcmd->u.raw.sdata = 0xffffffff; pcmd->u.raw.sg_lst[0].sg_len = add_size; pcmd->u.raw.sg_ranz = 1; } else { @@ -249,10 +250,9 @@ } else { return(-EINVAL); } - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str) + add_size; if (add_size > 0) { @@ -265,33 +265,33 @@ scp.request.rq_status = RQ_SCSI_BUSY; scp.request.sem = &sem; scp.SCp.this_residual = IOCTL_PRI; + GDTH_LOCK_SCSI_DOCMD(); scsi_do_cmd(&scp, cmnd, pcmd, sizeof(gdth_cmd_str), gdth_scsi_done, piowr->timeout*HZ, 1); + GDTH_UNLOCK_SCSI_DOCMD(); down(&sem); - piord->status = (ulong)scp.SCp.Message; + piord->status = (ulong32)scp.SCp.Message; } break; case GDTIOCTL_DRVERS: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION; break; case GDTIOCTL_CTRTYPE: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; if (ha->type == GDT_ISA || ha->type == GDT_EISA) { - piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 10); + piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10); } else if (ha->type != GDT_PCIMPR) { piord->iu.ctrtype.type = (unchar)((ha->stype<<8) + 6); } else { @@ -303,20 +303,18 @@ break; case GDTIOCTL_CTRCNT: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.ctrcnt.count = (ushort)gdth_ctr_count; break; case GDTIOCTL_OSVERS: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16); @@ -325,39 +323,24 @@ break; case GDTIOCTL_LOCKDRV: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; - for (i = k = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { - found = FALSE; - for (j = 0; j < ha->bus_cnt; ++j) { - for (k = 0; k < MAXID; ++k) { - if (ha->id[j][k].type == CACHE_DTYP && - ha->id[j][k].hostdrive == piowr->iu.lockdrv.drives[i]) { - found = TRUE; - break; - } - } - if (found) - break; - } - if (!found) + piord = (gdth_iord_str *)ha->pscratch; + for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { + j = piowr->iu.lockdrv.drives[i]; + if (j >= MAX_HDRIVES || !ha->hdr[j].present) continue; - if (piowr->iu.lockdrv.lock) { - save_flags( flags ); - cli(); - ha->id[j][k].lock = 1; - restore_flags( flags ); - gdth_wait_completion( hanum, j, k ); - gdth_stop_timeout( hanum, j, k ); + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + gdth_wait_completion( hanum, ha->bus_cnt, j ); + gdth_stop_timeout( hanum, ha->bus_cnt, j ); } else { - save_flags( flags ); - cli(); - ha->id[j][k].lock = 0; - restore_flags( flags ); - gdth_start_timeout( hanum, j, k ); + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + gdth_start_timeout( hanum, ha->bus_cnt, j ); gdth_next( hanum ); } } @@ -366,46 +349,54 @@ break; case GDTIOCTL_LOCKCHN: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - for (k = 0, j = piowr->iu.lockchn.channel; k < MAXID; ++k) { - if (ha->id[j][k].type != RAW_DTYP) - continue; - + i = piowr->iu.lockchn.channel; + if (i < ha->bus_cnt) { if (piowr->iu.lockchn.lock) { - save_flags( flags ); - cli(); - ha->id[j][k].lock = 1; - restore_flags( flags ); - gdth_wait_completion( hanum, j, k ); - gdth_stop_timeout( hanum, j, k ); + GDTH_LOCK_HA(ha, flags); + ha->raw[i].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + for (j = 0; j < ha->tid_cnt; ++j) { + gdth_wait_completion( hanum, i, j ); + gdth_stop_timeout( hanum, i, j ); + } } else { - save_flags( flags ); - cli(); - ha->id[j][k].lock = 0; - restore_flags( flags ); - gdth_start_timeout( hanum, j, k ); - gdth_next( hanum ); + GDTH_LOCK_HA(ha, flags); + ha->raw[i].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + for (j = 0; j < ha->tid_cnt; ++j) { + gdth_start_timeout( hanum, i, j ); + gdth_next( hanum ); + } } } - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; break; case GDTIOCTL_EVENT: - id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ); - if (id == -1) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) return(-EBUSY); - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; - if (piowr->iu.event.erase == 0) { - piord->iu.event.handle = gdth_read_event( piowr->iu.event.handle, - (gdth_evt_str *)piord->iu.event.evt ); + piord = (gdth_iord_str *)ha->pscratch; + if (piowr->iu.event.erase == 0xff) { + gdth_store_event(ha, + ((gdth_evt_str *)piowr->iu.event.evt)->event_source, + ((gdth_evt_str *)piowr->iu.event.evt)->event_idx, + &((gdth_evt_str *)piowr->iu.event.evt)->event_data); + if (((gdth_evt_str *)piowr->iu.event.evt)->event_source == ES_ASYNC) + gdth_log_event(&((gdth_evt_str *)piowr->iu.event.evt)->event_data); + } else if (piowr->iu.event.erase == 0xfe) { + gdth_clear_events(); + } else if (piowr->iu.event.erase == 0) { + piord->iu.event.handle = + gdth_read_event(ha,piowr->iu.event.handle, + (gdth_evt_str *)piord->iu.event.evt); } else { piord->iu.event.handle = piowr->iu.event.handle; - gdth_readapp_event( (unchar)piowr->iu.event.erase, - (gdth_evt_str *)piord->iu.event.evt ); + gdth_readapp_event(ha, (unchar)piowr->iu.event.erase, + (gdth_evt_str *)piord->iu.event.evt); } piord->size = sizeof(gdth_iord_str); piord->status = S_OK; @@ -415,7 +406,7 @@ return(-EINVAL); } /* we return a buffer ID to detect the right buffer during READ-IOCTL */ - return id; + return 1; } static int gdth_get_info(char *buffer,char **start,off_t offset, @@ -432,15 +423,15 @@ id = length; /* look for buffer ID in length */ - if (id > 4) { + if (id > 1) { #if LINUX_VERSION_CODE >= 0x020000 size = sprintf(buffer+len, - "%s SCSI Disk Array Controller\n", - gdth_ctr_name(hanum)); + "%s Disk Array Controller\n", + ha->ctr_name); #else size = sprintf(buffer+len, - "%s SCSI Disk Array Controller (SCSI Bus %d)\n", - gdth_ctr_name(hanum),busnum); + "%s Disk Array Controller (Bus %d)\n", + ha->ctr_name,busnum); #endif len += size; pos = begin + len; size = sprintf(buffer+len, @@ -457,12 +448,12 @@ goto stop_output; } else { - piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum]; + piord = (gdth_iord_str *)ha->pscratch; if (piord == NULL) goto stop_output; length = piord->size; memcpy(buffer+len, (char *)piord, length); - gdth_ioctl_free(hanum, id); + gdth_ioctl_free(hanum); len += length; pos = begin + len; if (pos < offset) { @@ -479,7 +470,7 @@ if (len > length) len = length; TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n", - len,pos,begin,offset,length,size)); + len,(int)pos,(int)begin,(int)offset,length,size)); return(len); } @@ -496,140 +487,152 @@ static int gdth_ioctl_alloc(int hanum, ushort size) { + gdth_ha_str *ha; ulong flags; - int i; + int ret_val; - if (size == 0) + if (size == 0 || size > GDTH_SCRATCH) return -1; - save_flags(flags); - cli(); + ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); - for (i = 0; i < 4; ++i) { - if (gdth_ioctl_tab[i][hanum] == NULL) { - gdth_ioctl_tab[i][hanum] = kmalloc( size, GFP_ATOMIC | GFP_DMA ); - break; - } - } + if (!ha->scratch_busy) { + ha->scratch_busy = TRUE; + ret_val = TRUE; + } else + ret_val = FALSE; - restore_flags(flags); - if (i == 4 || gdth_ioctl_tab[i][hanum] == NULL) - return -1; - return (i+1); + GDTH_UNLOCK_HA(ha, flags); + return ret_val; } -static void gdth_ioctl_free(int hanum, int idx) +static void gdth_ioctl_free(int hanum) { + gdth_ha_str *ha; ulong flags; - save_flags(flags); - cli(); + ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); - kfree( gdth_ioctl_tab[idx-1][hanum] ); - gdth_ioctl_tab[idx-1][hanum] = NULL; + ha->scratch_busy = FALSE; - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } static void gdth_wait_completion(int hanum, int busnum, int id) { + gdth_ha_str *ha; ulong flags; int i; Scsi_Cmnd *scp; - save_flags(flags); - cli(); + ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { - scp = gdth_cmd_tab[i][hanum].cmnd; - if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && + scp = ha->cmd_tab[i].cmnd; #if LINUX_VERSION_CODE >= 0x020000 + if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && scp->channel == (unchar)busnum) #else + if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && NUMDATA(scp->host)->busnum == (unchar)busnum) #endif { - restore_flags(flags); + scp->SCp.have_data_in = 0; + GDTH_UNLOCK_HA(ha, flags); while (!scp->SCp.have_data_in) barrier(); - save_flags(flags); - cli(); + GDTH_LOCK_SCSI_DONE(flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(flags); + GDTH_LOCK_HA(ha, flags); } } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } static void gdth_stop_timeout(int hanum, int busnum, int id) { + gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; - gdth_ha_str *ha; - save_flags(flags); - cli(); ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - if (scp->target == (unchar)id && #if LINUX_VERSION_CODE >= 0x020000 + if (scp->target == (unchar)id && scp->channel == (unchar)busnum) #else + if (scp->target == (unchar)id && NUMDATA(scp->host)->busnum == (unchar)busnum) #endif { TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(scp, 0); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } static void gdth_start_timeout(int hanum, int busnum, int id) { + gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; - gdth_ha_str *ha; - save_flags(flags); - cli(); ha = HADATA(gdth_ctr_tab[hanum]); + GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - if (scp->target == (unchar)id && #if LINUX_VERSION_CODE >= 0x020000 + if (scp->target == (unchar)id && scp->channel == (unchar)busnum) #else + if (scp->target == (unchar)id && NUMDATA(scp->host)->busnum == (unchar)busnum) #endif { TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(scp, scp->SCp.buffers_residual); + gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); } } - restore_flags(flags); + GDTH_UNLOCK_HA(ha, flags); } -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout) +static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout) { - ulong flags; int oldto; - save_flags(flags); - cli(); + oldto = scp->timeout_per_command; + scp->timeout_per_command = timeout; - oldto = scp->timeout; - scp->timeout = timeout; +#if LINUX_VERSION_CODE >= 0x02014B + if (timeout == 0) { + del_timer(&scp->eh_timeout); + scp->eh_timeout.data = (unsigned long) NULL; + scp->eh_timeout.expires = 0; + } else { + if (scp->eh_timeout.data != (unsigned long) NULL) + del_timer(&scp->eh_timeout); + scp->eh_timeout.data = (unsigned long) scp; + scp->eh_timeout.expires = jiffies + timeout; + add_timer(&scp->eh_timeout); + } +#else if (timeout > 0) { - if (timer_table[GDTH_TIMER].expires == 0) { - timer_table[GDTH_TIMER].expires = jiffies + timeout; - timer_active |= 1 << GDTH_TIMER; + if (timer_table[SCSI_TIMER].expires == 0) { + timer_table[SCSI_TIMER].expires = jiffies + timeout; + timer_active |= 1 << SCSI_TIMER; } else { - if (jiffies + timeout < timer_table[GDTH_TIMER].expires) - timer_table[GDTH_TIMER].expires = jiffies + timeout; + if (jiffies + timeout < timer_table[SCSI_TIMER].expires) + timer_table[SCSI_TIMER].expires = jiffies + timeout; } } +#endif - restore_flags(flags); return oldto; } - diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_proc.h linux/drivers/scsi/gdth_proc.h --- v2.2.0-pre6/linux/drivers/scsi/gdth_proc.h Tue Nov 4 09:17:30 1997 +++ linux/drivers/scsi/gdth_proc.h Mon Jan 11 10:17:20 1999 @@ -2,7 +2,7 @@ #define _GDTH_PROC_H /* gdth_proc.h - * $Id: gdth_proc.h,v 1.2 1997/02/21 08:08:51 achim Exp $ + * $Id: gdth_proc.h,v 1.5 1998/12/17 15:43:53 achim Exp $ */ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum); @@ -12,11 +12,11 @@ int length,int vh,int hanum,int busnum); static int gdth_ioctl_alloc(int hanum, ushort size); -static void gdth_ioctl_free(int hanum, int id); +static void gdth_ioctl_free(int hanum); static void gdth_wait_completion(int hanum, int busnum, int id); static void gdth_stop_timeout(int hanum, int busnum, int id); static void gdth_start_timeout(int hanum, int busnum, int id); -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout); +static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout); void gdth_scsi_done(Scsi_Cmnd *scp); diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/i91uscsi.c linux/drivers/scsi/i91uscsi.c --- v2.2.0-pre6/linux/drivers/scsi/i91uscsi.c Mon Dec 28 15:00:52 1998 +++ linux/drivers/scsi/i91uscsi.c Sun Jan 10 22:27:27 1999 @@ -71,6 +71,7 @@ 12/13/98 bv, Use spinlocks instead of cli() for serialized access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail members of the HCS structure. + 01/09/98 bv, Fix a deadlock on SMP system. **********************************************************************/ #define DEBUG_INTERRUPT 0 @@ -221,20 +222,9 @@ unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - /* - * We need to release the io_request_lock - * to make sure that the jiffies are updated - */ - spin_unlock_irq(&io_request_lock); - while (time_before_eq(jiffies, the_time)); - - /* - * Acquire the io_request_lock again - */ - spin_lock_irq(&io_request_lock); #else - while (time_before(jiffies, the_time)); + while (jiffies < the_time); #endif } @@ -1037,8 +1027,17 @@ if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#endif + tulip_main(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#endif + pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); @@ -1176,8 +1175,17 @@ if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#endif + tulip_main(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#endif + pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); @@ -1230,8 +1238,16 @@ /* disable Jasmin SCSI Int */ pCurHcb->HCS_Semaph = 0; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#endif + tulip_main(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#endif + pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); } @@ -1274,8 +1290,16 @@ #endif tul_post_scsi_rst(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#endif + tulip_main(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#endif + pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) @@ -1311,7 +1335,15 @@ /* disable Jasmin SCSI Int */ pCurHcb->HCS_Semaph = 0; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#endif + tulip_main(pCurHcb); + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#endif pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c --- v2.2.0-pre6/linux/drivers/scsi/imm.c Mon Jan 4 15:08:17 1999 +++ linux/drivers/scsi/imm.c Sat Jan 9 19:16:43 1999 @@ -328,7 +328,7 @@ if (k) return (r & 0xb8); - /* Counter expired - Time out occured */ + /* Counter expired - Time out occurred */ imm_fail(host_no, DID_TIME_OUT); printk("imm timeout in imm_wait\n"); return 0; /* command timed out */ @@ -943,7 +943,7 @@ unsigned char l = 0, h = 0; int retv, x; - /* First check for any errors that may of occured + /* First check for any errors that may of occurred * Here we check for internal errors */ if (tmp->failed) diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c --- v2.2.0-pre6/linux/drivers/scsi/ini9100u.c Tue Dec 22 14:16:56 1998 +++ linux/drivers/scsi/ini9100u.c Sun Jan 10 22:27:27 1999 @@ -93,6 +93,8 @@ * - Remove cli() locking for kernels >= 2.1.95. This uses * spinlocks to serialize access to the pSRB_head and * pSRB_tail members of the HCS structure. + * 09/01/99 bv - v1.03d + * - Fixed a deadlock problem in SMP. **************************************************************************/ #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) @@ -173,7 +175,7 @@ char *i91uCopyright = "Copyright (C) 1996-98"; char *i91uInitioName = "by Initio Corporation"; char *i91uProductName = "INI-9X00U/UW"; -char *i91uVersion = "v1.03b"; +char *i91uVersion = "v1.03d"; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) struct proc_dir_entry proc_scsi_ini9100u = diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h --- v2.2.0-pre6/linux/drivers/scsi/ini9100u.h Tue Dec 22 14:16:56 1998 +++ linux/drivers/scsi/ini9100u.h Mon Jan 11 10:36:18 1999 @@ -88,7 +88,7 @@ extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */ #endif -#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03b" +#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03d" #if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0) #define INI9100U { \ diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.2.0-pre6/linux/drivers/scsi/megaraid.c Tue Dec 22 14:16:56 1998 +++ linux/drivers/scsi/megaraid.c Sat Jan 9 19:16:43 1999 @@ -858,7 +858,7 @@ } /*-------------------------------------------------------------------- - * Initializes the adress of the controller's mailbox register + * Initializes the address of the controller's mailbox register * The mailbox register is used to issue commands to the card. * Format of the mailbox area: * 00 01 command diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c --- v2.2.0-pre6/linux/drivers/scsi/ppa.c Mon Jan 4 15:08:17 1999 +++ linux/drivers/scsi/ppa.c Sat Jan 9 19:16:43 1999 @@ -316,7 +316,7 @@ if (k) return (r & 0xf0); - /* Counter expired - Time out occured */ + /* Counter expired - Time out occurred */ ppa_fail(host_no, DID_TIME_OUT); printk("ppa timeout in ppa_wait\n"); return 0; /* command timed out */ @@ -804,7 +804,7 @@ unsigned char l = 0, h = 0; int retv; - /* First check for any errors that may of occured + /* First check for any errors that may of occurred * Here we check for internal errors */ if (tmp->failed) diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.2.0-pre6/linux/drivers/scsi/scsi.c Fri Jan 8 22:36:10 1999 +++ linux/drivers/scsi/scsi.c Mon Jan 11 09:56:56 1999 @@ -280,6 +280,8 @@ {"YAMAHA","CDR100","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"YAMAHA","CDR102","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN}, +{"IBM","DPES-","*", BLIST_NOTQ | BLIST_NOLUN}, +{"WDIGTL","WDE","*", BLIST_NOTQ | BLIST_NOLUN}, /* * Must be at end of list... */ diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v2.2.0-pre6/linux/drivers/scsi/scsi.h Thu Dec 31 10:29:01 1998 +++ linux/drivers/scsi/scsi.h Mon Jan 11 10:35:45 1999 @@ -317,7 +317,7 @@ #define IS_RESETTING 0x08 #define IS_ABORTING 0x10 #define ASKED_FOR_SENSE 0x20 - +#define SYNC_RESET 0x40 #if defined(__mc68000__) || defined(CONFIG_APUS) #include diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c --- v2.2.0-pre6/linux/drivers/scsi/scsi_obsolete.c Tue Dec 22 14:16:56 1998 +++ linux/drivers/scsi/scsi_obsolete.c Sun Jan 10 12:42:52 1999 @@ -23,6 +23,9 @@ * Major improvements to the timeout, abort, and reset processing, * as well as performance modifications for large queue depths by * Leonard N. Zubkoff + * + * Improved compatibility with 2.0 behaviour by Manfred Spraul + * */ /* @@ -354,6 +357,18 @@ printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result); #endif + if(SCpnt->flags & SYNC_RESET) + { + /* + * The behaviou of scsi_reset(SYNC) was changed in 2.1.? . + * The scsi mid-layer does a REDO after every sync reset, the driver + * must not do that any more. In order to prevent old drivers from + * crashing, all scsi_done() calls during sync resets are ignored. + */ + printk("scsi%d: device driver called scsi_done() " + "for a syncronous reset.\n", SCpnt->host->host_no); + return; + } if(SCpnt->flags & WAS_SENSE) { SCpnt->use_sg = SCpnt->old_use_sg; @@ -494,7 +509,7 @@ case RESERVATION_CONFLICT: printk("scsi%d, channel %d : RESERVATION CONFLICT performing" " reset.\n", SCpnt->host->host_no, SCpnt->channel); - scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); + scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); status = REDO; break; default: @@ -613,7 +628,7 @@ printk("scsi%d channel %d : resetting for second half of retries.\n", SCpnt->host->host_no, SCpnt->channel); scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); - break; + /* fall through to REDO */ } } else @@ -913,6 +928,8 @@ SCpnt->internal_timeout |= IN_RESET; update_timeout(SCpnt, RESET_TIMEOUT); + if (reset_flags & SCSI_RESET_SYNCHRONOUS) + SCpnt->flags |= SYNC_RESET; if (host->host_busy) { for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) @@ -969,6 +986,8 @@ host->last_reset = jiffies; if (!host->block) host->host_busy--; } + if (reset_flags & SCSI_RESET_SYNCHRONOUS) + SCpnt->flags &= ~SYNC_RESET; #ifdef DEBUG printk("scsi reset function returned %d\n", temp); diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/sound/lowlevel/README linux/drivers/sound/lowlevel/README --- v2.2.0-pre6/linux/drivers/sound/lowlevel/README Wed Aug 26 11:37:39 1998 +++ linux/drivers/sound/lowlevel/README Sat Jan 9 10:01:55 1999 @@ -2,7 +2,7 @@ ============================================ This directory contains additional low level sound drivers which -are not part of USS/Lite (Open Sound System). These drivers are +are not part of OSS/Lite (Open Sound System). These drivers are maintained by their authors (not by Hannu Savolainen). If you like to write a new low level sound driver, please contact diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c --- v2.2.0-pre6/linux/drivers/sound/wavfront.c Thu Jan 7 15:11:38 1999 +++ linux/drivers/sound/wavfront.c Sat Jan 9 19:16:43 1999 @@ -74,11 +74,29 @@ #include #include +#include + #include "sound_config.h" #include "soundmodule.h" #include +/* + * This sucks, hopefully it'll get standardised + */ + +#if defined(__alpha__) +#ifdef __SMP__ +#define LOOPS_PER_SEC cpu_data[smp_processor_id()].loops_per_sec +#else +#define LOOPS_PER_SEC loops_per_sec +#endif +#endif + +#if defined(__i386__) +#define LOOPS_PER_SEC current_cpu_data.loops_per_sec +#endif + #define MIDI_SYNTH_NAME "WaveFront MIDI" #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT #include "midi_synth.h" @@ -440,7 +458,7 @@ if (short_loop_cnt == 0) { short_loop_cnt = wait_usecs * - (current_cpu_data.loops_per_sec / 1000000); + (LOOPS_PER_SEC / 1000000); } /* Spin for a short period of time, because >99% of all diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- v2.2.0-pre6/linux/drivers/video/fbmem.c Fri Nov 27 13:09:27 1998 +++ linux/drivers/video/fbmem.c Sat Jan 9 19:16:43 1999 @@ -22,9 +22,7 @@ #include #include #include -#ifdef CONFIG_PROC_FS #include -#endif #ifdef CONFIG_KMOD #include #endif @@ -205,7 +203,6 @@ return MINOR(current->tty->device) - 1; } -#ifdef CONFIG_PROC_FS static int fbmem_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *private) { @@ -220,7 +217,6 @@ *start = buf + offset; return len > offset ? len - offset : 0; } -#endif static ssize_t fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) @@ -583,20 +579,16 @@ return 0; } -#ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_fbmem; -#endif __initfunc(void fbmem_init(void)) { int i; -#ifdef CONFIG_PROC_FS proc_fbmem = create_proc_entry("fb", 0, 0); if (proc_fbmem) proc_fbmem->read_proc = fbmem_read_proc; -#endif if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c --- v2.2.0-pre6/linux/drivers/video/mdacon.c Sun Nov 8 14:03:04 1998 +++ linux/drivers/video/mdacon.c Tue Jan 12 14:03:22 1999 @@ -331,7 +331,7 @@ mda_type_name = "MDA"; if (! mda_detect()) { - printk("mdacon: MDA card not detected."); + printk("mdacon: MDA card not detected.\n"); return NULL; } diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c --- v2.2.0-pre6/linux/drivers/video/retz3fb.c Tue Dec 22 14:16:57 1998 +++ linux/drivers/video/retz3fb.c Sat Jan 9 19:16:43 1999 @@ -757,7 +757,7 @@ reg_w(regs, VDAC_MASK, 0xff); /* - * Extended palette adressing ??? + * Extended palette addressing ??? */ switch (bpp){ case 8: diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h --- v2.2.0-pre6/linux/fs/autofs/autofs_i.h Thu Nov 19 09:56:28 1998 +++ linux/fs/autofs/autofs_i.h Mon Jan 11 15:03:30 1999 @@ -92,10 +92,6 @@ #define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) -#ifndef END_OF_TIME -#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) -#endif - #define AUTOFS_SBI_MAGIC 0x6d4a556d struct autofs_sb_info { @@ -111,6 +107,11 @@ u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; }; +extern inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) +{ + return (struct autofs_sb_info *)(sb->u.generic_sbp); +} + /* autofs_oz_mode(): do we see the man behind the curtain? (The processes which do manipulations for us in user space sees the raw filesystem without "magic".) */ @@ -126,6 +127,7 @@ void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); void autofs_hash_delete(struct autofs_dir_ent *); struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *); +void autofs_hash_dputall(struct autofs_dirhash *); void autofs_hash_nuke(struct autofs_dirhash *); /* Expiration-handling functions */ diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c --- v2.2.0-pre6/linux/fs/autofs/dirhash.c Sun Nov 8 14:03:04 1998 +++ linux/fs/autofs/dirhash.c Mon Jan 11 15:03:30 1999 @@ -47,7 +47,7 @@ ent = dh->expiry_head.exp_next; - if ( ent == &(dh->expiry_head) ) + if ( ent == &(dh->expiry_head) || sbi->catatonic ) return NULL; /* No entries */ while ( jiffies - ent->last_usage >= timeout ) { @@ -62,8 +62,10 @@ dentry = ent->dentry; if ( !dentry ) { + /* Should only happen in catatonic mode */ printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name); autofs_delete_usage(ent); + continue; } if ( !dentry->d_inode ) { @@ -200,6 +202,23 @@ *ptr = ((bucket+1) << 16) + ecount; return ent; +} + +/* Iterate over all the ents, and remove all dentry pointers. Used on + entering catatonic mode, in order to make the filesystem unmountable. */ +void autofs_hash_dputall(struct autofs_dirhash *dh) +{ + int i; + struct autofs_dir_ent *ent, *nent; + + for ( i = 0 ; i < AUTOFS_HASH_SIZE ; i++ ) { + for ( ent = dh->h[i] ; ent ; ent = ent->next ) { + if ( ent->dentry ) { + dput(ent->dentry); + ent->dentry = NULL; + } + } + } } /* Delete everything. This is used on filesystem destruction, so we diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.2.0-pre6/linux/fs/autofs/inode.c Tue Dec 22 14:16:57 1998 +++ linux/fs/autofs/inode.c Mon Jan 11 15:03:30 1999 @@ -34,8 +34,7 @@ static void autofs_put_super(struct super_block *sb) { - struct autofs_sb_info *sbi = - (struct autofs_sb_info *) sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(sb); unsigned int n; if ( !sbi->catatonic ) @@ -297,8 +296,7 @@ { ino_t ino = inode->i_ino; unsigned int n; - struct autofs_sb_info *sbi = - (struct autofs_sb_info *) inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); /* Initialize to the default case (stub directory) */ diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.2.0-pre6/linux/fs/autofs/root.c Tue Dec 22 14:16:57 1998 +++ linux/fs/autofs/root.c Mon Jan 11 15:03:30 1999 @@ -68,13 +68,15 @@ { struct autofs_dir_ent *ent = NULL; struct autofs_dirhash *dirhash; + struct autofs_sb_info *sbi; struct inode * inode = filp->f_dentry->d_inode; off_t onr, nr; if (!inode || !S_ISDIR(inode->i_mode)) return -ENOTDIR; - dirhash = &((struct autofs_sb_info *)inode->i_sb->u.generic_sbp)->dirhash; + sbi = autofs_sbi(inode->i_sb); + dirhash = &sbi->dirhash; nr = filp->f_pos; switch(nr) @@ -168,12 +170,10 @@ */ static int autofs_revalidate(struct dentry * dentry) { - struct autofs_sb_info *sbi; struct inode * dir = dentry->d_parent->d_inode; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dir_ent *ent; - sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; - /* Pending dentry */ if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) { if (autofs_oz_mode(sbi)) @@ -220,7 +220,7 @@ if (!S_ISDIR(dir->i_mode)) return -ENOTDIR; - sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + sbi = autofs_sbi(dir->i_sb); oz_mode = autofs_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", @@ -267,7 +267,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; @@ -338,7 +338,7 @@ */ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; @@ -365,7 +365,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; @@ -393,7 +393,7 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; ino_t ino; @@ -492,8 +492,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct autofs_sb_info *sbi = - (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c --- v2.2.0-pre6/linux/fs/autofs/waitq.c Mon Dec 28 15:00:52 1998 +++ linux/fs/autofs/waitq.c Mon Jan 11 15:03:30 1999 @@ -41,6 +41,7 @@ wq = nwq; } fput(sbi->pipe); /* Close the pipe */ + autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ } static int autofs_write(struct file *file, const void *addr, int bytes) diff -u --recursive --new-file v2.2.0-pre6/linux/fs/nls/Config.in linux/fs/nls/Config.in --- v2.2.0-pre6/linux/fs/nls/Config.in Tue Dec 22 14:16:57 1998 +++ linux/fs/nls/Config.in Sat Jan 9 10:01:56 1999 @@ -25,20 +25,20 @@ tristate 'Codepage 862 (Hebrew)' CONFIG_NLS_CODEPAGE_862 tristate 'Codepage 863 (Canadian French)' CONFIG_NLS_CODEPAGE_863 tristate 'Codepage 864 (Arabic)' CONFIG_NLS_CODEPAGE_864 - tristate 'Codepage 865 (Nordic European)' CONFIG_NLS_CODEPAGE_865 + tristate 'Codepage 865 (Norwegian, Danish)' CONFIG_NLS_CODEPAGE_865 tristate 'Codepage 866 (Cyrillic/Russian)' CONFIG_NLS_CODEPAGE_866 tristate 'Codepage 869 (Greek)' CONFIG_NLS_CODEPAGE_869 tristate 'Codepage 874 (Thai)' CONFIG_NLS_CODEPAGE_874 tristate 'NLS ISO 8859-1 (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1 - tristate 'NLS ISO 8859-2 (Latin 2; Slavic/Central European)' CONFIG_NLS_ISO8859_2 + tristate 'NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)' CONFIG_NLS_ISO8859_2 tristate 'NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)' CONFIG_NLS_ISO8859_3 tristate 'NLS ISO 8859-4 (Latin 4; Estonian, Latvian, Lithuanian)' CONFIG_NLS_ISO8859_4 tristate 'NLS ISO 8859-5 (Cyrillic)' CONFIG_NLS_ISO8859_5 tristate 'NLS ISO 8859-6 (Arabic)' CONFIG_NLS_ISO8859_6 tristate 'NLS ISO 8859-7 (Modern Greek)' CONFIG_NLS_ISO8859_7 tristate 'NLS ISO 8859-8 (Hebrew)' CONFIG_NLS_ISO8859_8 - tristate 'NLS ISO 8859-9 (Latin 5; Turkey)' CONFIG_NLS_ISO8859_9 - tristate 'NLS ISO 8859-15 (Latin 9; Western European with Euro)' CONFIG_NLS_ISO8859_15 + tristate 'NLS ISO 8859-9 (Latin 5; Turkish)' CONFIG_NLS_ISO8859_9 + tristate 'NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)' CONFIG_NLS_ISO8859_15 tristate 'NLS KOI8-R (Russian)' CONFIG_NLS_KOI8_R endmenu fi diff -u --recursive --new-file v2.2.0-pre6/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.2.0-pre6/linux/fs/proc/array.c Thu Jan 7 15:11:40 1999 +++ linux/fs/proc/array.c Fri Jan 8 22:54:17 1999 @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -372,28 +371,6 @@ i.freeswap >> 10); } -static int get_swapstats(char * buffer) -{ - unsigned long *w = swapstats.kswap_wakeups; - - return sprintf(buffer, - "ProcFreeTry: %8lu\n" - "ProcFreeSucc: %8lu\n" - "ProcShrinkTry: %8lu\n" - "ProcShrinkSucc: %8lu\n" - "KswapFreeTry: %8lu\n" - "KswapFreeSucc: %8lu\n" - "KswapWakeups: %8lu %lu %lu %lu\n", - swapstats.gfp_freepage_attempts, - swapstats.gfp_freepage_successes, - swapstats.gfp_shrink_attempts, - swapstats.gfp_shrink_successes, - swapstats.kswap_freepage_attempts, - swapstats.kswap_freepage_successes, - w[0], w[1], w[2], w[3] - ); -} - static int get_version(char * buffer) { extern char *linux_banner; @@ -1279,9 +1256,6 @@ case PROC_MEMINFO: return get_meminfo(page); - - case PROC_SWAPSTATS: - return get_swapstats(page); #ifdef CONFIG_PCI_OLD_PROC case PROC_PCI: diff -u --recursive --new-file v2.2.0-pre6/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.2.0-pre6/linux/fs/proc/root.c Tue Dec 22 14:16:57 1998 +++ linux/fs/proc/root.c Fri Jan 8 22:54:17 1999 @@ -493,11 +493,6 @@ S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; -static struct proc_dir_entry proc_root_swapstats = { - PROC_SWAPSTATS, 9, "swapstats", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations -}; static struct proc_dir_entry proc_root_kmsg = { PROC_KMSG, 4, "kmsg", S_IFREG | S_IRUSR, 1, 0, 0, @@ -653,7 +648,6 @@ proc_register(&proc_root, &proc_root_loadavg); proc_register(&proc_root, &proc_root_uptime); proc_register(&proc_root, &proc_root_meminfo); - proc_register(&proc_root, &proc_root_swapstats); proc_register(&proc_root, &proc_root_kmsg); proc_register(&proc_root, &proc_root_version); proc_register(&proc_root, &proc_root_cpuinfo); diff -u --recursive --new-file v2.2.0-pre6/linux/fs/select.c linux/fs/select.c --- v2.2.0-pre6/linux/fs/select.c Fri Nov 27 13:09:28 1998 +++ linux/fs/select.c Sun Jan 10 10:22:34 1999 @@ -221,6 +221,10 @@ || (ret = __get_user(usec, &tvp->tv_usec))) goto out_nofds; + ret = -EINVAL; + if (sec < 0 || usec < 0) + goto out_nofds; + if ((unsigned long) sec < MAX_SELECT_SECONDS) { timeout = ROUND_UP(usec, 1000000/HZ); timeout += sec * (unsigned long) HZ; @@ -331,10 +335,13 @@ if (nfds > NR_OPEN) goto out; - if (timeout < 0) - timeout = MAX_SCHEDULE_TIMEOUT; - else if (timeout) - timeout = (timeout*HZ+999)/1000+1; + if (timeout) { + /* Carefula about overflow in the intermediate values */ + if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ) + timeout = (timeout*HZ+999)/1000+1; + else /* Negative or overflow */ + timeout = MAX_SCHEDULE_TIMEOUT; + } err = -ENOMEM; if (timeout) { diff -u --recursive --new-file v2.2.0-pre6/linux/fs/ufs/namei.c linux/fs/ufs/namei.c --- v2.2.0-pre6/linux/fs/ufs/namei.c Thu Jan 7 15:11:40 1999 +++ linux/fs/ufs/namei.c Fri Jan 8 22:54:18 1999 @@ -56,10 +56,10 @@ #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) /* - * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. + * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure. * - * Len <= UFS_MAXNAMLEN' is guaranteed by caller. - * De != NULL' is guaranteed by caller. + * len <= UFS_MAXNAMLEN' is guaranteed by caller. + * de != NULL' is guaranteed by caller. */ static inline int ufs_match (int len, const char * const name, struct ufs_dir_entry * de, unsigned flags, unsigned swab) diff -u --recursive --new-file v2.2.0-pre6/linux/fs/ufs/super.c linux/fs/ufs/super.c --- v2.2.0-pre6/linux/fs/ufs/super.c Fri Jan 8 22:36:14 1999 +++ linux/fs/ufs/super.c Fri Jan 8 22:54:18 1999 @@ -641,11 +641,14 @@ case UFS_FSSTABLE: UFSD(("fs is stable\n")) break; + case UFS_FSOSF1: + UFSD(("fs is DEC OSF/1\n")) + break; case UFS_FSACTIVE: printk("ufs_read_super: fs is active\n"); sb->s_flags |= MS_RDONLY; break; - case UFS_FSBAD: + case UFS_FSBAD: printk("ufs_read_super: fs is bad\n"); sb->s_flags |= MS_RDONLY; break; diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h --- v2.2.0-pre6/linux/include/asm-alpha/core_cia.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/core_cia.h Wed Jan 13 10:42:49 1999 @@ -328,7 +328,7 @@ { unsigned long w = __kernel_insbl(b, addr & 3); *(vuip) ((addr << 5) + CIA_IO + 0x00) = w; - wmb(); + mb(); } __EXTERN_INLINE unsigned int cia_inw(unsigned long addr) @@ -342,7 +342,7 @@ { unsigned long w = __kernel_inswl(b, addr & 3); *(vuip) ((addr << 5) + CIA_IO + 0x08) = w; - wmb(); + mb(); } __EXTERN_INLINE unsigned int cia_inl(unsigned long addr) @@ -353,7 +353,7 @@ __EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr) { *(vuip) ((addr << 5) + CIA_IO + 0x18) = b; - wmb(); + mb(); } diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h --- v2.2.0-pre6/linux/include/asm-alpha/core_mcpcia.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/core_mcpcia.h Sun Jan 10 09:59:59 1999 @@ -71,9 +71,7 @@ * */ -#define MCPCIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ -#define MCPCIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ -#define MCPCIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ +#define MCPCIA_MEM_MASK 0x07ffffff /* SPARSE Mem region mask is 27 bits */ #define MCPCIA_DMA_WIN_BASE_DEFAULT (2*1024*1024*1024U) #define MCPCIA_DMA_WIN_SIZE_DEFAULT (2*1024*1024*1024U) @@ -386,23 +384,10 @@ unsigned long hose = (addr >> 32) & 3; if (addr >= alpha_mv.sm_base_r1 - && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_R1_MASK) { - mask = MCPCIA_MEM_R1_MASK; + && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_MASK) { + mask = MCPCIA_MEM_MASK; base = MCPCIA_SPARSE(hose); } -#if 0 - /* FIXME FIXME FIXME: SPARSE_MEM_R2 and R3 are not defined? */ - else if (addr >= alpha_mv.sm_base_r2 - && addr <= alpha_mv.sm_base_r2 + MCPCIA_MEM_R2_MASK) { - mask = MCPCIA_MEM_R2_MASK; - base = MCPCIA_SPARSE_MEM_R2; - } - else if (addr >= alpha_mv.sm_base_r3 - && addr <= alpha_mv.sm_base_r3 + MCPCIA_MEM_R3_MASK) { - mask = MCPCIA_MEM_R3_MASK; - base = MCPCIA_SPARSE_MEM_R3; - } -#endif else { #if 0 @@ -462,8 +447,8 @@ unsigned long hose = (in_addr >> 32) & 3; unsigned long result, msb, work, temp; - msb = addr & 0xE0000000UL; - temp = addr & MCPCIA_MEM_R1_MASK; + msb = addr & ~MCPCIA_MEM_MASK; + temp = addr & MCPCIA_MEM_MASK; set_hae(msb); work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00); @@ -477,8 +462,8 @@ unsigned long hose = (in_addr >> 32) & 3; unsigned long result, msb, work, temp; - msb = addr & 0xE0000000UL; - temp = addr & MCPCIA_MEM_R1_MASK ; + msb = addr & ~MCPCIA_MEM_MASK; + temp = addr & MCPCIA_MEM_MASK ; set_hae(msb); work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08); @@ -492,8 +477,8 @@ unsigned long hose = (in_addr >> 32) & 3; unsigned long msb; - msb = addr & 0xE0000000; - addr &= MCPCIA_MEM_R1_MASK; + msb = addr & ~MCPCIA_MEM_MASK; + addr &= MCPCIA_MEM_MASK; set_hae(msb); *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101; @@ -505,8 +490,8 @@ unsigned long hose = (in_addr >> 32) & 3; unsigned long msb ; - msb = addr & 0xE0000000 ; - addr &= MCPCIA_MEM_R1_MASK ; + msb = addr & ~MCPCIA_MEM_MASK ; + addr &= MCPCIA_MEM_MASK ; set_hae(msb); *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001; diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h --- v2.2.0-pre6/linux/include/asm-alpha/core_polaris.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_polaris.h Sun Jan 10 09:59:59 1999 @@ -0,0 +1,239 @@ +#ifndef __ALPHA_POLARIS__H__ +#define __ALPHA_POLARIS__H__ + +#include +#include +#include + +/* + * POLARIS is the internal name for a core logic chipset which provides + * memory controller and PCI access for the 21164PC chip based systems. + * + * This file is based on: + * + * Polaris System Controller + * Device Functional Specification + * 22-Jan-98 + * Rev. 4.2 + * + */ + +/* Polaris memory regions */ +#define POLARIS_SPARSE_MEM_BASE (IDENT_ADDR + 0xf800000000) +#define POLARIS_DENSE_MEM_BASE (IDENT_ADDR + 0xf900000000) +#define POLARIS_SPARSE_IO_BASE (IDENT_ADDR + 0xf980000000) +#define POLARIS_SPARSE_CONFIG_BASE (IDENT_ADDR + 0xf9c0000000) +#define POLARIS_IACK_BASE (IDENT_ADDR + 0xf9f8000000) +#define POLARIS_DENSE_IO_BASE (IDENT_ADDR + 0xf9fc000000) +#define POLARIS_DENSE_CONFIG_BASE (IDENT_ADDR + 0xf9fe000000) + +/* The Polaris command/status registers live in PCI Config space for + * bus 0/device 0. As such, they may be bytes, words, or doublewords. + */ +#define POLARIS_W_VENID (POLARIS_DENSE_CONFIG_BASE) +#define POLARIS_W_DEVID (POLARIS_DENSE_CONFIG_BASE+2) +#define POLARIS_W_CMD (POLARIS_DENSE_CONFIG_BASE+4) +#define POLARIS_W_STATUS (POLARIS_DENSE_CONFIG_BASE+6) + +/* No HAE address. Polaris has no concept of an HAE, since it + * supports transfers of all sizes in dense space. + */ + +#define POLARIS_DMA_WIN_BASE_DEFAULT 0x80000000 /* fixed, 2G @ 2G */ +#define POLARIS_DMA_WIN_SIZE_DEFAULT 0x80000000 /* fixed, 2G @ 2G */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define POLARIS_DMA_WIN_BASE alpha_mv.dma_win_base +#define POLARIS_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define POLARIS_DMA_WIN_BASE POLARIS_DMA_WIN_BASE_DEFAULT +#define POLARIS_DMA_WIN_SIZE POLARIS_DMA_WIN_SIZE_DEFAULT +#endif + +/* + * Data structure for handling POLARIS machine checks: + */ +struct el_POLARIS_sysdata_mcheck { + u_long psc_status; + u_long psc_pcictl0; + u_long psc_pcictl1; + u_long psc_pcictl2; +}; + + #ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +__EXTERN_INLINE unsigned long polaris_virt_to_bus(void * address) +{ + return virt_to_phys(address) + POLARIS_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * polaris_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - POLARIS_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * POLARIS, the PCI/memory support chipset for the PCA56 (21164PC) + * processors, can use either a sparse address mapping scheme, or the + * so-called byte-word PCI address space, to get at PCI memory and I/O. + * + * However, we will support only the BWX form. + */ + +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int polaris_inb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE)); +} + +__EXTERN_INLINE void polaris_outb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_IO_BASE)); + mb(); +} + +__EXTERN_INLINE unsigned int polaris_inw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE)); +} + +__EXTERN_INLINE void polaris_outw(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_IO_BASE)); + mb(); +} + +__EXTERN_INLINE unsigned int polaris_inl(unsigned long addr) +{ + return *(vuip)(addr + POLARIS_DENSE_IO_BASE); +} + +__EXTERN_INLINE void polaris_outl(unsigned int b, unsigned long addr) +{ + *(vuip)(addr + POLARIS_DENSE_IO_BASE) = b; + mb(); +} + +/* + * Memory functions. Polaris allows all accesses (byte/word + * as well as long/quad) to be done through dense space. + * + * We will only support DENSE access via BWX insns. + */ + +__EXTERN_INLINE unsigned long polaris_readb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_MEM_BASE)); +} + +__EXTERN_INLINE unsigned long polaris_readw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_MEM_BASE)); +} + +__EXTERN_INLINE unsigned long polaris_readl(unsigned long addr) +{ + return *(vuip)(addr + POLARIS_DENSE_MEM_BASE); +} + +__EXTERN_INLINE unsigned long polaris_readq(unsigned long addr) +{ + return *(vulp)(addr + POLARIS_DENSE_MEM_BASE); +} + +__EXTERN_INLINE void polaris_writeb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_MEM_BASE)); + mb(); +} + +__EXTERN_INLINE void polaris_writew(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_MEM_BASE)); + mb(); +} + +__EXTERN_INLINE void polaris_writel(unsigned int b, unsigned long addr) +{ + *(vuip)(addr + POLARIS_DENSE_MEM_BASE) = b; + mb(); +} + +__EXTERN_INLINE void polaris_writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr + POLARIS_DENSE_MEM_BASE) = b; + mb(); +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long polaris_dense_mem(unsigned long addr) +{ + return POLARIS_DENSE_MEM_BASE; +} + +#undef vucp +#undef vusp +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#define virt_to_bus polaris_virt_to_bus +#define bus_to_virt polaris_bus_to_virt + +#define __inb polaris_inb +#define __inw polaris_inw +#define __inl polaris_inl +#define __outb polaris_outb +#define __outw polaris_outw +#define __outl polaris_outl +#define __readb polaris_readb +#define __readw polaris_readw +#define __writeb polaris_writeb +#define __writew polaris_writew +#define __readl polaris_readl +#define __readq polaris_readq +#define __writel polaris_writel +#define __writeq polaris_writeq +#define dense_mem polaris_dense_mem + +#define inb(port) __inb((port)) +#define inw(port) __inw((port)) +#define inl(port) __inl((port)) + +#define outb(v, port) __outb((v),(port)) +#define outw(v, port) __outw((v),(port)) +#define outl(v, port) __outl((v),(port)) + +#define readb(a) __readb((unsigned long)(a)) +#define readw(a) __readw((unsigned long)(a)) +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) + +#define writeb(v,a) __writeb((v),(unsigned long)(a)) +#define writew(v,a) __writew((v),(unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_POLARIS__H__ */ diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h --- v2.2.0-pre6/linux/include/asm-alpha/core_tsunami.h Wed Sep 9 14:51:10 1998 +++ linux/include/asm-alpha/core_tsunami.h Sun Jan 10 09:59:59 1999 @@ -16,8 +16,8 @@ * */ -#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) +#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024U) +#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024U) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) #define TSUNAMI_DMA_WIN_BASE alpha_mv.dma_win_base diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h --- v2.2.0-pre6/linux/include/asm-alpha/io.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/io.h Sun Jan 10 09:59:59 1999 @@ -141,6 +141,8 @@ # include #elif defined(CONFIG_ALPHA_JENSEN) # include +#elif defined(CONFIG_ALPHA_RX164) +# include #else #error "What system is this?" #endif diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h --- v2.2.0-pre6/linux/include/asm-alpha/irq.h Thu Dec 31 10:29:02 1998 +++ linux/include/asm-alpha/irq.h Sun Jan 10 09:59:59 1999 @@ -34,6 +34,7 @@ defined(CONFIG_ALPHA_XLT) || \ defined(CONFIG_ALPHA_MIATA) || \ defined(CONFIG_ALPHA_RUFFIAN) || \ + defined(CONFIG_ALPHA_RX164) || \ defined(CONFIG_ALPHA_NORITAKE) # define NR_IRQS 48 diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h --- v2.2.0-pre6/linux/include/asm-alpha/spinlock.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/spinlock.h Sun Jan 10 09:59:59 1999 @@ -207,7 +207,7 @@ " br 1b\n" ".previous" : "=m" (__dummy_lock(lock)), "=&r" (regx) - : "0" (__dummy_lock(lock)) + : "m" (__dummy_lock(lock)) ); } #endif /* DEBUG_RWLOCK */ @@ -230,7 +230,7 @@ "6: br 1b\n" ".previous" : "=m" (__dummy_lock(lock)), "=&r" (regx) - : "0" (__dummy_lock(lock))); + : "m" (__dummy_lock(lock))); } #define read_lock_irq(lock) (__cli(), read_lock(lock)) diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h --- v2.2.0-pre6/linux/include/asm-alpha/unistd.h Wed Sep 9 14:51:10 1998 +++ linux/include/asm-alpha/unistd.h Sat Jan 9 19:08:27 1999 @@ -67,7 +67,7 @@ #define __NR_getpgrp 63 #define __NR_getpagesize 64 #define __NR_osf_mremap 65 /* not implemented */ -#define __NR_osf_vfork 66 +#define __NR_vfork 66 #define __NR_stat 67 #define __NR_lstat 68 #define __NR_osf_sbrk 69 /* not implemented */ diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-i386/locks.h linux/include/asm-i386/locks.h --- v2.2.0-pre6/linux/include/asm-i386/locks.h Sat Nov 29 10:33:21 1997 +++ linux/include/asm-i386/locks.h Mon Jan 11 10:11:58 1999 @@ -62,7 +62,7 @@ not be safe this way */ if(!--sp->users) { - lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID; + sp->cpu= NO_PROC_ID;lock_clear_bit(0,&sp->lock); return 1; } return 0; @@ -102,15 +102,17 @@ extern __inline__ void spinunlock(struct spinlock *sp) { + int pri; if(current->lock_order!=sp->priority) panic("lock release order violation %s (%d)\n", sp->name, current->lock_order); + pri=sp->oldpri; if(prim_spin_unlock(sp)) { /* * Update the debugging lock priority chain. We dumped * our last right to the lock. */ - current->lock_order=sp->oldpri; + current->lock_order=sp->pri; } } diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h --- v2.2.0-pre6/linux/include/asm-i386/semaphore.h Wed Dec 16 10:32:56 1998 +++ linux/include/asm-i386/semaphore.h Mon Jan 11 10:35:06 1999 @@ -49,11 +49,6 @@ * * This is trivially done with load_locked/store_cond, * but on the x86 we need an external synchronizer. - * Currently this is just the global interrupt lock, - * bah. Go for a smaller spinlock some day. - * - * (On the other hand this shouldn't be in any critical - * path, so..) */ static inline void wake_one_more(struct semaphore * sem) { diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h --- v2.2.0-pre6/linux/include/asm-sparc/page.h Thu Aug 6 14:06:34 1998 +++ linux/include/asm-sparc/page.h Sun Jan 10 22:56:43 1999 @@ -19,7 +19,6 @@ #ifdef __KERNEL__ -#include #include /* for KERNBASE */ #include diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/file.h linux/include/linux/file.h --- v2.2.0-pre6/linux/include/linux/file.h Mon Dec 28 15:00:53 1998 +++ linux/include/linux/file.h Sat Jan 9 19:16:44 1999 @@ -62,7 +62,7 @@ * precious bytes from my kernel, even without counting all the code compiled * as module! * - * I suspect there are many other similiar "optimizations" across the + * I suspect there are many other similar "optimizations" across the * kernel... */ extern void fput(struct file *file); diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.2.0-pre6/linux/include/linux/mm.h Fri Jan 8 22:36:24 1999 +++ linux/include/linux/mm.h Mon Jan 11 10:37:07 1999 @@ -324,6 +324,7 @@ #define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO) #define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO) #define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO) +#define GFP_KSWAPD (__GFP_IO) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.2.0-pre6/linux/include/linux/proc_fs.h Mon Jan 4 15:08:18 1999 +++ linux/include/linux/proc_fs.h Mon Jan 11 10:37:07 1999 @@ -52,8 +52,7 @@ PROC_STRAM, PROC_SOUND, PROC_MTRR, /* whether enabled or not */ - PROC_FS, - PROC_SWAPSTATS + PROC_FS }; enum pid_directory_inos { diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.2.0-pre6/linux/include/linux/sched.h Fri Jan 8 22:36:24 1999 +++ linux/include/linux/sched.h Mon Jan 11 10:37:07 1999 @@ -33,6 +33,7 @@ #define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ #define CLONE_PID 0x00001000 /* set if pid shared */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mmput */ /* * These are the constant used to fake the fixed-point load-average @@ -257,8 +258,8 @@ /* Pointer to task[] array linkage. */ struct task_struct **tarray_ptr; - struct wait_queue *wait_chldexit, *vfork_sleep; /* for wait4()/vfork */ - + struct wait_queue *wait_chldexit; /* for wait4() */ + struct semaphore *vfork_sem; /* for vfork() */ unsigned long policy, rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; unsigned long it_real_incr, it_prof_incr, it_virt_incr; @@ -269,10 +270,7 @@ /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1; - int trashing_memory:1; unsigned long swap_address; - unsigned long old_maj_flt; /* old value of maj_flt */ - unsigned long dec_flt; /* page fault count of the last time */ unsigned long swap_cnt; /* number of pages to swap on next pass */ /* process credentials */ uid_t uid,euid,suid,fsuid; @@ -323,6 +321,7 @@ #define PF_DUMPCORE 0x00000200 /* dumped core */ #define PF_SIGNALED 0x00000400 /* killed by a signal */ #define PF_MEMALLOC 0x00000800 /* Allocating memory */ +#define PF_VFORK 0x00001000 /* Wake up parent in mmput */ #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ #define PF_DTRACE 0x00200000 /* delayed trace (used on m68k, i386) */ @@ -356,7 +355,7 @@ /* utime */ {0,0,0,0},0, \ /* per CPU times */ {0, }, {0, }, \ /* flt */ 0,0,0,0,0,0, \ -/* swp */ 0,0,0,0,0,0, \ +/* swp */ 0,0,0, \ /* process credentials */ \ /* uid etc */ 0,0,0,0,0,0,0,0, \ /* suppl grps*/ 0, {0,}, \ diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.2.0-pre6/linux/include/linux/swap.h Thu Jan 7 15:11:40 1999 +++ linux/include/linux/swap.h Mon Jan 11 10:35:07 1999 @@ -61,15 +61,6 @@ extern unsigned long page_cache_size; extern int buffermem; -struct swap_stats -{ - long proc_freepage_attempts; - long proc_freepage_successes; - long kswap_freepage_attempts; - long kswap_freepage_successes; -}; -extern struct swap_stats swap_stats; - /* Incomplete types for prototype declarations: */ struct task_struct; struct vm_area_struct; @@ -82,7 +73,7 @@ extern void swap_setup (void); /* linux/mm/vmscan.c */ -extern int try_to_free_pages(unsigned int gfp_mask, int count); +extern int try_to_free_pages(unsigned int gfp_mask); /* linux/mm/page_io.c */ extern void rw_swap_page(int, unsigned long, char *, int); @@ -139,9 +130,7 @@ #ifdef SWAP_CACHE_INFO extern unsigned long swap_cache_add_total; -extern unsigned long swap_cache_add_success; extern unsigned long swap_cache_del_total; -extern unsigned long swap_cache_del_success; extern unsigned long swap_cache_find_total; extern unsigned long swap_cache_find_success; #endif diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/swapctl.h linux/include/linux/swapctl.h --- v2.2.0-pre6/linux/include/linux/swapctl.h Mon Jan 4 15:08:18 1999 +++ linux/include/linux/swapctl.h Mon Jan 11 10:35:08 1999 @@ -4,41 +4,6 @@ #include #include -/* Swap tuning control */ - -typedef struct swap_control_v6 -{ - unsigned int sc_max_page_age; - unsigned int sc_page_advance; - unsigned int sc_page_decline; - unsigned int sc_page_initial_age; - unsigned int sc_age_cluster_fract; - unsigned int sc_age_cluster_min; - unsigned int sc_pageout_weight; - unsigned int sc_bufferout_weight; -} swap_control_v6; -typedef struct swap_control_v6 swap_control_t; -extern swap_control_t swap_control; - -typedef struct swapstat_v1 -{ - unsigned long wakeups; - unsigned long pages_reclaimed; - unsigned long pages_shm; - unsigned long pages_mmap; - unsigned long pages_swap; - - unsigned long gfp_freepage_attempts; - unsigned long gfp_freepage_successes; - unsigned long gfp_shrink_attempts; - unsigned long gfp_shrink_successes; - unsigned long kswap_freepage_attempts; - unsigned long kswap_freepage_successes; - unsigned long kswap_wakeups[4]; -} swapstat_v1; -typedef swapstat_v1 swapstat_t; -extern swapstat_t swapstats; - typedef struct buffer_mem_v1 { unsigned int min_percent; @@ -66,30 +31,5 @@ } pager_daemon_v1; typedef pager_daemon_v1 pager_daemon_t; extern pager_daemon_t pager_daemon; - -#define SC_VERSION 1 -#define SC_MAX_VERSION 1 - -#ifdef __KERNEL__ - -/* Define the maximum (least urgent) priority for the page reclaim code */ -#define RCL_MAXPRI 6 -/* We use an extra priority in the swap accounting code to represent - failure to free a resource at any priority */ -#define RCL_FAILURE (RCL_MAXPRI + 1) - -#define AGE_CLUSTER_FRACT (swap_control.sc_age_cluster_fract) -#define AGE_CLUSTER_MIN (swap_control.sc_age_cluster_min) -#define PAGEOUT_WEIGHT (swap_control.sc_pageout_weight) -#define BUFFEROUT_WEIGHT (swap_control.sc_bufferout_weight) - -/* Page aging (see mm/swap.c) */ - -#define MAX_PAGE_AGE (swap_control.sc_max_page_age) -#define PAGE_ADVANCE (swap_control.sc_page_advance) -#define PAGE_DECLINE (swap_control.sc_page_decline) -#define PAGE_INITIAL_AGE (swap_control.sc_page_initial_age) - -#endif /* __KERNEL */ #endif /* _LINUX_SWAPCTL_H */ diff -u --recursive --new-file v2.2.0-pre6/linux/ipc/sem.c linux/ipc/sem.c --- v2.2.0-pre6/linux/ipc/sem.c Mon Dec 28 15:00:53 1998 +++ linux/ipc/sem.c Sat Jan 9 19:16:44 1999 @@ -696,7 +696,7 @@ /* * If queue.status == 1 we where woken up and * have to retry else we simply return. - * If an interrupt occured we have to clean up the + * If an interrupt occurred we have to clean up the * queue * */ diff -u --recursive --new-file v2.2.0-pre6/linux/kernel/fork.c linux/kernel/fork.c --- v2.2.0-pre6/linux/kernel/fork.c Fri Jan 8 22:36:25 1999 +++ linux/kernel/fork.c Sun Jan 10 13:23:35 1999 @@ -284,7 +284,10 @@ void mmput(struct mm_struct *mm) { /* notify parent sleeping on vfork() */ - wake_up(¤t->p_opptr->vfork_sleep); + if (current->flags & PF_VFORK) { + current->flags &= ~PF_VFORK; + up(current->p_opptr->vfork_sem); + } if (atomic_dec_and_test(&mm->count)) { release_segments(mm); @@ -456,10 +459,12 @@ { unsigned long new_flags = p->flags; - new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU); + new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK); new_flags |= PF_FORKNOEXEC; if (!(clone_flags & CLONE_PTRACE)) new_flags &= ~(PF_PTRACED|PF_TRACESYS); + if (clone_flags & CLONE_VFORK) + new_flags |= PF_VFORK; p->flags = new_flags; } @@ -524,7 +529,7 @@ p->p_pptr = p->p_opptr = current; p->p_cptr = NULL; init_waitqueue(&p->wait_chldexit); - init_waitqueue(&p->vfork_sleep); + p->vfork_sem = NULL; p->sigpending = 0; sigemptyset(&p->signal); @@ -571,7 +576,6 @@ /* ok, now we should be set up.. */ p->swappable = 1; - p->trashing_memory = 0; p->exit_signal = clone_flags & CSIGNAL; p->pdeath_signal = 0; diff -u --recursive --new-file v2.2.0-pre6/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.2.0-pre6/linux/kernel/sysctl.c Thu Jan 7 15:11:41 1999 +++ linux/kernel/sysctl.c Fri Jan 8 22:54:16 1999 @@ -216,8 +216,6 @@ }; static ctl_table vm_table[] = { - {VM_SWAPCTL, "swapctl", - &swap_control, sizeof(swap_control_t), 0644, NULL, &proc_dointvec}, {VM_FREEPG, "freepages", &freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec}, {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL, diff -u --recursive --new-file v2.2.0-pre6/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.2.0-pre6/linux/mm/page_alloc.c Fri Jan 8 22:36:25 1999 +++ linux/mm/page_alloc.c Tue Jan 12 14:32:44 1999 @@ -90,33 +90,6 @@ */ spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; -/* - * This routine is used by the kernel swap daemon to determine - * whether we have "enough" free pages. It is fairly arbitrary, - * having a low-water and high-water mark. - * - * This returns: - * 0 - urgent need for memory - * 1 - need some memory, but do it slowly in the background - * 2 - no need to even think about it. - */ -int free_memory_available(void) -{ - static int available = 1; - - if (nr_free_pages < freepages.low) { - available = 0; - return 0; - } - - if (nr_free_pages > freepages.high) { - available = 1; - return 2; - } - - return available; -} - static inline void free_pages_ok(unsigned long map_nr, unsigned long order) { struct free_area_struct *area = free_area + order; @@ -155,11 +128,6 @@ free_pages_ok(page->map_nr, 0); return; } -#if 0 - if (PageSwapCache(page) && atomic_read(&page->count) == 1) - printk(KERN_WARNING "VM: Releasing swap cache page at %p", - __builtin_return_address(0)); -#endif } void free_pages(unsigned long addr, unsigned long order) @@ -177,12 +145,6 @@ free_pages_ok(map_nr, order); return; } -#if 0 - if (PageSwapCache(map) && atomic_read(&map->count) == 1) - printk(KERN_WARNING - "VM: Releasing swap cache pages at %p", - __builtin_return_address(0)); -#endif } } @@ -249,38 +211,24 @@ * do our best to just allocate things without * further thought. */ - if (current->flags & PF_MEMALLOC) - goto ok_to_allocate; + if (!(current->flags & PF_MEMALLOC)) { + static int trashing = 0; + int freed; - /* - * Avoid going back-and-forth between allocating - * memory and trying to free it. If we get into - * a bad memory situation, we're better off trying - * to free things up until things are better. - * - * Most notably, this puts most of the onus of - * freeing up memory on the processes that _use_ - * the most memory, rather than on everybody. - */ - if (nr_free_pages > freepages.min) { - if (!current->trashing_memory) - goto ok_to_allocate; - if (nr_free_pages > freepages.low) { - current->trashing_memory = 0; - goto ok_to_allocate; + if (nr_free_pages > freepages.min) { + if (!trashing) + goto ok_to_allocate; + if (nr_free_pages > freepages.low) { + trashing = 0; + goto ok_to_allocate; + } } - } - /* - * Low priority (user) allocations must not - * succeed if we are having trouble allocating - * memory. - */ - current->trashing_memory = 1; - { - int freed; + + trashing = 1; current->flags |= PF_MEMALLOC; - freed = try_to_free_pages(gfp_mask, freepages.high - nr_free_pages); + freed = try_to_free_pages(gfp_mask); current->flags &= ~PF_MEMALLOC; + if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH))) goto nopage; } @@ -406,21 +354,29 @@ struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info; offset = (offset >> page_cluster) << page_cluster; - - for (i = 1 << page_cluster; i > 0; i--) { - if (offset >= swapdev->max - || nr_free_pages - atomic_read(&nr_async_pages) < - (freepages.high + freepages.low)/2) - return; - if (!swapdev->swap_map[offset] || - swapdev->swap_map[offset] == SWAP_MAP_BAD || - test_bit(offset, swapdev->swap_lockmap)) - continue; - new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0); - if (new_page != NULL) - __free_page(new_page); - offset++; - } + + i = 1 << page_cluster; + do { + /* Don't read-ahead past the end of the swap area */ + if (offset >= swapdev->max) + break; + /* Don't block on I/O for read-ahead */ + if (atomic_read(&nr_async_pages) >= pager_daemon.swap_cluster) + break; + /* Don't read in bad or busy pages */ + if (!swapdev->swap_map[offset]) + break; + if (swapdev->swap_map[offset] == SWAP_MAP_BAD) + break; + if (test_bit(offset, swapdev->swap_lockmap)) + break; + + /* Ok, do the async read-ahead now */ + new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0); + if (new_page != NULL) + __free_page(new_page); + offset++; + } while (--i); return; } diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swap.c linux/mm/swap.c --- v2.2.0-pre6/linux/mm/swap.c Fri Jan 1 12:58:21 1999 +++ linux/mm/swap.c Fri Jan 8 22:54:16 1999 @@ -46,23 +46,6 @@ out, so that we don't try to swap TOO many pages out at once */ atomic_t nr_async_pages = ATOMIC_INIT(0); -/* - * Constants for the page aging mechanism: the maximum age (actually, - * the maximum "youthfulness"); the quanta by which pages rejuvenate - * and age; and the initial age for new pages. - * - * The "pageout_weight" is strictly a fixedpoint number with the - * ten low bits being the fraction (ie 8192 really means "8.0"). - */ -swap_control_t swap_control = { - 20, 3, 1, 3, /* Page aging */ - 32, 4, /* Aging cluster */ - 8192, /* sc_pageout_weight aka PAGEOUT_WEIGHT */ - 8192, /* sc_bufferout_weight aka BUFFEROUT_WEIGHT */ -}; - -swapstat_t swapstats = {0}; - buffer_mem_t buffer_mem = { 2, /* minimum percent buffer */ 10, /* borrow percent buffer */ @@ -80,7 +63,6 @@ SWAP_CLUSTER_MAX, /* minimum number of tries */ SWAP_CLUSTER_MAX, /* do swap I/O in clusters of this size */ }; - /* * Perform any setup for the swap system diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swap_state.c linux/mm/swap_state.c --- v2.2.0-pre6/linux/mm/swap_state.c Fri Jan 1 12:58:21 1999 +++ linux/mm/swap_state.c Wed Jan 13 09:54:50 1999 @@ -29,18 +29,16 @@ #ifdef SWAP_CACHE_INFO unsigned long swap_cache_add_total = 0; -unsigned long swap_cache_add_success = 0; unsigned long swap_cache_del_total = 0; -unsigned long swap_cache_del_success = 0; unsigned long swap_cache_find_total = 0; unsigned long swap_cache_find_success = 0; void show_swap_cache_info(void) { - printk("Swap cache: add %ld/%ld, delete %ld/%ld, find %ld/%ld\n", - swap_cache_add_total, swap_cache_add_success, - swap_cache_del_total, swap_cache_del_success, - swap_cache_find_total, swap_cache_find_success); + printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n", + swap_cache_add_total, + swap_cache_del_total, + swap_cache_find_success, swap_cache_find_total); } #endif @@ -69,9 +67,6 @@ page->offset = entry; add_page_to_hash_queue(page, &swapper_inode, entry); add_page_to_inode_queue(&swapper_inode, page); -#ifdef SWAP_CACHE_INFO - swap_cache_add_success++; -#endif return 1; } @@ -192,16 +187,6 @@ printk ("VM: Removing swap cache page with wrong inode hash " "on page %08lx\n", page_address(page)); } -#if 0 - /* - * This is a legal case, but warn about it. - */ - if (atomic_read(&page->count) == 1) { - printk (KERN_WARNING - "VM: Removing page cache on unshared page %08lx\n", - page_address(page)); - } -#endif #ifdef DEBUG_SWAP printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n", @@ -222,7 +207,6 @@ #ifdef SWAP_CACHE_INFO swap_cache_del_total++; - swap_cache_del_success++; #endif #ifdef DEBUG_SWAP printk("DebugVM: delete_from_swap_cache(%08lx count %d, " @@ -262,15 +246,22 @@ struct page * lookup_swap_cache(unsigned long entry) { struct page *found; - + +#ifdef SWAP_CACHE_INFO + swap_cache_find_total++; +#endif while (1) { found = find_page(&swapper_inode, entry); if (!found) return 0; if (found->inode != &swapper_inode || !PageSwapCache(found)) goto out_bad; - if (!PageLocked(found)) + if (!PageLocked(found)) { +#ifdef SWAP_CACHE_INFO + swap_cache_find_success++; +#endif return found; + } __free_page(found); __wait_on_page(found); } @@ -292,7 +283,7 @@ struct page * read_swap_cache_async(unsigned long entry, int wait) { - struct page *found_page, *new_page; + struct page *found_page = 0, *new_page; unsigned long new_page_addr; #ifdef DEBUG_SWAP @@ -300,15 +291,20 @@ entry, wait ? ", wait" : ""); #endif /* + * Make sure the swap entry is still in use. + */ + if (!swap_duplicate(entry)) /* Account for the swap cache */ + goto out; + /* * Look for the page in the swap cache. */ found_page = lookup_swap_cache(entry); if (found_page) - goto out; + goto out_free_swap; new_page_addr = __get_free_page(GFP_USER); if (!new_page_addr) - goto out; /* Out of memory */ + goto out_free_swap; /* Out of memory */ new_page = mem_map + MAP_NR(new_page_addr); /* @@ -317,11 +313,6 @@ found_page = lookup_swap_cache(entry); if (found_page) goto out_free_page; - /* - * Make sure the swap entry is still in use. - */ - if (!swap_duplicate(entry)) /* Account for the swap cache */ - goto out_free_page; /* * Add it to the swap cache and read its contents. */ @@ -339,6 +330,8 @@ out_free_page: __free_page(new_page); +out_free_swap: + swap_free(entry); out: return found_page; } diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.2.0-pre6/linux/mm/swapfile.c Fri Nov 27 13:09:31 1998 +++ linux/mm/swapfile.c Fri Jan 8 23:48:41 1999 @@ -23,6 +23,7 @@ struct swap_info_struct swap_info[MAX_SWAPFILES]; +#define SWAPFILE_CLUSTER 256 static inline int scan_swap_map(struct swap_info_struct *si) { @@ -30,7 +31,7 @@ /* * We try to cluster swap pages by allocating them * sequentially in swap. Once we've allocated - * SWAP_CLUSTER_MAX pages this way, however, we resort to + * SWAPFILE_CLUSTER pages this way, however, we resort to * first-free allocation, starting a new cluster. This * prevents us from scattering swap pages all over the entire * swap partition, so that we reduce overall disk seek times @@ -46,7 +47,7 @@ goto got_page; } } - si->cluster_nr = SWAP_CLUSTER_MAX; + si->cluster_nr = SWAPFILE_CLUSTER; for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) { if (si->swap_map[offset]) continue; diff -u --recursive --new-file v2.2.0-pre6/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.2.0-pre6/linux/mm/vmscan.c Fri Jan 8 22:36:25 1999 +++ linux/mm/vmscan.c Sun Jan 10 13:20:11 1999 @@ -439,7 +439,7 @@ * forever in a really bad memory squeeze. */ if (nr_free_pages < freepages.high) - try_to_free_pages(0, 16); + try_to_free_pages(GFP_KSWAPD); } return 0; @@ -454,9 +454,10 @@ * cluster them so that we get good swap-out behaviour. See * the "free_memory()" macro for details. */ -int try_to_free_pages(unsigned int gfp_mask, int count) +int try_to_free_pages(unsigned int gfp_mask) { int priority; + int count = SWAP_CLUSTER_MAX; lock_kernel(); diff -u --recursive --new-file v2.2.0-pre6/linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- v2.2.0-pre6/linux/net/ipv4/Config.in Thu Jan 7 15:11:41 1999 +++ linux/net/ipv4/Config.in Sat Jan 9 10:01:56 1999 @@ -72,7 +72,7 @@ bool 'IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD fi fi -bool 'IP: TCP syncookie support (not enabled per default) ' CONFIG_SYN_COOKIES +bool 'IP: TCP syncookie support (not enabled per default)' CONFIG_SYN_COOKIES comment '(it is safe to leave these untouched)' #bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP tristate 'IP: Reverse ARP' CONFIG_INET_RARP diff -u --recursive --new-file v2.2.0-pre6/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.2.0-pre6/linux/net/ipv4/ip_fw.c Fri Jan 8 22:36:25 1999 +++ linux/net/ipv4/ip_fw.c Sun Jan 10 22:56:43 1999 @@ -63,7 +63,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.2.0-pre6/linux/net/irda/irttp.c linux/net/irda/irttp.c --- v2.2.0-pre6/linux/net/irda/irttp.c Tue Dec 22 14:16:59 1998 +++ linux/net/irda/irttp.c Sun Jan 10 22:56:43 1999 @@ -26,7 +26,6 @@ #include #include #include -#include #include diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/Menuconfig linux/scripts/Menuconfig --- v2.2.0-pre6/linux/scripts/Menuconfig Mon Dec 28 15:00:53 1998 +++ linux/scripts/Menuconfig Sat Jan 9 19:16:44 1999 @@ -57,6 +57,14 @@ # 13 Dec 1998, Riley H Williams (rhw@bigfoot.com) # When an error occurs, actually display the error message as well as # our comments thereon. +# +# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net) +# Fix mod_bool to honor $CONFIG_MODULES. +# Fix dep_tristate to call define_bool when dependency is "n". +# +# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) +# Blow away lxdialog.scrltmp on entry to activate_menu. This protects +# against people who use commands like ' ' to select menus. # @@ -177,17 +185,13 @@ # else in the kernel. # function dep_tristate () { - if [ "$CONFIG_MODULES" != "y" ] - then - bool "$1" "$2" - else - if eval [ "_$3" != "_m" ] - then - tristate "$1" "$2" $3 - else - mod_bool "$1" "$2" - fi - fi + if [ "$3" = "y" ]; then + tristate "$1" "$2" + else if [ "$3" = "m" ]; then + mod_bool "$1" "$2" + else + define_bool "$2" "$n" + fi; fi } # @@ -372,16 +376,20 @@ # Same as bool() except options are (Module/No) # function mod_bool () { - set_x_info "$2" "n" - - case $x in - y|m) flag='M' ;; - *) flag=' ' ;; - esac - - echo -ne "'$2' '<$flag> $1$info' " >>MCmenu - - echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists + if [ "$CONFIG_MODULES" != "y" ]; then + define_bool "$2" "n" + else + set_x_info "$2" "n" + + case $x in + y|m) flag='M' ;; + *) flag=' ' ;; + esac + + echo -ne "'$2' '<$flag> $1$info' " >>MCmenu + + echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists + fi } # @@ -720,6 +728,7 @@ # dialog commands or recursively call other menus. # function activate_menu () { + rm -f lxdialog.scrltmp while true do comment_ctr=0 #So comment lines get unique tags diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c --- v2.2.0-pre6/linux/scripts/lxdialog/menubox.c Thu Nov 12 16:21:25 1998 +++ linux/scripts/lxdialog/menubox.c Sat Jan 9 19:16:44 1999 @@ -48,6 +48,12 @@ * *) If for some reason the last scrolling position is not saved by * lxdialog, it sets the scrolling so that the selected item is in the * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. */ #include "dialog.h" @@ -227,6 +233,7 @@ choice = choice - scroll; fclose(f); } else { + scroll=0; remove("lxdialog.scrltmp"); fclose(f); f=NULL; diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/tkgen.c linux/scripts/tkgen.c --- v2.2.0-pre6/linux/scripts/tkgen.c Fri Jan 8 22:36:28 1999 +++ linux/scripts/tkgen.c Sat Jan 9 19:16:44 1999 @@ -69,6 +69,11 @@ * 0: they may have been set to 1 elsewhere. CONFIG_NETLINK is * an example. * + * 1999 01 04 + * Michael Elizabeth Chastain + * - Call clear_globalflags when writing out update_mainmenu. + * This fixes the missing global/vfix lines for ARCH=alpha on 2.2.0-pre4. + * * TO DO: * - clean up - there are useless ifdef's everywhere. * - better comments throughout - C code generating tcl is really cryptic. @@ -358,7 +363,7 @@ } printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num); - printf(".menu%d.config.f.x%d.m configure -state normal;",menu_num, line_num); + printf("global CONFIG_MODULES; if {($CONFIG_MODULES == 1)} then { .menu%d.config.f.x%d.m configure -state normal };",menu_num, line_num); printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num); /* * Or in a bit to the variable - this causes all of the radiobuttons @@ -913,6 +918,7 @@ * the top level menu, and this procedure will ensure that things are * correct. */ + clear_globalflags(scfg); printf("proc update_mainmenu {w} {\n"); for(cfg = scfg; cfg != NULL; cfg = cfg->next) {