diff -u --recursive --new-file v2.1.130/linux/CREDITS linux/CREDITS --- v2.1.130/linux/CREDITS Fri Nov 27 13:09:20 1998 +++ linux/CREDITS Tue Dec 1 09:39:09 1998 @@ -1116,11 +1116,11 @@ D: SCSI Tape Driver N: Hamish Macdonald -E: hamish@border.ocunix.on.ca +E: hamish_macdonald@westendsys.com D: Linux/68k port -S: 102-B Valleystream Drive -S: Nepean, Ontario -S: Canada K2H-9E1 +S: 32 Clydesdale Avenue +S: Kanata, Ontario +S: Canada K2M-2G7 N: Peter MacDonald D: SLS distribution @@ -2074,7 +2074,7 @@ S: USA N: Marc Zyngier -E: maz@gloups.fdn.fr +E: maz@wild-wind.fr.eu.org D: MD driver S: 11 rue Victor HUGO S: 95560 Montsoult diff -u --recursive --new-file v2.1.130/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.130/linux/Documentation/Configure.help Fri Nov 27 13:09:21 1998 +++ linux/Documentation/Configure.help Sun Nov 29 10:38:43 1998 @@ -2397,9 +2397,6 @@ information on the WWW at http://www.tor.shaw.wave.ca/~ambrose/kernel21.html. - If you say Y here, you should also say Y to "IP: always defragment", - below. - If you say Y here, then the modules ip_masq_ftp.o (for ftp file transfers), ip_masq_irc.o (for irc chats), ip_masq_quake.o (you guessed it), ip_masq_vdolive.o (for VDOLive video connections), @@ -2503,7 +2500,7 @@ The module will be called ip_masq_markfw.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -IP: always defragment +IP: always defragment (required for masquerading) CONFIG_IP_ALWAYS_DEFRAG If you say Y here, then all incoming fragments (parts of IP packets that arose when some host between origin and destination decided @@ -2511,18 +2508,13 @@ reassembled (defragmented) before being processed, even if they are about to be forwarded. - This option is highly recommended if you have said Y to "IP: - masquerading" because that facility requires that second and further - fragments can be related to TCP or UDP port numbers, which are only - stored in the first fragment. + You must say Y here if you want to enable "IP: masquerading" or "IP: + transparent proxying". When using "IP: firewalling" support, you might also want to say Y here, to have a more reliable firewall (otherwise second and further fragments must be dealt with by the firewall, which can be tricky). - When using "IP: transparent proxying", this option is implicit, - although it is safe to say Y here. - Only say Y here if running either a firewall that is the sole link to your network or a transparent proxy; never ever say Y here for a normal router or host. @@ -3868,7 +3860,7 @@ NCR53C8XX SCSI support CONFIG_SCSI_NCR53C8XX - This is the BSD ncr driver adapted to linux for the NCR53C8XX family + This is the BSD ncr driver adapted to Linux for the NCR53C8XX family of PCI-SCSI controllers. This driver supports parity checking, tagged command queuing and fast synchronous data transfers up to 80 MB/s with wide FAST-40 LVD devices and controllers. @@ -8327,6 +8319,16 @@ standby events while one is already being processed they will be ignored. Without this the Thinkpad 560 has troubles with the user level daemon apmd, and with the PCMCIA package pcmcia-cs. + +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. + Say Y. Watchdog Timer Support CONFIG_WATCHDOG diff -u --recursive --new-file v2.1.130/linux/Makefile linux/Makefile --- v2.1.130/linux/Makefile Fri Nov 27 13:09:21 1998 +++ linux/Makefile Fri Nov 27 13:19:07 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 130 +SUBLEVEL = 131 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --recursive --new-file v2.1.130/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.1.130/linux/arch/alpha/config.in Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/config.in Tue Dec 1 09:33:59 1998 @@ -22,14 +22,6 @@ mainmenu_option next_comment comment 'General setup' -unset CONFIG_CROSSCOMPILE CONFIG_NATIVE - -if [ "`uname`" != "Linux" ]; then - define_bool CONFIG_CROSSCOMPILE y -else - define_bool CONFIG_NATIVE y -fi - choice 'Alpha system type' \ "Generic CONFIG_ALPHA_GENERIC \ Alcor/Alpha-XLT CONFIG_ALPHA_ALCOR \ diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.130/linux/arch/alpha/kernel/bios32.c Fri Nov 27 13:09:21 1998 +++ linux/arch/alpha/kernel/bios32.c Tue Dec 1 09:33:59 1998 @@ -296,60 +296,82 @@ * on SRM. It is more trouble than it iw worth to conditionalize this. */ -static struct { - struct reset_irq { - struct pci_dev *dev; - u8 irq; - } irq[16]; - int irq_count; - - struct reset_io { - struct pci_dev *dev; - u8 reg; - u32 io; - } io[16]; - int io_count; -} srm_resets; +struct srm_irq_reset { + struct srm_irq_reset *next; + struct pci_dev *dev; + u8 irq; +} *srm_irq_resets; + +struct srm_io_reset { + struct srm_io_reset *next; + struct pci_dev *dev; + u32 io; + u8 reg; +} *srm_io_resets; /* Apply the collected reset modifications. */ void reset_for_srm(void) { - struct pci_dev *dev; - int i; + struct srm_irq_reset *qreset; + struct srm_io_reset *ireset; /* Reset any IRQs that we changed. */ - for (i = 0; i < srm_resets.irq_count; i++) { - dev = srm_resets.irq[i].dev; - - pcibios_write_config_byte(dev->bus->number, dev->devfn, + for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) { + pcibios_write_config_byte(qreset->dev->bus->number, + qreset->dev->devfn, PCI_INTERRUPT_LINE, - srm_resets.irq[i].irq); + qreset->irq); #if 1 printk("reset_for_srm: bus %d slot 0x%x " "SRM IRQ 0x%x changed back from 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - srm_resets.irq[i].irq, dev->irq); + qreset->dev->bus->number, + PCI_SLOT(qreset->dev->devfn), + qreset->irq, qreset->dev->irq); #endif } /* Reset any IO addresses that we changed. */ - for (i = 0; i < srm_resets.io_count; i++) { - dev = srm_resets.io[i].dev; - - pcibios_write_config_byte(dev->bus->number, dev->devfn, - srm_resets.io[i].reg, - srm_resets.io[i].io); + for (ireset = srm_io_resets; ireset ; ireset = ireset->next) { + pcibios_write_config_dword(ireset->dev->bus->number, + ireset->dev->devfn, + ireset->reg, ireset->io); #if 1 printk("reset_for_srm: bus %d slot 0x%x " - "SRM IO restored to 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - srm_resets.io[i].io); + "SRM MEM/IO restored to 0x%x\n", + ireset->dev->bus->number, + PCI_SLOT(ireset->dev->devfn), + ireset->io); #endif } } +static void +new_irq_reset(struct pci_dev *dev, u8 irq) +{ + struct srm_irq_reset *n; + n = kmalloc(sizeof(*n), GFP_KERNEL); + + n->next = srm_irq_resets; + n->dev = dev; + n->irq = irq; + srm_irq_resets = n; +} + +static void +new_io_reset(struct pci_dev *dev, u8 reg, u32 io) +{ + struct srm_io_reset *n; + n = kmalloc(sizeof(*n), GFP_KERNEL); + + n->next = srm_io_resets; + n->dev = dev; + n->reg = reg; + n->io = io; + srm_io_resets = n; +} + /* * Disable PCI device DEV so that it does not respond to I/O or memory @@ -426,6 +448,7 @@ struct pci_bus *bus; unsigned short cmd; unsigned int base, mask, size, off, idx; + unsigned int orig_base; unsigned int alignto; unsigned long handle; @@ -467,6 +490,8 @@ * Figure out how much space and of what type this * device wants. */ + pcibios_read_config_dword(bus->number, dev->devfn, off, + &orig_base); pcibios_write_config_dword(bus->number, dev->devfn, off, 0xffffffff); pcibios_read_config_dword(bus->number, dev->devfn, off, &base); @@ -504,8 +529,10 @@ alignto = MAX(0x800, size); base = ALIGN(io_base, alignto); io_base = base + size; + pcibios_write_config_dword(bus->number, dev->devfn, off, base | 0x1); + new_io_reset(dev, off, orig_base); handle = PCI_HANDLE(bus->number) | base | 1; dev->base_address[idx] = handle; @@ -582,8 +609,11 @@ } } mem_base = base + size; + pcibios_write_config_dword(bus->number, dev->devfn, off, base); + new_io_reset(dev, off, orig_base); + handle = PCI_HANDLE(bus->number) | base; dev->base_address[idx] = handle; @@ -596,9 +626,16 @@ * addresses to be used. */ if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) { - pcibios_write_config_dword(bus->number, - dev->devfn, - off+4, 0); + unsigned int orig_base2; + pcibios_read_config_dword(bus->number, + dev->devfn, + off+4, &orig_base2); + if (0 != orig_base2) { + pcibios_write_config_dword(bus->number, + dev->devfn, + off+4, 0); + new_io_reset (dev, off+4, orig_base2); + } /* Bypass hi reg in the loop. */ dev->base_address[++idx] = 0; @@ -720,10 +757,9 @@ PCI_IO_BASE, l); /* - * Also: - * clear out the upper 16 bits of IO base/limit. - * clear out the upper 32 bits of PREF base/limit. - */ + * Clear out the upper 16 bits of IO base/limit. + * Clear out the upper 32 bits of PREF base/limit. + */ pcibios_write_config_dword(bridge->bus->number, bridge->devfn, PCI_IO_BASE_UPPER16, 0); pcibios_write_config_dword(bridge->bus->number, bridge->devfn, @@ -738,6 +774,7 @@ l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000); pcibios_write_config_dword(bridge->bus->number, bridge->devfn, PCI_MEMORY_BASE, l); + /* * Turn off downstream PF memory address range, unless * there is a VGA behind this bridge, in which case, we @@ -839,7 +876,6 @@ { struct pci_bus *bus = dev->bus; unsigned int reg, orig_base, new_base, found_one = 0; - struct reset_io *ior; for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { /* Read the current setting, check for I/O space and >= 64K */ @@ -870,10 +906,7 @@ pcibios_write_config_dword(bus->number, dev->devfn, reg, new_base); - ior = &srm_resets.io[srm_resets.io_count++]; - ior->dev = dev; - ior->reg = reg; - ior->io = orig_base; + new_io_reset(dev, reg, orig_base); found_one++; } @@ -990,8 +1023,6 @@ &irq_orig); if (irq_orig != dev->irq) { - struct reset_irq *r; - DBG_DEVS(("common_pci_fixup: bus %d " "slot 0x%x SRM IRQ 0x%x " "changed to 0x%x\n", @@ -999,9 +1030,7 @@ PCI_SLOT(dev->devfn), irq_orig, dev->irq)); - r = &srm_resets.irq[srm_resets.irq_count++]; - r->dev = dev; - r->irq = irq_orig; + new_irq_reset(dev, irq_orig); } } diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.1.130/linux/arch/alpha/kernel/process.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/process.c Tue Dec 1 09:33:59 1998 @@ -133,18 +133,15 @@ strncpy((char *)cpup->ipc_buffer, restart_cmd, sizeof(cpup->ipc_buffer)); } - } - else { + } else { flags |= 0x00040000UL; /* "remain halted" */ } cpup->flags = flags; mb(); - if (alpha_use_srm_setup) { - reset_for_srm(); - set_hae(srm_hae); - } + reset_for_srm(); + set_hae(srm_hae); #ifdef CONFIG_DUMMY_CONSOLE /* This has the effect of reseting the VGA video origin. */ @@ -156,10 +153,8 @@ /* Reset rtc to defaults. */ { unsigned char control; - unsigned long flags; - /* I'm not sure if i really need to disable interrupts here. */ - save_and_cli(flags); + cli(); /* Reset periodic interrupt frequency. */ CMOS_WRITE(0x26, RTC_FREQ_SELECT); @@ -170,7 +165,7 @@ CMOS_WRITE(control, RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); - restore_flags(flags); + sti(); } #endif diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.1.130/linux/arch/alpha/kernel/setup.c Fri Nov 27 13:09:22 1998 +++ linux/arch/alpha/kernel/setup.c Tue Dec 1 09:33:59 1998 @@ -43,12 +43,6 @@ #include "proto.h" -#if 1 -# define DBG_SRM(args) printk args -#else -# define DBG_SRM(args) -#endif - struct hwrpb_struct *hwrpb; unsigned long srm_hae; @@ -114,6 +108,7 @@ extern struct alpha_machine_vector miata_mv; 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 noname_mv; extern struct alpha_machine_vector noritake_mv; extern struct alpha_machine_vector noritake_primo_mv; @@ -127,6 +122,34 @@ extern struct alpha_machine_vector takara_mv; extern struct alpha_machine_vector xl_mv; extern struct alpha_machine_vector xlt_mv; +#pragma weak alcor_mv +#pragma weak alphabook1_mv +#pragma weak avanti_mv +#pragma weak cabriolet_mv +#pragma weak dp264_mv +#pragma weak eb164_mv +#pragma weak eb64p_mv +#pragma weak eb66_mv +#pragma weak eb66p_mv +#pragma weak jensen_mv +#pragma weak lx164_mv +#pragma weak miata_mv +#pragma weak mikasa_mv +#pragma weak mikasa_primo_mv +#pragma weak monet_mv +#pragma weak noname_mv +#pragma weak noritake_mv +#pragma weak noritake_primo_mv +#pragma weak p2k_mv +#pragma weak pc164_mv +#pragma weak rawhide_mv +#pragma weak ruffian_mv +#pragma weak sable_mv +#pragma weak sable_gamma_mv +#pragma weak sx164_mv +#pragma weak takara_mv +#pragma weak xl_mv +#pragma weak xlt_mv void __init @@ -197,26 +220,18 @@ cpu->type); } -#ifdef CONFIG_ALPHA_GENERIC if (!vec) { panic("Unsupported system type: %s%s%s (%ld %ld)\n", type_name, (*var_name ? " variation " : ""), var_name, hwrpb->sys_type, hwrpb->sys_variation); } - alpha_mv = *vec; + if (vec != &alpha_mv) + alpha_mv = *vec; +#ifdef CONFIG_ALPHA_GENERIC /* Assume that we've booted from SRM if we havn't booted from MILO. Detect the later by looking for "MILO" in the system serial nr. */ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; -#else - /* Once we're sure we can reliably identify systems, we should - simply panic as we do above. */ - if (vec != &alpha_mv) { - printk("WARNING: Not configured for system type: %s%s%s " - "(%ld %ld)\nContinuing with trepidation...\n", - type_name, (*var_name ? " variation " : ""), var_name, - hwrpb->sys_type, hwrpb->sys_variation); - } #endif printk("Booting on %s%s%s using machine vector %s\n", @@ -361,7 +376,6 @@ static struct alpha_machine_vector * __init get_sysvec(long type, long variation, long cpu) { -#ifdef CONFIG_ALPHA_GENERIC static struct alpha_machine_vector *systype_vecs[] __initlocaldata = { NULL, /* 0 */ @@ -398,7 +412,7 @@ NULL, /* XXM */ &takara_mv, NULL, /* Yukon */ - &dp264_mv, + NULL, /* Tsunami -- see variation. */ NULL, /* Wildfire */ NULL, /* CUSCO */ }; @@ -432,6 +446,19 @@ &eb66p_mv }; + static struct alpha_machine_vector *tsunami_vecs[] __initlocaldata = + { + NULL, + &dp264_mv, /* dp164 */ + &dp264_mv, /* warhol */ + &dp264_mv, /* windjammer */ + &monet_mv, /* monet */ + &dp264_mv, /* clipper */ + &dp264_mv, /* goldrush */ + &dp264_mv, /* webbrick */ + &dp264_mv, /* catamaran */ + }; + /* ??? Do we need to distinguish between Rawhides? */ struct alpha_machine_vector *vec; @@ -472,6 +499,10 @@ if (member < N(eb66_indices)) vec = eb66_vecs[eb66_indices[member]]; break; + case ST_DEC_TSUNAMI: + if (member < N(tsunami_indices)) + vec = tsunami_vecs[tsunami_indices[member]]; + break; case ST_DEC_1000: cpu &= 0xffffffff; if (cpu == EV5_CPU || cpu == EV56_CPU) @@ -496,17 +527,11 @@ } } return vec; -#else - /* TODO: verify that the system is of the type for which we - were configured. For now, cop out and return success. */ - return &alpha_mv; -#endif /* GENERIC */ } static struct alpha_machine_vector * __init get_sysvec_byname(const char *name) { -#ifdef CONFIG_ALPHA_GENERIC static struct alpha_machine_vector *all_vecs[] __initlocaldata = { &alcor_mv, @@ -523,6 +548,7 @@ &miata_mv, &mikasa_mv, &mikasa_primo_mv, + &monet_mv, &noname_mv, &noritake_mv, &noritake_primo_mv, @@ -545,11 +571,6 @@ return mv; } return NULL; -#else - if (strcasecmp(alpha_mv.vector_name, name) == 0) - return &alpha_mv; - return NULL; -#endif } static void diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.1.130/linux/arch/alpha/kernel/sys_dp264.c Fri Nov 27 13:09:22 1998 +++ linux/arch/alpha/kernel/sys_dp264.c Tue Dec 1 09:33:59 1998 @@ -32,16 +32,6 @@ #include "bios32.h" #include "machvec.h" -struct hwrpb_struct *hwrpb; - -/* hwrpb->sys_variation helpers */ -#define MEMBER_ID(x) (((x)>>10)&0x3f) - -#define DP264_ID 1 -#define MONET_ID 4 -#define GOLDRUSH_ID 6 -#define WEBBRICK_ID 7 - #define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index) /* @@ -301,28 +291,22 @@ dp264_pci_fixup(void) { layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(dp264_map_irq, common_swizzle); + SMC669_Init(); +} - /* must do map and/or swizzle different on some */ - switch (MEMBER_ID(hwrpb->sys_variation)) { - case MONET_ID: - common_pci_fixup(monet_map_irq, monet_swizzle); - /* es1888_init(); */ /* later? */ - break; - - case DP264_ID: - case GOLDRUSH_ID: - case WEBBRICK_ID: - default: - common_pci_fixup(dp264_map_irq, common_swizzle); - break; - } /* end MEMBER_ID switch */ - +static void __init +monet_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(monet_map_irq, monet_swizzle); + /* es1888_init(); */ /* later? */ SMC669_Init(); } /* - * The System Vector + * The System Vectors */ struct alpha_machine_vector dp264_mv __initmv = { @@ -347,3 +331,27 @@ kill_arch: generic_kill_arch, }; ALIAS_MV(dp264) + +struct alpha_machine_vector monet_mv __initmv = { + vector_name: "Monet", + 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: monet_pci_fixup, + kill_arch: generic_kill_arch, +}; +/* No alpha_mv alias for monet, since we compile it in unconditionally + with DP264; setup_arch knows how to cope. */ diff -u --recursive --new-file v2.1.130/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.1.130/linux/arch/i386/boot/setup.S Fri Oct 9 13:27:05 1998 +++ linux/arch/i386/boot/setup.S Sat Nov 28 17:18:54 1998 @@ -396,8 +396,6 @@ cmp bx,#0x0504d ! check for "PM" signature jne done_apm_bios ! no signature -> no APM BIOS - mov [64],ax ! record the APM BIOS version - mov [76],cx ! and flags and cx,#0x02 ! Is 32 bit supported? je done_apm_bios ! no ... @@ -416,6 +414,26 @@ mov [74],dx ! BIOS data segment mov [78],esi ! BIOS code segment length mov [82],di ! BIOS data segment length +! +! Redo the installation check as the 32 bit connect +! modifies the flags returned on some BIOSs +! + mov ax,#0x05300 ! APM BIOS installation check + xor bx,bx + int 0x15 + jc apm_disconnect ! error -> should not happen, tidy up + + cmp bx,#0x0504d ! check for "PM" signature + jne apm_disconnect ! no signature -> should not happen, tidy up + + mov [64],ax ! record the APM BIOS version + mov [76],cx ! and flags + jmp done_apm_bios + +apm_disconnect: + mov ax,#0x05304 ! Disconnect + xor bx,bx + int 0x15 ! ignore return code jmp done_apm_bios no_32_apm_bios: diff -u --recursive --new-file v2.1.130/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.1.130/linux/arch/i386/config.in Mon Oct 5 13:13:35 1998 +++ linux/arch/i386/config.in Sat Nov 28 20:32:10 1998 @@ -72,6 +72,7 @@ bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK bool ' Power off on shutdown' CONFIG_APM_POWER_OFF bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE fi endmenu diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.1.130/linux/arch/i386/kernel/apm.c Fri Oct 9 13:27:05 1998 +++ linux/arch/i386/kernel/apm.c Sat Nov 28 17:18:54 1998 @@ -30,6 +30,7 @@ * Feb 1998, Version 1.4 * Aug 1998, Version 1.5 * Sep 1998, Version 1.6 + * Nov 1998, Version 1.7 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -60,6 +61,17 @@ * Fix OOPS at power off with no APM BIOS by Jan Echternach * * Stephen Rothwell + * 1.7: Modify driver's cached copy of the disabled/disengaged flags + * to reflect current state of APM BIOS. + * Chris Rankin + * Reset interrupt 0 timer to 100Hz after suspend + * Chad Miller + * Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE + * Richard Gooch + * Allow boot time disabling of APM + * Make boot messages far less verbose by default + * Make asm safer + * Stephen Rothwell * * APM 1.1 Reference: * @@ -167,7 +179,7 @@ * * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant * [Confirmed by TI representative] - * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification + * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification * [Confirmed by BIOS disassembly] * [This may work now ...] * P: Toshiba 1950S: battery life information only gets updated after resume @@ -215,6 +227,19 @@ #define APM_RELAX_SEGMENTS /* + * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend. + * This patched by Chad Miller , orig code by David + * Chen + */ +#undef INIT_TIMER_AFTER_SUSPEND + +#ifdef INIT_TIMER_AFTER_SUSPEND +#include +#include +#include +#endif + +/* * Need to poll the APM BIOS every second */ #define APM_CHECK_TIMEOUT (HZ) @@ -267,13 +292,15 @@ static long clock_cmos_diff; static int got_clock_diff = 0; +static int debug = 0; +static int apm_disabled = 0; static struct wait_queue * process_list = NULL; static struct apm_bios_struct * user_list = NULL; static struct timer_list apm_timer; -static char driver_version[] = "1.6"; /* no spaces */ +static char driver_version[] = "1.7"; /* no spaces */ #ifdef APM_DEBUG static char * apm_event_name[] = { @@ -393,7 +420,7 @@ # define APM_DO_RESTORE_SEGS #endif -static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in, +static u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi) { unsigned int saved_fs; @@ -404,13 +431,17 @@ APM_DO_CLI; APM_DO_SAVE_SEGS; __asm__ __volatile__(APM_DO_ZERO_SEGS + "pushl %%edi\n\t" + "pushl %%ebp\n\t" "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" "setc %%al\n\t" + "popl %%ebp\n\t" + "popl %%edi\n\t" APM_DO_POP_SEGS - : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx), - "=S" (*esi) + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx), + "=S" (*esi) : "a" (eax_in), "b" (ebx_in), "c" (ecx_in) - : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc"); + : "memory", "cc"); APM_DO_RESTORE_SEGS; __restore_flags(flags); return *eax & 0xff; @@ -420,7 +451,7 @@ * This version only returns one value (usually an error code) */ -static inline u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in, +static u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in, u32 *eax) { u8 error; @@ -431,13 +462,22 @@ __save_flags(flags); APM_DO_CLI; APM_DO_SAVE_SEGS; - __asm__ __volatile__(APM_DO_ZERO_SEGS - "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" - "setc %%bl\n\t" - APM_DO_POP_SEGS - : "=a" (*eax), "=b" (error) - : "a" (eax_in), "b" (ebx_in), "c" (ecx_in) - : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc"); + { + int cx, dx, si; + + __asm__ __volatile__(APM_DO_ZERO_SEGS + "pushl %%edi\n\t" + "pushl %%ebp\n\t" + "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" + "setc %%bl\n\t" + "popl %%ebp\n\t" + "popl %%edi\n\t" + APM_DO_POP_SEGS + : "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx), + "=S" (si) + : "a" (eax_in), "b" (ebx_in), "c" (ecx_in) + : "memory", "cc"); + } APM_DO_RESTORE_SEGS; __restore_flags(flags); return error; @@ -470,7 +510,7 @@ return APM_SUCCESS; } -static inline int set_power_state(u_short what, u_short state) +static int set_power_state(u_short what, u_short state) { u32 eax; @@ -499,7 +539,6 @@ #endif #ifdef CONFIG_APM_DO_ENABLE -/* Called by apm_setup if apm_enabled will be true. */ static int apm_enable_power_management(void) { u32 eax; @@ -508,6 +547,7 @@ (apm_bios_info.version > 0x100) ? 0x0001 : 0xffff, 1, &eax)) return (eax >> 8) & 0xff; + apm_bios_info.flags &= ~APM_BIOS_DISABLED; return APM_SUCCESS; } #endif @@ -574,9 +614,10 @@ for (i = 0; i < ERROR_COUNT; i++) if (error_table[i].key == err) break; if (i < ERROR_COUNT) - printk(KERN_NOTICE "apm_bios: %s: %s\n", str, error_table[i].msg); + printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg); else - printk(KERN_NOTICE "apm_bios: %s: unknown error code %#2.2x\n", str, err); + printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n", + str, err); } /* Called from console driver -- must make sure apm_enabled. */ @@ -629,7 +670,6 @@ callback_list_t ** ptr; callback_list_t * old; - ptr = &callback_list; for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next) if ((*ptr)->callback == callback) break; @@ -663,7 +703,7 @@ static int notified; if (notified == 0) { - printk( "apm_bios: an event queue overflowed\n" ); + printk(KERN_ERR "apm: an event queue overflowed\n"); notified = 1; } as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; @@ -719,6 +759,18 @@ err = apm_set_power_state(APM_STATE_SUSPEND); if (err) apm_error("suspend", err); +#ifdef INIT_TIMER_AFTER_SUSPEND + save_flags(flags); + cli(); + /* set the clock to 100 Hz */ + outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ + udelay(10); + outb_p(LATCH & 0xff , 0x40); /* LSB */ + udelay(10); + outb(LATCH >> 8 , 0x40); /* MSB */ + udelay(10); + restore_flags(flags); +#endif set_time(); } @@ -771,24 +823,27 @@ static void check_events(void) { - apm_event_t event; + apm_event_t event; +#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE + static unsigned long last_resume = 0; + static int did_resume = 0; +#endif while ((event = get_event()) != 0) { #ifdef APM_DEBUG if (event <= NR_APM_EVENT_NAME) - printk(KERN_DEBUG "APM BIOS received %s notify\n", + printk(KERN_DEBUG "apm: received %s notify\n", apm_event_name[event - 1]); else - printk(KERN_DEBUG "APM BIOS received unknown " + printk(KERN_DEBUG "apm: received unknown " "event 0x%02x\n", event); #endif switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - if (waiting_for_resume) { - return; - } + if (waiting_for_resume) + return; waiting_for_resume = 1; #endif send_event(event, APM_STANDBY_RESUME, NULL); @@ -803,10 +858,13 @@ break; #endif case APM_SYS_SUSPEND: +#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE + if (did_resume && ((jiffies - last_resume) < HZ)) + break; +#endif #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - if (waiting_for_resume) { - return; - } + if (waiting_for_resume) + return; waiting_for_resume = 1; #endif send_event(event, APM_NORMAL_RESUME, NULL); @@ -820,6 +878,10 @@ #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND waiting_for_resume = 0; #endif +#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE + last_resume = jiffies; + did_resume = 1; +#endif set_time(); send_event(event, 0, NULL); break; @@ -905,7 +967,7 @@ static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func) { if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { - printk(KERN_ERR "apm_bios: %s passed bad filp", func); + printk(KERN_ERR "apm: %s passed bad filp", func); return 1; } return 0; @@ -1041,7 +1103,7 @@ as1 = as1->next) ; if (as1 == NULL) - printk(KERN_ERR "apm_bios: filp not in user list"); + printk(KERN_ERR "apm: filp not in user list"); else as1->next = as->next; } @@ -1055,7 +1117,7 @@ as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { - printk(KERN_ERR "apm_bios: cannot allocate struct of size %d bytes", + printk(KERN_ERR "apm: cannot allocate struct of size %d bytes", sizeof(*as)); return -ENOMEM; } @@ -1168,6 +1230,26 @@ } #endif +void __init apm_setup(char *str, int *dummy) +{ + int invert; + + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + invert = (strncmp(str, "no-", 3) == 0); + if (invert) + str += 3; + if (strncmp(str, "debug", 5) == 0) + debug = !invert; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } +} + void __init apm_bios_init(void) { unsigned short bx; @@ -1178,23 +1260,18 @@ char * bat_stat; static struct proc_dir_entry *ent; -#ifdef __SMP__ - if (smp_num_cpus > 1) { - printk(KERN_NOTICE "APM disabled: APM is not SMP safe.\n"); - return; - } -#endif if (apm_bios_info.version == 0) { - printk(KERN_INFO "APM BIOS not found.\n"); + printk(KERN_INFO "apm: BIOS not found.\n"); return; } - printk(KERN_INFO "APM BIOS version %c.%c Flags 0x%02x (Driver version %s)\n", - ((apm_bios_info.version >> 8) & 0xff) + '0', - (apm_bios_info.version & 0xff) + '0', - apm_bios_info.flags, - driver_version); + printk(KERN_INFO + "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n", + ((apm_bios_info.version >> 8) & 0xff), + (apm_bios_info.version & 0xff), + apm_bios_info.flags, + driver_version); if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) { - printk(KERN_INFO " No 32 bit BIOS support\n"); + printk(KERN_INFO "apm: no 32 bit BIOS support\n"); return; } @@ -1209,14 +1286,28 @@ if (apm_bios_info.version < 0x102) apm_bios_info.cseg_16_len = 0xFFFF; /* 64k */ - printk(KERN_INFO " Entry %x:%lx cseg16 %x dseg %x", - apm_bios_info.cseg, apm_bios_info.offset, - apm_bios_info.cseg_16, apm_bios_info.dseg); - if (apm_bios_info.version > 0x100) - printk(" cseg len %x, cseg16 len %x, dseg len %x", - apm_bios_info.cseg_len, apm_bios_info.cseg_16_len, - apm_bios_info.dseg_len); - printk("\n"); + if (debug) { + printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x", + apm_bios_info.cseg, apm_bios_info.offset, + apm_bios_info.cseg_16, apm_bios_info.dseg); + if (apm_bios_info.version > 0x100) + printk(" cseg len %x, cseg16 len %x, dseg len %x", + apm_bios_info.cseg_len, + apm_bios_info.cseg_16_len, + apm_bios_info.dseg_len); + printk("\n"); + } + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return; + } +#ifdef __SMP__ + if (smp_num_cpus > 1) { + printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + return; + } +#endif /* * Set up a segment that references the real mode segment 0x40 @@ -1253,74 +1344,78 @@ set_limit(gdt[APM_CS_16 >> 3], apm_bios_info.cseg_16_len); set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len); #endif - /* The APM 1.2 docs state that the apm_driver_version - * call can fail if we try to connect as 1.2 to a 1.1 bios. + /* + * We only support BIOSs up to version 1.2 */ - apm_bios_info.version = 0x0102; - error = apm_driver_version(&apm_bios_info.version); - if (error != APM_SUCCESS) { /* Fall back to an APM 1.1 connection. */ - apm_bios_info.version = 0x0101; - error = apm_driver_version(&apm_bios_info.version); - } - if (error != APM_SUCCESS) /* Fall back to an APM 1.0 connection. */ + if (apm_bios_info.version > 0x0102) + apm_bios_info.version = 0x0102; + if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) { + /* Fall back to an APM 1.0 connection. */ apm_bios_info.version = 0x100; - else { - apm_engage_power_management(0x0001); - printk( " Connection version %d.%d\n", - (apm_bios_info.version >> 8) & 0xff, - apm_bios_info.version & 0xff ); } } - - error = apm_get_power_status(&bx, &cx, &dx); - if (error) - printk(KERN_INFO " Power status not available\n"); - else { - switch ((bx >> 8) & 0xff) { - case 0: power_stat = "off line"; break; - case 1: power_stat = "on line"; break; - case 2: power_stat = "on backup power"; break; - default: power_stat = "unknown"; break; - } - switch (bx & 0xff) { - case 0: bat_stat = "high"; break; - case 1: bat_stat = "low"; break; - case 2: bat_stat = "critical"; break; - case 3: bat_stat = "charging"; break; - default: bat_stat = "unknown"; break; - } - printk(KERN_INFO " AC %s, battery status %s, battery life ", - power_stat, bat_stat); - if ((cx & 0xff) == 0xff) - printk("unknown\n"); - else - printk("%d%%\n", cx & 0xff); - if (apm_bios_info.version > 0x100) { - printk(" battery flag 0x%02x, battery life ", - (cx >> 8) & 0xff); - if (dx == 0xffff) + if (debug) { + printk(KERN_INFO "apm: onnection version %d.%d\n", + (apm_bios_info.version >> 8) & 0xff, + apm_bios_info.version & 0xff ); + + error = apm_get_power_status(&bx, &cx, &dx); + if (error) + printk(KERN_INFO "apm: power status not available\n"); + else { + switch ((bx >> 8) & 0xff) { + case 0: power_stat = "off line"; break; + case 1: power_stat = "on line"; break; + case 2: power_stat = "on backup power"; break; + default: power_stat = "unknown"; break; + } + switch (bx & 0xff) { + case 0: bat_stat = "high"; break; + case 1: bat_stat = "low"; break; + case 2: bat_stat = "critical"; break; + case 3: bat_stat = "charging"; break; + default: bat_stat = "unknown"; break; + } + printk(KERN_INFO "apm: AC %s, battery status %s, battery life ", + power_stat, bat_stat); + if ((cx & 0xff) == 0xff) printk("unknown\n"); - else { - if ((dx & 0x8000)) - printk("%d minutes\n", dx & 0x7ffe ); - else - printk("%d seconds\n", dx & 0x7fff ); + else + printk("%d%%\n", cx & 0xff); + if (apm_bios_info.version > 0x100) { + printk("apm: battery flag 0x%02x, battery life ", + (cx >> 8) & 0xff); + if (dx == 0xffff) + printk("unknown\n"); + else { + if ((dx & 0x8000)) + printk("%d minutes\n", dx & 0x7ffe ); + else + printk("%d seconds\n", dx & 0x7fff ); + } } } } #ifdef CONFIG_APM_DO_ENABLE - /* - * This call causes my NEC UltraLite Versa 33/C to hang if it is - * booted with PM disabled but not in the docking station. - * Unfortunate ... - */ - error = apm_enable_power_management(); - if (error) - apm_error("enable power management", error); - if (error == APM_DISABLED) - return; + if (apm_bios_info.flags & APM_BIOS_DISABLED) { + /* + * This call causes my NEC UltraLite Versa 33/C to hang if it + * is booted with PM disabled but not in the docking station. + * Unfortunate ... + */ + error = apm_enable_power_management(); + if (error) { + apm_error("enable power management", error); + return; + } + } #endif + if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0) + && (apm_bios_info.version > 0x0100)) { + if (apm_engage_power_management(0x0001) == APM_SUCCESS) + apm_bios_info.flags &= ~APM_BIOS_DISENGAGED; + } init_timer(&apm_timer); apm_timer.function = do_apm_timer; diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.130/linux/arch/i386/kernel/process.c Fri Nov 27 13:09:22 1998 +++ linux/arch/i386/kernel/process.c Tue Dec 1 11:28:24 1998 @@ -102,44 +102,25 @@ /* * The idle loop on a uniprocessor i386.. - */ - -asmlinkage int sys_idle(void) + */ +static int cpu_idle(void *unused) { - unsigned long start_idle = 0; - int ret = -EPERM; + unsigned long start_idle = jiffies; - lock_kernel(); - if (current->pid != 0) - goto out; /* endless idle loop with no priority at all */ - current->priority = 0; - current->counter = 0; for (;;) { - /* - * We are locked at this point. So we can safely call - * the APM bios knowing only one CPU at a time will do - * so. - */ - if (!start_idle) { - check_pgt_cache(); - start_idle = jiffies; - } if (jiffies - start_idle > HARD_IDLE_TIMEOUT) hard_idle(); else { if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched) __asm__("hlt"); } - run_task_queue(&tq_scheduler); if (current->need_resched) - start_idle = 0; + start_idle = jiffies; + current->policy = SCHED_YIELD; schedule(); + check_pgt_cache(); } - ret = 0; -out: - unlock_kernel(); - return ret; } #else @@ -150,21 +131,19 @@ int cpu_idle(void *unused) { - current->priority = 0; - while(1) - { - if(current_cpu_data.hlt_works_ok && - !hlt_counter && !current->need_resched) - __asm("hlt"); - check_pgt_cache(); - run_task_queue(&tq_scheduler); - /* endless idle loop with no priority at all */ - current->counter = 0; + /* endless idle loop with no priority at all */ + while(1) { + if (current_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched) + __asm__("hlt"); + current->policy = SCHED_YIELD; schedule(); + check_pgt_cache(); } } +#endif + asmlinkage int sys_idle(void) { if (current->pid != 0) @@ -173,8 +152,6 @@ return 0; } -#endif - /* * This routine reboots the machine by asking the keyboard * controller to pulse the reset-line low. We try that for a while, @@ -509,23 +486,27 @@ */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - long retval; + long retval, d0; __asm__ __volatile__( "movl %%esp,%%esi\n\t" "int $0x80\n\t" /* Linux/i386 system call */ "cmpl %%esp,%%esi\n\t" /* child or parent? */ "je 1f\n\t" /* parent - jump */ - "pushl %3\n\t" /* push argument */ - "call *%4\n\t" /* call fn */ - "movl %2,%0\n\t" /* exit */ + /* Load the argument into eax, and push it. That way, it does + * not matter whether the called function is compiled with + * -mregparm or not. */ + "movl %4,%%eax\n\t" + "pushl %%eax\n\t" + "call *%5\n\t" /* call fn */ + "movl %3,%0\n\t" /* exit */ "int $0x80\n" "1:\t" - :"=a" (retval) + :"=&a" (retval), "=&S" (d0) :"0" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), "b" (flags | CLONE_VM) - :"si"); + : "memory"); return retval; } diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.1.130/linux/arch/i386/kernel/signal.c Mon Oct 5 13:13:35 1998 +++ linux/arch/i386/kernel/signal.c Tue Dec 1 11:28:24 1998 @@ -592,7 +592,7 @@ * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) +int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; struct k_sigaction *ka; diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v2.1.130/linux/arch/i386/kernel/vm86.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/vm86.c Tue Dec 1 11:28:24 1998 @@ -63,7 +63,7 @@ #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1) asmlinkage struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); -asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) +struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) { struct pt_regs *ret; unsigned long tmp; diff -u --recursive --new-file v2.1.130/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.130/linux/arch/i386/mm/init.c Wed Sep 9 14:51:05 1998 +++ linux/arch/i386/mm/init.c Fri Nov 27 12:46:56 1998 @@ -293,11 +293,18 @@ * extended bios data area. * * there is a real-mode segmented pointer pointing to the - * 4K EBDA area at 0x40E, calculate and scan it here: + * 4K EBDA area at 0x40E, calculate and scan it here. + * + * NOTE! There are Linux loaders that will corrupt the EBDA + * area, and as such this kind of SMP config may be less + * trustworthy, simply because the SMP table may have been + * stomped on during early boot. */ address = *(unsigned short *)phys_to_virt(0x40E); address<<=4; smp_scan_config(address, 0x1000); + if (smp_found_config) + printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n"); } #endif start_mem = PAGE_ALIGN(start_mem); diff -u --recursive --new-file v2.1.130/linux/arch/i386/mm/ioremap.c linux/arch/i386/mm/ioremap.c --- v2.1.130/linux/arch/i386/mm/ioremap.c Tue Jul 28 14:21:07 1998 +++ linux/arch/i386/mm/ioremap.c Fri Nov 27 15:03:14 1998 @@ -84,11 +84,16 @@ * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. */ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) { void * addr; struct vm_struct * area; + unsigned long offset; /* * Don't remap the low PCI/ISA area, it's always mapped.. @@ -105,9 +110,9 @@ /* * Mappings have to be page-aligned */ - if (phys_addr & ~PAGE_MASK) - return NULL; - size = PAGE_ALIGN(size); + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(size + offset); /* * Don't allow mappings that wrap.. @@ -126,11 +131,11 @@ vfree(addr); return NULL; } - return addr; + return (void *) (offset + (char *)addr); } void iounmap(void *addr) { if (addr > high_memory) - return vfree(addr); + return vfree((void *) (PAGE_MASK & (unsigned long) addr)); } diff -u --recursive --new-file v2.1.130/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.1.130/linux/drivers/char/keyboard.c Tue Aug 18 22:02:03 1998 +++ linux/drivers/char/keyboard.c Fri Nov 27 10:24:27 1998 @@ -201,7 +201,12 @@ add_keyboard_randomness(scancode); tty = ttytab? ttytab[fg_console]: NULL; - kbd = kbd_table + fg_console; + if (tty && (!tty->driver_data)) { + /* This is to workaround ugly bug in tty_io.c, which + does not do locking when it should */ + tty = NULL; + } + kbd = kbd_table + fg_console; if ((raw_mode = (kbd->kbdmode == VC_RAW))) { put_queue(scancode); /* we do not return yet, because we want to maintain diff -u --recursive --new-file v2.1.130/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.1.130/linux/drivers/char/lp.c Sun Nov 8 14:02:55 1998 +++ linux/drivers/char/lp.c Fri Nov 27 10:23:11 1998 @@ -16,8 +16,17 @@ * Parport sharing hacking by Andrea Arcangeli * Fixed kernel_(to/from)_user memory copy to check for errors * by Riccardo Facchetti - * Interrupt handling workaround for printers with buggy handshake - * by Andrea Arcangeli, 11 May 98 + * Redesigned interrupt handling for handle printers with buggy handshake + * by Andrea Arcangeli, 11 May 1998 + * Full efficient handling of printer with buggy irq handshake (now I have + * understood the meaning of the strange handshake). This is done sending new + * characters if the interrupt is just happened, even if the printer say to + * be still BUSY. This is needed at least with Epson Stylus Color. To enable + * the new TRUST_IRQ mode read the `LP OPTIMIZATION' section below... + * Fixed the irq on the rising edge of the strobe case. + * Obsoleted the CAREFUL flag since a printer that doesn' t work with + * CAREFUL will block a bit after in lp_check_status(). + * Andrea Arcangeli, 15 Oct 1998 */ /* This driver should, in theory, work with any parallel port that has an @@ -49,6 +58,74 @@ * # insmod lp.o reset=1 */ +/* + * LP OPTIMIZATIONS + * + * - TRUST_IRQ flag + * + * Epson Stylus Color, HP and many other new printers want the TRUST_IRQ flag + * set when printing with interrupts. This is a long story. Such printers + * use a broken handshake (see the timing graph below) when printing with + * interrupts. The lp driver as default is just able to handle such bogus + * handshake, but setting such flag cause lp to go faster and probably do + * what such printers want (even if not documented). + * + * NOTE that setting the TRUST_IRQ flag in some printer can cause the irq + * printing to fail completly. You must try, to know if your printer + * will handle it. I suggest a graphics printing to force a major flow of + * characters to the printer for do the test. NOTE also that the TRUST_IRQ + * flag _should_ be fine everywhere but there is a lot of buggy hardware out + * there, so I am forced to implement it as a not-default thing. + * WARNING: before to do the test, be sure to have not played with the + * `-w' parameter of tunelp! + * + * Note also that lp automagically warn you (with a KERN_WARNING) if it + * detects that you could _try_ to set the TRUST_IRQ flag to speed up the + * printing and decrease the CPU load. + * + * To set the TRUST_IRQ flag you can use this command: + * + * tunelp /dev/lp? -T on + * + * If you have an old tunelp executable you can (hack and) use this simple + * C lazy proggy to set the flag in the lp driver: + +-------------------------- cut here ------------------------------------- +#include +#include + +#define LPTRUSTIRQ 0x060f + +int main(int argc, char **argv) +{ + int fd = open("/dev/lp0", O_RDONLY); + ioctl(fd, LPTRUSTIRQ, argc - 1); + if (argc - 1) + printf("trusting the irq\n"); + else + printf("untrusting the irq\n"); + return 0; +} +-------------------------- cut here ------------------------------------- + + * - LP_WAIT time + * + * You can use this setting if your printer is fast enough and/or your + * machine is slow enough ;-). + * + * tunelp /dev/lp? -w 0 + * + * - LP_CHAR tries + * + * If you print with irqs probably you can decrease the CPU load a lot using + * this setting. This is not the default because the printing is reported to + * be jerky somewhere... + * + * tunelp /dev/lp? -c 1 + * + * 11 Nov 1998, Andrea Arcangeli + */ + /* COMPATIBILITY WITH OLD KERNELS * * Under Linux 2.0 and previous versions, lp devices were bound to ports at @@ -79,6 +156,12 @@ * ftp://e-mind.com/pub/linux/pscan/ * * 11 May 98, Andrea Arcangeli + * + * My printer scanner run on an Epson Stylus Color show that such printer + * generates the irq on the _rising_ edge of the STROBE. Now lp handle + * this case fine too. + * + * 15 Oct 1998, Andrea Arcangeli */ #include @@ -95,7 +178,6 @@ #include #undef LP_STATS -#undef LP_NEED_CAREFUL #include #include @@ -115,16 +197,14 @@ NULL, 0, 0, 0} }; -/* Test if printer is ready (and optionally has no error conditions) */ -#ifdef LP_NEED_CAREFUL -#define LP_READY(minor, status) \ - ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY)) -#define _LP_CAREFUL_READY(status) \ - ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \ - (LP_PBUSY|LP_PSELECD|LP_PERRORP) -#else -#define LP_READY(minor, status) ((status) & LP_PBUSY) -#endif +/* Test if printer is ready */ +#define LP_READY(status) ((status) & LP_PBUSY) +/* Test if the printer is not acking the strobe */ +#define LP_NO_ACKING(status) ((status) & LP_PACK) +/* Test if the printer has error conditions */ +#define LP_NO_ERROR(status) \ + (((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \ + (LP_PSELECD|LP_PERRORP)) #undef LP_DEBUG #undef LP_READ_DEBUG @@ -187,60 +267,124 @@ return retval; } +#define lp_wait(minor) udelay(LP_WAIT(minor)) + static inline int lp_char(char lpchar, int minor) { - unsigned int wait = 0; unsigned long count = 0; #ifdef LP_STATS struct lp_stats *stats; #endif + if (signal_pending(current)) + return 0; + for (;;) { + unsigned char status; + int irq_ok = 0; + + /* + * Give a chance to other pardevice to run in the meantime. + */ lp_yield(minor); - if (LP_READY(minor, r_str(minor))) - break; - if (++count == LP_CHAR(minor) || signal_pending(current)) - return 0; + + status = r_str(minor); + if (LP_NO_ERROR(status)) + { + if (LP_READY(status)) + break; + + /* + * This is a crude hack that should be well known + * at least by Epson device driver developers. -arca + */ + irq_ok = (!LP_POLLED(minor) && + LP_NO_ACKING(status) && + lp_table[minor].irq_detected); + if ((LP_F(minor) & LP_TRUST_IRQ) && irq_ok) + break; + } + /* + * NOTE: if you run with irqs you _must_ use + * `tunelp /dev/lp? -c 1' to be rasonable efficient! + */ + if (++count == LP_CHAR(minor)) + { + if (irq_ok) + { + static int first_time = 1; + /* + * The printer is using a buggy handshake, so + * revert to polling to not overload the + * machine and warn the user that its printer + * could get optimized trusting the irq. -arca + */ + lp_table[minor].irq_missed = 1; + if (first_time) + { + first_time = 0; + printk(KERN_WARNING "lp%d: the " + "printing could be optimized " + "using the TRUST_IRQ flag, " + "see the top of " + "linux/drivers/char/lp.c\n", + minor); + } + } + return 0; + } } w_dtr(minor, lpchar); + #ifdef LP_STATS stats = &LP_STAT(minor); stats->chars++; #endif + /* must wait before taking strobe high, and after taking strobe low, according spec. Some printers need it, others don't. */ -#ifndef __sparc__ - while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */ - wait++; -#else - udelay(1); -#endif + lp_wait(minor); + /* control port takes strobe high */ - w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE); -#ifndef __sparc__ - while (wait) /* FIXME: should be a udelay() */ - wait--; -#else - udelay(1); -#endif - /* take strobe low */ if (LP_POLLED(minor)) - /* take strobe low */ - w_ctr(minor, LP_PSELECP | LP_PINITP); - else { + w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE); + lp_wait(minor); + w_ctr(minor, LP_PSELECP | LP_PINITP); + } else { + /* + * Epson Stylus Color generate the IRQ on the rising edge of + * strobe so clean the irq's information before playing with + * the strobe. -arca + */ lp_table[minor].irq_detected = 0; lp_table[minor].irq_missed = 0; + /* + * Be sure that the CPU doesn' t reorder instructions. -arca + */ + mb(); + w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN); + lp_wait(minor); w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN); } + /* + * Give to the printer a chance to put BUSY low. Really we could + * remove this because we could _guess_ that we are slower to reach + * again lp_char() than the printer to put BUSY low, but I' d like + * to remove this variable from the function I go solve + * when I read bug reports ;-). -arca + */ + lp_wait(minor); + #ifdef LP_STATS /* update waittime statistics */ if (count > stats->maxwait) { #ifdef LP_DEBUG - printk(KERN_DEBUG "lp%d success after %d counts.\n", minor, count); + printk(KERN_DEBUG "lp%d success after %d counts.\n", + minor, count); #endif stats->maxwait = count; } @@ -325,7 +469,10 @@ lp_table[minor].irq_detected = 0; lp_table[minor].irq_missed = 1; - w_ctr(minor, LP_PSELECP | LP_PINITP); + if (LP_POLLED(minor)) + w_ctr(minor, LP_PSELECP | LP_PINITP); + else + w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN); do { bytes_written = 0; @@ -396,9 +543,7 @@ goto lp_polling; } if (!lp_table[minor].irq_detected) - { interruptible_sleep_on_timeout(&lp->wait_q, LP_TIMEOUT_INTERRUPT); - } sti(); } } @@ -453,101 +598,97 @@ return (i & 0x0f); } -static inline void lp_select_in_high(int minor) -{ - parport_frob_control(lp_table[minor].dev->port, 8, 8); +static void lp_read_terminate(struct parport *port) { + parport_write_control(port, (parport_read_control(port) & ~2) | 8); + /* SelectIN high, AutoFeed low */ + if (parport_wait_peripheral(port, 0x80, 0)) + /* timeout, SelectIN high, Autofeed low */ + return; + parport_write_control(port, parport_read_control(port) | 2); + /* AutoFeed high */ + parport_wait_peripheral(port, 0x80, 0x80); + /* no timeout possible, Autofeed low, SelectIN high */ + parport_write_control(port, (parport_read_control(port) & ~2) | 8); } /* Status readback confirming to ieee1284 */ static ssize_t lp_read(struct file * file, char * buf, - size_t count, loff_t *ppos) + size_t length, loff_t *ppos) { - unsigned char z=0, Byte=0, status; - char *temp; - ssize_t retval; - unsigned int counter=0; - unsigned int i; + int i; unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev); - - /* Claim Parport or sleep until it becomes available - */ - lp_parport_claim (minor); + char *temp = buf; + ssize_t count = 0; + unsigned char z = 0; + unsigned char Byte = 0; + struct parport *port = lp_table[minor].dev->port; - temp=buf; -#ifdef LP_READ_DEBUG - printk(KERN_INFO "lp%d: read mode\n", minor); -#endif + lp_parport_claim (minor); - retval = verify_area(VERIFY_WRITE, buf, count); - if (retval) - return retval; - if (parport_ieee1284_nibble_mode_ok(lp_table[minor].dev->port, 0)==0) { -#ifdef LP_READ_DEBUG - printk(KERN_INFO "lp%d: rejected IEEE1284 negotiation.\n", - minor); -#endif - lp_select_in_high(minor); - parport_release(lp_table[minor].dev); - return temp-buf; /* End of file */ - } - for (i=0; i<=(count*2); i++) { - parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */ - do { - status = (r_str(minor) & 0x40); - udelay(50); - counter++; - if (current->need_resched) - schedule (); - } while ((status == 0x40) && (counter < 20)); - if (counter == 20) { - /* Timeout */ + switch (parport_ieee1284_nibble_mode_ok(port, 0)) + { + case 0: + /* Handshake failed. */ + lp_read_terminate(port); + lp_parport_release (minor); + return -EIO; + case 1: + /* No data. */ + lp_read_terminate(port); + lp_parport_release (minor); + return 0; + default: + /* Data available. */ + + /* Hack: Wait 10ms (between events 6 and 7) */ + schedule_timeout((HZ+99)/100); + break; + } + + for (i=0; ; i++) { + parport_frob_control(port, 2, 2); /* AutoFeed high */ + if (parport_wait_peripheral(port, 0x40, 0)) { #ifdef LP_READ_DEBUG - printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n"); + /* Some peripherals just time out when they've sent + all their data. */ + printk("%s: read1 timeout.\n", port->name); #endif - parport_frob_control(lp_table[minor].dev->port, 2, 0); - lp_select_in_high(minor); - parport_release(lp_table[minor].dev); - return temp-buf; /* end the read at timeout */ + parport_frob_control(port, 2, 0); /* AutoFeed low */ + break; } - counter=0; z = lp_read_nibble(minor); - parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */ - do { - status=(r_str(minor) & 0x40); - udelay(20); - counter++; - if (current->need_resched) - schedule (); - } while ( (status == 0) && (counter < 20) ); - if (counter == 20) { /* Timeout */ -#ifdef LP_READ_DEBUG - printk(KERN_DEBUG "lp_read: (Autofeed low) timeout\n"); -#endif - if (signal_pending(current)) { - lp_select_in_high(minor); - parport_release(lp_table[minor].dev); - if (temp !=buf) - return temp-buf; - else - return -EINTR; - } - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(LP_TIME(minor)); + parport_frob_control(port, 2, 0); /* AutoFeed low */ + if (parport_wait_peripheral(port, 0x40, 0x40)) { + printk("%s: read2 timeout.\n", port->name); + break; } + if ((i & 1) != 0) { + Byte |= (z<<4); + if (temp) { + if (__put_user (Byte, temp)) + { + count = -EFAULT; + temp = NULL; + } else { + temp++; - counter=0; - - if (( i & 1) != 0) { - Byte= (Byte | z<<4); - if (__put_user(Byte, (char *)temp)) - return -EFAULT; - temp++; - } else Byte=z; + if (++count == length) + temp = NULL; + } + } + /* Does the error line indicate end of data? */ + if ((parport_read_status(port) & LP_PERRORP) == + LP_PERRORP) + break; + } else + Byte=z; } - lp_select_in_high(minor); - lp_parport_release(minor); - return temp-buf; + lp_read_terminate(port); + + lp_parport_release (minor); + + return count; } #endif @@ -645,7 +786,7 @@ else LP_F(minor) &= ~LP_ABORTOPEN; break; -#ifdef LP_NEED_CAREFUL +#ifdef OBSOLETED case LPCAREFUL: if (arg) LP_F(minor) |= LP_CAREFUL; @@ -653,6 +794,12 @@ LP_F(minor) &= ~LP_CAREFUL; break; #endif + case LPTRUSTIRQ: + if (arg) + LP_F(minor) |= LP_TRUST_IRQ; + else + LP_F(minor) &= ~LP_TRUST_IRQ; + break; case LPWAIT: LP_WAIT(minor) = arg; break; @@ -695,7 +842,6 @@ } return retval; } - static struct file_operations lp_fops = { lp_lseek, diff -u --recursive --new-file v2.1.130/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.130/linux/drivers/char/tty_io.c Fri Nov 27 13:09:23 1998 +++ linux/drivers/char/tty_io.c Fri Nov 27 10:24:27 1998 @@ -868,7 +868,13 @@ * Failures after this point use release_mem to clean up, so * there's no need to null out the local pointers. */ - driver->table[idx] = tty; + driver->table[idx] = tty; /* FIXME: this is broken and + probably causes ^D bug. tty->private_date does not (yet) point + to a console, if keypress comes now, await armagedon. + + also, driver->table is accessed from interrupt for vt case, + and this does not look like atomic access at all. */ + if (!*tp_loc) *tp_loc = tp; if (!*ltp_loc) diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx --- v2.1.130/linux/drivers/scsi/ChangeLog.ncr53c8xx Thu Nov 19 09:56:28 1998 +++ linux/drivers/scsi/ChangeLog.ncr53c8xx Sun Nov 29 10:38:43 1998 @@ -1,3 +1,19 @@ +Thu Nov 26 22:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1d + - The SISL RAID change requires now remap_pci_mem() stuff to be + compiled for __i386__ when normal IOs are used. + - Minor spelling fixes in doc files. + +Sat Nov 21 18:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1c + - Ignore chips that are driven by SISL RAID (DAC 960). + Change sent by Leonard Zubkoff and slightly reworked. + - Still a buglet in the tags initial settings that needed to be fixed. + It was not possible to disable TGQ at system startup for devices + that claim TGQ support. The driver used at least 2 for the queue + depth but did'nt keep track of user settings for tags depth lower + than 2. + Wed Nov 11 10:00 1998 Gerard Roudier (groudier@club-internet.fr) * revision 3.1b - The driver was unhappy when configured with default_tags > MAX_TAGS diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx --- v2.1.130/linux/drivers/scsi/README.ncr53c8xx Sun Nov 8 14:03:02 1998 +++ linux/drivers/scsi/README.ncr53c8xx Sun Nov 29 10:38:43 1998 @@ -4,7 +4,7 @@ 21 Rue Carnot 95170 DEUIL LA BARRE - FRANCE -18 October 1998 +22 November 1998 =============================================================================== 1. Introduction @@ -853,7 +853,7 @@ For 810A, 860, 825A, 875 and 895 scsi chips, this option enables support of features that reduce load of PCI bus and memory accesses during scsi transfer processing: burst op-code fetch, read multiple, - read line, prefetch, cache line line, write and invalidate, + read line, prefetch, cache line, write and invalidate, burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only). Can be changed by the following boot setup command: ncr53c8xx=specf:n diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.130/linux/drivers/scsi/ncr53c8xx.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/scsi/ncr53c8xx.c Sun Nov 29 10:38:43 1998 @@ -73,7 +73,7 @@ */ /* -** November 11 1998, version 3.1b +** November 26 1998, version 3.1d ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -582,7 +582,7 @@ #define bus_dvma_to_mem(p) (p) #endif -#ifndef NCR_IOMAPPED +#if defined(__i386__) || !defined(NCR_IOMAPPED) __initfunc( static vm_offset_t remap_pci_mem(u_long base, u_long size) ) @@ -601,7 +601,7 @@ if (vaddr) iounmap((void *) (vaddr & PAGE_MASK)); } -#endif /* !NCR_IOMAPPED */ +#endif /* __i386__ || !NCR_IOMAPPED */ /* ** Insert a delay in micro-seconds and milli-seconds. @@ -2145,7 +2145,6 @@ (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); static void ncr_script_fill (struct script * scr, struct scripth * scripth); static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd); -static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags); static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p); static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); @@ -5837,7 +5836,7 @@ ** If tags was reduced due to queue full, ** increase tags if 1000 good status received. */ - if (lp && lp->numtags < lp->maxtags) { + if (lp && lp->usetags && lp->numtags < lp->maxtags) { ++lp->num_good; if (lp->num_good >= 1000) { lp->num_good = 0; @@ -6537,24 +6536,6 @@ **========================================================== */ -static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags) -{ - if (numtags > tp->usrtags) - numtags = tp->usrtags; - - if (tp) { - int ln; - for (ln = 0; ln < MAX_LUN; ln++) { - lcb_p lp = tp->lp[ln]; - - if (!lp) - continue; - lp->maxtags = lp->numtags = numtags; - ncr_setup_tags (np, (tp - np->target), ln); - } - } -} - static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln) { tcb_p tp = &np->target[tn]; @@ -6671,10 +6652,17 @@ case UC_SETTAGS: for (t=0; tuser.target>>t)&1)) continue; np->target[t].usrtags = np->user.data; - ncr_setmaxtags (np, &np->target[t], np->user.data); - }; + for (ln = 0; ln < MAX_LUN; ln++) { + lcb_p lp = np->target[t].lp[ln]; + if (!lp) + continue; + lp->maxtags = lp->numtags = np->user.data; + ncr_setup_tags (np, t, ln); + } + }; break; case UC_SETDEBUG: @@ -7824,7 +7812,7 @@ ** field of the controller's struct ncb. ** ** Possible cases: hs sir msg_in value send goto -** We try try to negotiate: +** We try to negotiate: ** -> target doesnt't msgin NEG FAIL noop defa. - dispatch ** -> target rejected our msg NEG FAIL reject defa. - dispatch ** -> target answered (ok) NEG SYNC sdtr set - clrack @@ -8718,7 +8706,7 @@ */ if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) { lp->inq_byte7 = inq_byte7; - lp->numtags = tp->usrtags; + lp->numtags = lp->maxtags; ncr_setup_tags (np, tn, ln); } @@ -9622,8 +9610,6 @@ #endif ncr_chip *chip; - printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", - bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); /* * Read info from the PCI config space. * pcibios_read_config_xxx() functions are assumed to be used for @@ -9650,6 +9636,11 @@ PCI_BASE_ADDRESS_1, &base); (void) pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, &base_2); + + /* Handle 64bit base adresses for 53C896. */ + if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + (void) pcibios_read_config_dword(bus, device_fn, + PCI_BASE_ADDRESS_3, &base_2); (void) pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq); #endif @@ -9674,6 +9665,34 @@ chip->revision_id = revision; break; } + +#if defined(__i386__) + /* + * Ignore Symbios chips controlled by SISL RAID controller. + */ + if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) { + unsigned int ScriptsSize, MagicValue; + vm_offset_t ScriptsRAM; + + if (chip->features & FE_RAM8K) + ScriptsSize = 8192; + else + ScriptsSize = 4096; + + ScriptsRAM = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK, + ScriptsSize); + if (ScriptsRAM) { + MagicValue = readl(ScriptsRAM + ScriptsSize - 16); + unmap_pci_mem(ScriptsRAM, ScriptsSize); + if (MagicValue == 0x52414944) + return -1; + } + } +#endif + + printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", + bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); + if (!chip) { printk("ncr53c8xx: not initializing, device not supported\n"); return -1; @@ -10069,6 +10088,7 @@ ncb_p np; tcb_p tp; lcb_p lp; + int numtags; if (device->host != host) continue; @@ -10080,15 +10100,16 @@ /* ** Select queue depth from driver setup. ** Donnot use more than configured by user. - ** Use 2 for devices that donnot support tags. ** Use at least 2. ** Donnot use more than our maximum. */ - device->queue_depth = - device_queue_depth(np, device->id, device->lun); - if (device->queue_depth > tp->usrtags) - device->queue_depth = tp->usrtags; - if (!device->tagged_supported || device->queue_depth < 2) + numtags = device_queue_depth(np, device->id, device->lun); + if (numtags > tp->usrtags) + numtags = tp->usrtags; + if (!device->tagged_supported) + numtags = 1; + device->queue_depth = numtags; + if (device->queue_depth < 2) device->queue_depth = 2; if (device->queue_depth > SCSI_NCR_MAX_TAGS) device->queue_depth = SCSI_NCR_MAX_TAGS; @@ -10098,8 +10119,10 @@ ** we need to know this value in order not to ** announce stupid things to user. */ - if (lp) + if (lp) { + lp->numtags = lp->maxtags = numtags; lp->scdev_depth = device->queue_depth; + } ncr_setup_tags (np, device->id, device->lun); #ifdef DEBUG_NCR53C8XX diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h --- v2.1.130/linux/drivers/scsi/ncr53c8xx.h Thu Nov 19 09:56:28 1998 +++ linux/drivers/scsi/ncr53c8xx.h Tue Dec 1 14:03:09 1998 @@ -45,7 +45,7 @@ /* ** Name and revision of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1b" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1d" /* ** Check supported Linux versions @@ -424,6 +424,10 @@ #define FE_LDSTR (1<<13) #define FE_RAM (1<<14) #define FE_CLK80 (1<<15) +#define FE_RAM8K (1<<16) +#define FE_64BIT (1<<17) +#define FE_IO256 (1<<18) +#define FE_NOPM (1<<19) #define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) #define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) #define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM) @@ -484,7 +488,8 @@ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ , \ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 7, 31, 7, \ - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ + FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\ + FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\ } /* diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c --- v2.1.130/linux/drivers/scsi/scsi_obsolete.c Sun Nov 8 14:03:02 1998 +++ linux/drivers/scsi/scsi_obsolete.c Sun Nov 29 10:40:31 1998 @@ -607,10 +607,9 @@ if ((++SCpnt->retries) < SCpnt->allowed) { if ((SCpnt->retries >= (SCpnt->allowed >> 1)) - /* FIXME: last_reset == 0 is allowed - * && !(SCpnt->host->last_reset > 0 */ && - time_before(jiffies, SCpnt->host->last_reset - + MIN_RESET_PERIOD) + /* FIXME: last_reset == 0 is allowed */ + && time_after(jiffies, SCpnt->host->last_reset + + MIN_RESET_PERIOD) && !(SCpnt->flags & WAS_RESET)) { printk("scsi%d channel %d : resetting for second half of retries.\n", diff -u --recursive --new-file v2.1.130/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.1.130/linux/drivers/sound/sb_common.c Thu Nov 12 16:21:22 1998 +++ linux/drivers/sound/sb_common.c Sun Nov 29 11:18:04 1998 @@ -878,6 +878,7 @@ if(!sb16_set_dma_hw(devc)) { free_irq(devc->irq, devc); + release_region(hw_config->io_base, 16); return 0; } diff -u --recursive --new-file v2.1.130/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.1.130/linux/drivers/video/atyfb.c Fri Nov 27 13:09:27 1998 +++ linux/drivers/video/atyfb.c Sun Nov 29 11:18:04 1998 @@ -973,6 +973,11 @@ #endif #endif + if (! cursor->ram) { + kfree(cursor); + return NULL; + } + if (curblink) { init_timer(cursor->timer); cursor->timer->expires = jiffies + (HZ / 50); @@ -2917,6 +2922,11 @@ info->ati_regbase = (unsigned long) ioremap(info->ati_regbase_phys, 0x1000); + if(!info->ati_regbase) { + kfree(info); + return; + } + info->ati_regbase_phys += 0xc00; info->ati_regbase += 0xc00; @@ -2939,6 +2949,11 @@ info->frame_buffer_phys = addr; info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); + if(!info->frame_buffer) { + kfree(info); + return; + } + #endif /* __sparc__ */ if (!aty_init(info, "PCI")) { @@ -3046,6 +3061,13 @@ info->ati_regbase_phys = 0x7ff000+addr; info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys, 0x1000); + + if(! info->ati_regbase) { + printk("atyfb_init: ioremap() returned NULL\n"); + kfree(info); + return; + } + info->ati_regbase_phys += 0xc00; info->ati_regbase += 0xc00; @@ -3066,6 +3088,12 @@ /* Map in frame buffer */ info->frame_buffer_phys = addr; info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); + + if(! info->frame_buffer) { + printk("atyfb_init: ioremap() returned NULL\n"); + kfree(info); + return; + } if (!aty_init(info, dp->full_name)) { kfree(info); diff -u --recursive --new-file v2.1.130/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.130/linux/fs/affs/namei.c Fri May 8 23:14:50 1998 +++ linux/fs/affs/namei.c Mon Nov 30 16:04:15 1998 @@ -242,8 +242,6 @@ inode = dentry->d_inode; retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto unlink_done; if (current->fsuid != inode->i_uid && current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) goto unlink_done; diff -u --recursive --new-file v2.1.130/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.130/linux/fs/ext2/namei.c Fri Oct 23 22:01:22 1998 +++ linux/fs/ext2/namei.c Tue Dec 1 15:34:08 1998 @@ -661,7 +661,6 @@ if (le32_to_cpu(de->inode) != inode->i_ino) goto end_rmdir; - down(&inode->i_sem); /* * Prune any child dentries so that this dentry becomes negative. */ @@ -686,7 +685,6 @@ retval = ext2_delete_entry (de, bh); dir->i_version = ++event; } - up(&inode->i_sem); if (retval) goto end_rmdir; mark_buffer_dirty(bh, 1); @@ -733,8 +731,6 @@ DQUOT_INIT(inode); retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto end_unlink; if ((dir->i_mode & S_ISVTX) && diff -u --recursive --new-file v2.1.130/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v2.1.130/linux/fs/minix/namei.c Mon Sep 28 10:51:34 1998 +++ linux/fs/minix/namei.c Mon Nov 30 16:04:15 1998 @@ -490,8 +490,6 @@ inode = dentry->d_inode; retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; if (de->inode != inode->i_ino) { brelse(bh); current->counter = 0; diff -u --recursive --new-file v2.1.130/linux/fs/namei.c linux/fs/namei.c --- v2.1.130/linux/fs/namei.c Thu Nov 19 09:56:28 1998 +++ linux/fs/namei.c Tue Dec 1 15:35:03 1998 @@ -834,6 +834,37 @@ return error; } +/* + * Whee.. Deadlock country. Happily there are only two VFS + * operations that do this.. + */ +static inline void double_lock(struct dentry *d1, struct dentry *d2) +{ + struct semaphore *s1 = &d1->d_inode->i_sem; + struct semaphore *s2 = &d2->d_inode->i_sem; + + if (s1 != s2) { + if ((unsigned long) s1 < (unsigned long) s2) { + struct semaphore *tmp = s2; + s2 = s1; s1 = tmp; + } + down(s1); + } + down(s2); +} + +static inline void double_unlock(struct dentry *d1, struct dentry *d2) +{ + struct semaphore *s1 = &d1->d_inode->i_sem; + struct semaphore *s2 = &d2->d_inode->i_sem; + + up(s1); + if (s1 != s2) + up(s2); + dput(d1); + dput(d2); +} + static inline int do_rmdir(const char * name) { int error; @@ -845,13 +876,21 @@ if (IS_ERR(dentry)) goto exit; - dir = lock_parent(dentry); - error = PTR_ERR(dir); - if (IS_ERR(dir)) - goto exit_dput; + dir = dget(dentry->d_parent); error = -ENOENT; if (!dentry->d_inode) + goto exit; + + /* + * The dentry->d_count stuff confuses d_delete() enough to + * not kill the inode from under us while it is locked. This + * wouldn't be needed, except the dentry semaphore is really + * in the inode, not in the dentry.. + */ + dentry->d_count++; + double_lock(dir, dentry); + if (dentry->d_parent != dir) goto exit_lock; error = -EROFS; @@ -886,9 +925,8 @@ error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry); exit_lock: - unlock_dir(dir); -exit_dput: - dput(dentry); + dentry->d_count--; + double_unlock(dentry, dir); exit: return error; } @@ -943,13 +981,16 @@ goto exit_lock; /* + * A directory can't be unlink'ed. * A file cannot be removed from an append-only directory. */ error = -EPERM; + if (S_ISDIR(dentry->d_inode->i_mode)) + goto exit_lock; + if (IS_APPEND(dir->d_inode)) goto exit_lock; - error = -EPERM; if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink) goto exit_lock; @@ -1142,37 +1183,6 @@ } unlock_kernel(); return error; -} - -/* - * Whee.. Deadlock country. Happily there is only one VFS - * operation that does this.. - */ -static inline void double_lock(struct dentry *d1, struct dentry *d2) -{ - struct semaphore *s1 = &d1->d_inode->i_sem; - struct semaphore *s2 = &d2->d_inode->i_sem; - - if (s1 != s2) { - if ((unsigned long) s1 < (unsigned long) s2) { - struct semaphore *tmp = s2; - s2 = s1; s1 = tmp; - } - down(s1); - } - down(s2); -} - -static inline void double_unlock(struct dentry *d1, struct dentry *d2) -{ - struct semaphore *s1 = &d1->d_inode->i_sem; - struct semaphore *s2 = &d2->d_inode->i_sem; - - up(s1); - if (s1 != s2) - up(s2); - dput(d1); - dput(d2); } static inline int do_rename(const char * oldname, const char * newname) diff -u --recursive --new-file v2.1.130/linux/fs/nfs/file.c linux/fs/nfs/file.c --- v2.1.130/linux/fs/nfs/file.c Fri Nov 27 13:09:28 1998 +++ linux/fs/nfs/file.c Tue Dec 1 13:34:51 1998 @@ -240,22 +240,21 @@ if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX) return -ENOLCK; - /* If unlocking a file region, flush dirty pages (unless we've - * been killed by a signal, that is). */ - if (cmd == F_SETLK && fl->fl_type == F_UNLCK - && !signal_pending(current)) { - status = nfs_wb_area(inode, /* current->pid ?*/ - fl->fl_start, fl->fl_end == NLM_OFFSET_MAX? 0 : - fl->fl_end - fl->fl_start + 1); - if (status < 0) - return status; - } + /* + * Flush all pending writes before doing anything + * with locks.. + */ + status = nfs_wb_all(inode); + if (status < 0) + return status; if ((status = nlmclnt_proc(inode, cmd, fl)) < 0) return status; - /* Here, we could turn off write-back of pages in the - * locked file region */ - + /* + * Make sure we re-validate anything we've got cached. + * This makes locking act as a cache coherency point. + */ + NFS_CACHEINV(inode); return 0; } diff -u --recursive --new-file v2.1.130/linux/fs/nfs/write.c linux/fs/nfs/write.c --- v2.1.130/linux/fs/nfs/write.c Fri Nov 27 13:09:28 1998 +++ linux/fs/nfs/write.c Tue Dec 1 11:11:32 1998 @@ -584,15 +584,6 @@ } /* - * Write back everything in a specific area for locking purposes.. - */ -int -nfs_wb_area(struct inode *inode, off_t offset, off_t len) -{ - NFS_WB(inode, 1); -} - -/* * Write back and invalidate. Sometimes we can't leave the stuff * hanging if we can't write it out. */ diff -u --recursive --new-file v2.1.130/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.130/linux/fs/nfsd/vfs.c Sun Nov 8 14:03:07 1998 +++ linux/fs/nfsd/vfs.c Tue Dec 1 13:54:40 1998 @@ -1072,6 +1072,11 @@ if (IS_ERR(rdentry)) goto out_nfserr; + /* + * FIXME!! + * + * This should do a double-lock on both rdentry and the parent + */ err = fh_lock_parent(fhp, rdentry); if (err) goto out; diff -u --recursive --new-file v2.1.130/linux/fs/open.c linux/fs/open.c --- v2.1.130/linux/fs/open.c Thu Nov 19 09:56:28 1998 +++ linux/fs/open.c Tue Dec 1 11:03:25 1998 @@ -797,11 +797,11 @@ printk("VFS: Close: file count is 0\n"); return 0; } - if (dentry->d_inode) - locks_remove_posix(filp, id); retval = 0; if (filp->f_op && filp->f_op->flush) retval = filp->f_op->flush(filp); + if (dentry->d_inode) + locks_remove_posix(filp, id); fput(filp); return retval; } diff -u --recursive --new-file v2.1.130/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c --- v2.1.130/linux/fs/qnx4/namei.c Sat Sep 5 16:46:41 1998 +++ linux/fs/qnx4/namei.c Mon Nov 30 16:04:15 1998 @@ -245,9 +245,6 @@ goto end_unlink; } retval = -EPERM; - if (S_ISDIR(inode->i_mode)) { - goto end_unlink; - } if ((dir->i_mode & S_ISVTX) && current->fsuid != inode->i_uid && current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) { diff -u --recursive --new-file v2.1.130/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v2.1.130/linux/fs/sysv/namei.c Wed May 20 19:10:41 1998 +++ linux/fs/sysv/namei.c Mon Nov 30 16:04:15 1998 @@ -476,8 +476,6 @@ inode = dentry->d_inode; retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; if (de->inode != inode->i_ino) { brelse(bh); current->counter = 0; diff -u --recursive --new-file v2.1.130/linux/fs/ufs/namei.c linux/fs/ufs/namei.c --- v2.1.130/linux/fs/ufs/namei.c Fri Oct 23 22:01:22 1998 +++ linux/fs/ufs/namei.c Tue Dec 1 13:52:19 1998 @@ -701,7 +701,6 @@ if (SWAB32(de->d_ino) != inode->i_ino) goto end_rmdir; - down(&inode->i_sem); /* * Prune any child dentries so that this dentry becomes negative. */ @@ -727,7 +726,6 @@ retval = ufs_delete_entry (dir, de, bh); dir->i_version = ++event; } - up(&inode->i_sem); if (retval) goto end_rmdir; mark_buffer_dirty(bh, 1); @@ -784,8 +782,6 @@ inode->i_sb->dq_op->initialize (inode, -1); retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto end_unlink; if ((dir->i_mode & S_ISVTX) && diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/README-WIP.txt linux/fs/umsdos/README-WIP.txt --- v2.1.130/linux/fs/umsdos/README-WIP.txt Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/README-WIP.txt Sun Nov 29 11:43:13 1998 @@ -2,21 +2,19 @@ (started by Peter T. Waltenberg ) (Final conversion to dentries Bill Hawes ) ----------- WARNING --------- WARNING --------- WARNING ----------- There is no warning any more. Both read-only and read-write stuff is fixed, both in msdos-compatibile mode, and in umsdos EMD mode, and it seems stable. -There are still few symlink/hardlink nuisances, but those are not fatal. +There are still few hardlink nuisances, but those are not fatal. -I'd call it wide beta, and ask for as many people as possible to +I'd call it pre-release, and ask for as many people as possible to come and test it! See notes below for some more information, or if you are trying to use UMSDOS as root partition. ----------- WARNING --------- WARNING --------- WARNING ----------- Legend: those lines marked with '+' on the beggining of line indicates it passed all of my tests, and performed perfect in all of them. -Current status (981018) - UMSDOS dentry-Beta 0.83: +Current status (981129) - UMSDOS dentry-pre 0.84: (1) pure MSDOS (no --linux-.--- EMD file): @@ -51,13 +49,13 @@ + resolve symlink - works + dereference symlink - works + dangling symlink - works -- hard links - seems to work mostly ++ hard links - works + special files (block/char devices, FIFOs, sockets...) - works -- various umsdos ioctls - works ++ various umsdos ioctls - works WRITE: -- create symlink - works mostly, but see WARNING below ++ create symlink - works - create hardlink - works, but see portability WARNING below + create file - works + create special file - works @@ -66,16 +64,16 @@ + rename file (dif. dir) - works - rename hardlink (same dir) - - rename hardlink (dif. dir) - -- rename symlink (same dir) - -- rename symlink (dif. dir) - problems sometimes. see warning below. ++ rename symlink (same dir) - works ++ rename symlink (dif. dir) - works + rename dir (same dir) - works + rename dir (dif. dir) - works + delete file - works + notify_change (chown,perms) - works + delete hardlink - works + mkdir - works -- rmdir - HMMM. see with clean --linux-.--- files... -- umssyncing (many ioctls) - works ++ rmdir - works ++ umssyncing (many ioctls) - works - CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank @@ -91,13 +89,6 @@ example is specs file about it. Specifically, moving directory which contains hardlinks will break them. -Warning: moving symlinks around may break them until umount/remount. - -Warning: I seem to able to reproduce one problem with creting symlink after -I rm -rf directory: it is manifested as symlink apperantly being regular -file instead of symlink until next umount/mount pair. Tracking this one -down... - Note: (about pseudoroot) If you are currently trying to use UMSDOS as root partition (with linux installed in c:\linux) it will boot, but there are some problems. Volunteers ready to test pseudoroot are needed (preferably @@ -105,7 +96,8 @@ different interpretation of hard links in normal in pseudo-root modes, resulting is 'silent delete' of them sometimes. Also, '/DOS' pseudo directory is only partially re-implemented and buggy. It works most of the -time, though. +time, though. Update: should work ok in 0.84, although it still does not +work correctly in combination with initrd featere. Working on this! Warning: (about creating hardlinks in pseudoroot mode) - hardlinks created in pseudoroot mode are not compatibile with 'normal' hardlinks, and vice versa. @@ -114,6 +106,8 @@ people either always use pseudoroot, or always use normal umsdos filesystem, this is no showstopper. +Warning: (about hardlinks) - modifying hardlinks (esp. if there are in +different directories) are currently somewhat broken, I'm working on it. ------------------------------------------------------------------------------ diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/check.c linux/fs/umsdos/check.c --- v2.1.130/linux/fs/umsdos/check.c Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/check.c Sun Nov 29 11:43:13 1998 @@ -66,10 +66,10 @@ void check_sb (struct super_block *sb, const char c) { if (sb) { - Printk ((" (has %c_sb=%d, %d)", - c, MAJOR (sb->s_dev), MINOR (sb->s_dev))); + printk (" (has %c_sb=%d, %d)", + c, MAJOR (sb->s_dev), MINOR (sb->s_dev)); } else { - Printk ((" (%c_sb is NULL)", c)); + printk (" (%c_sb is NULL)", c); } } @@ -81,35 +81,37 @@ void check_inode (struct inode *inode) { if (inode) { - Printk ((KERN_DEBUG "* inode is %lu (i_count=%d)", - inode->i_ino, inode->i_count)); + printk (KERN_DEBUG "* inode is %lu (i_count=%d)", + inode->i_ino, inode->i_count); check_sb (inode->i_sb, 'i'); if (inode->i_dentry.next) { /* FIXME: does this work ? */ - Printk ((" (has i_dentry)")); + printk (" (has i_dentry)"); } else { - Printk ((" (NO i_dentry)")); + printk (" (NO i_dentry)"); } + printk (" (i_patched=%d)", inode->u.umsdos_i.i_patched); + if (inode->i_op == NULL) { - Printk ((" (i_op is NULL)\n")); + printk (" (i_op is NULL)\n"); } else if (inode->i_op == &umsdos_dir_inode_operations) { - Printk ((" (i_op is umsdos_dir_inode_operations)\n")); + printk (" (i_op is umsdos_dir_inode_operations)\n"); } else if (inode->i_op == &umsdos_file_inode_operations) { - Printk ((" (i_op is umsdos_file_inode_operations)\n")); + printk (" (i_op is umsdos_file_inode_operations)\n"); } else if (inode->i_op == &umsdos_file_inode_operations_no_bmap) { - Printk ((" (i_op is umsdos_file_inode_operations_no_bmap)\n")); + printk (" (i_op is umsdos_file_inode_operations_no_bmap)\n"); } else if (inode->i_op == &umsdos_file_inode_operations_readpage) { - Printk ((" (i_op is umsdos_file_inode_operations_readpage)\n")); + printk (" (i_op is umsdos_file_inode_operations_readpage)\n"); } else if (inode->i_op == &umsdos_rdir_inode_operations) { - Printk ((" (i_op is umsdos_rdir_inode_operations)\n")); + printk (" (i_op is umsdos_rdir_inode_operations)\n"); } else if (inode->i_op == &umsdos_symlink_inode_operations) { - Printk ((" (i_op is umsdos_symlink_inode_operations)\n")); + printk (" (i_op is umsdos_symlink_inode_operations)\n"); } else { - Printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op)); + printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op)); } } else { - Printk ((KERN_DEBUG "* inode is NULL\n")); + printk (KERN_DEBUG "* inode is NULL\n"); } } @@ -127,40 +129,40 @@ return; } - Printk ((KERN_DEBUG "checkd_inode: inode %lu\n", inode->i_ino)); + printk (KERN_DEBUG "checkd_inode: inode %lu\n", inode->i_ino); cur = inode->i_dentry.next; while (count++ < 10) { PRINTK (("1...")); if (!cur) { - Printk ((KERN_ERR "checkd_inode: *** NULL reached. exit.\n")); + printk (KERN_ERR "checkd_inode: *** NULL reached. exit.\n"); return; } PRINTK (("2...")); ret = list_entry (cur, struct dentry, d_alias); PRINTK (("3...")); if (cur == cur->next) { - Printk ((KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n")); + printk (KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n"); return; } PRINTK (("4...")); if (!ret) { - Printk ((KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n")); + printk (KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n"); return; } PRINTK (("5... (ret=%p)...", ret)); PRINTK (("5.1.. (ret->d_dname=%p)...", &(ret->d_name))); PRINTK (("5.1.1. (ret->d_dname.len=%d)...", (int) ret->d_name.len)); PRINTK (("5.1.2. (ret->d_dname.name=%c)...", ret->d_name.name)); - Printk ((KERN_DEBUG "checkd_inode: i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name)); + printk (KERN_DEBUG "checkd_inode: i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name); PRINTK (("6...")); cur = cur->next; PRINTK (("7...")); #if 1 - Printk ((KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n")); + printk (KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n"); return; #endif } - Printk ((KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n")); + printk (KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n"); return; } @@ -172,19 +174,19 @@ void check_dent_int (struct dentry *dentry, int parent) { if (parent) { - Printk ((KERN_DEBUG "* parent(%d) dentry: %.*s\n", - parent, (int) dentry->d_name.len, dentry->d_name.name)); + printk (KERN_DEBUG "* parent(%d) dentry: %.*s\n", + parent, (int) dentry->d_name.len, dentry->d_name.name); } else { - Printk ((KERN_DEBUG "* checking dentry: %.*s\n", - (int) dentry->d_name.len, dentry->d_name.name)); + printk (KERN_DEBUG "* checking dentry: %.*s\n", + (int) dentry->d_name.len, dentry->d_name.name); } check_inode (dentry->d_inode); - Printk ((KERN_DEBUG "* d_count=%d", dentry->d_count)); + printk (KERN_DEBUG "* d_count=%d", dentry->d_count); check_sb (dentry->d_sb, 'd'); if (dentry->d_op == NULL) { - Printk ((" (d_op is NULL)\n")); + printk (" (d_op is NULL)\n"); } else { - Printk ((" (d_op is UNKNOWN: %p)\n", dentry->d_op)); + printk (" (d_op is UNKNOWN: %p)\n", dentry->d_op); } } @@ -196,35 +198,35 @@ void check_dentry_path (struct dentry *dentry, const char *desc) { int count=0; - Printk ((KERN_DEBUG "*** check_dentry_path: %.60s\n", desc)); + printk (KERN_DEBUG "*** check_dentry_path: %.60s\n", desc); if (!dentry) { - Printk ((KERN_DEBUG "*** checking dentry... it is NULL !\n")); + printk (KERN_DEBUG "*** checking dentry... it is NULL !\n"); return; } if (IS_ERR(dentry)) { - Printk ((KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n", - PTR_ERR(dentry))); + printk (KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n", + PTR_ERR(dentry)); return; } while (dentry && count < 10) { check_dent_int (dentry, count++); if (dentry == dentry->d_parent) { - Printk ((KERN_DEBUG "*** end checking dentry (root reached ok)\n")); + printk (KERN_DEBUG "*** end checking dentry (root reached ok)\n"); break; } dentry = dentry->d_parent; } if (count >= 10) { /* if infinite loop detected */ - Printk ((KERN_ERR - "*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n")); + printk (KERN_ERR + "*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n"); } if (!dentry) { - Printk ((KERN_ERR - "*** WARNING ! NULL dentry ! check_dentry_path aborted !\n")); + printk (KERN_ERR + "*** WARNING ! NULL dentry ! check_dentry_path aborted !\n"); } } #else diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c --- v2.1.130/linux/fs/umsdos/dir.c Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/dir.c Sun Nov 29 11:43:13 1998 @@ -383,7 +383,6 @@ if (inode->u.umsdos_i.i_patched) goto out; inode->u.umsdos_i.i_patched = 1; - if (S_ISREG (entry->mode)) entry->mtime = inode->i_mtime; inode->i_mode = entry->mode; diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c --- v2.1.130/linux/fs/umsdos/inode.c Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/inode.c Sun Nov 29 11:43:13 1998 @@ -60,6 +60,7 @@ " Notify jacques@solucorp.qc.ca\n"); } + inode->u.umsdos_i.i_patched = 0; fat_put_inode (inode); } @@ -125,15 +126,6 @@ } -/* - * Tells if an Umsdos inode has been "patched" once. - * Return != 0 if so. - */ -int umsdos_isinit (struct inode *inode) -{ - return 0; /* inode->u.umsdos_i.i_emd_owner != 0; */ -} - /* * Connect the proper tables in the inode and add some info. @@ -200,7 +192,7 @@ */ void UMSDOS_read_inode (struct inode *inode) { - PRINTK ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ", + Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ", inode, inode->i_ino)); msdos_read_inode (inode); @@ -235,8 +227,8 @@ struct file filp; struct umsdos_dirent entry; -Printk(("UMSDOS_notify_change: entering for %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name)); +Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n", +dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched)); ret = inode_change_ok (inode, attr); if (ret) { @@ -348,7 +340,8 @@ * But it has the side effect to re"dirt" the inode. */ /* - * internal_notify_change (inode, &newattrs); + * UMSDOS_notify_change (inode, &newattrs); + * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work. We need to remove ourselves from list on dirty inodes. /mn/ */ } @@ -385,7 +378,7 @@ if (!res) goto out_fail; - printk (KERN_INFO "UMSDOS dentry-Beta 0.83 " + printk (KERN_INFO "UMSDOS dentry-pre 0.84 " "(compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE); diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c --- v2.1.130/linux/fs/umsdos/namei.c Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/namei.c Tue Dec 1 13:52:47 1998 @@ -1020,11 +1020,6 @@ goto out; } - /* - * Lock the directory, then check whether it's empty. - */ - down(&dentry->d_inode->i_sem); - /* check whether the EMD is empty */ ret = -ENOTEMPTY; empty = umsdos_isempty (dentry); @@ -1050,7 +1045,6 @@ } } else if (empty == 2) ret = 0; - up(&dentry->d_inode->i_sem); if (ret) goto out; diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c --- v2.1.130/linux/fs/umsdos/rdir.c Sun Nov 8 14:03:08 1998 +++ linux/fs/umsdos/rdir.c Tue Dec 1 13:53:24 1998 @@ -83,17 +83,17 @@ { int ret; - /* N.B. this won't work ... lookups of `..' are done by VFS */ -#ifdef BROKEN_TO_BITS - if (pseudo_root && len == 2 && name[0] == '.' && name[1] == '.' && - dir == saved_root->d_inode) { -printk (KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n"); - pseudo_root->i_count++; - d_add(dentry, pseudo_root); - ret = 0; + if (saved_root && dir == saved_root->d_inode && !nopseudo && + dentry->d_name.len == UMSDOS_PSDROOT_LEN && + memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) { + /* #Specification: pseudo root / DOS/linux + * Even in the real root directory (c:\), the directory + * /linux won't show + */ + + ret = -ENOENT; goto out; } -#endif ret = msdos_lookup (dir, dentry); if (ret) { @@ -111,20 +111,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name)); umsdos_patch_dentry_inode(dentry, 0); - /* N.B. Won't work -- /linux dentry will already have - * an inode, so we'll never get called here. - */ -#ifdef BROKEN_TO_BITS - if (dentry->d_inode == pseudo_root && !nopseudo) { - /* #Specification: pseudo root / DOS/linux - * Even in the real root directory (c:\), the directory - * /linux won't show - */ -printk(KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n"); - /* make the dentry negative */ - d_delete(dentry); - } -#endif } out: /* always install our dentry ops ... */ @@ -180,7 +166,6 @@ if (ret != -ENOTEMPTY) goto out; - down(&dentry->d_inode->i_sem); empty = umsdos_isempty (dentry); if (empty == 1) { struct dentry *demd; @@ -194,7 +179,6 @@ dput(demd); } } - up(&dentry->d_inode->i_sem); if (ret) goto out; diff -u --recursive --new-file v2.1.130/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h --- v2.1.130/linux/include/asm-i386/semaphore.h Fri Nov 27 13:09:28 1998 +++ linux/include/asm-i386/semaphore.h Tue Dec 1 13:34:47 1998 @@ -36,9 +36,9 @@ asmlinkage int __down_failed_interruptible(void /* params in registers */); asmlinkage void __up_wakeup(void /* special register calling convention */); -extern void __down(struct semaphore * sem); -extern int __down_interruptible(struct semaphore * sem); -extern void __up(struct semaphore * sem); +asmlinkage void __down(struct semaphore * sem); +asmlinkage int __down_interruptible(struct semaphore * sem); +asmlinkage void __up(struct semaphore * sem); extern spinlock_t semaphore_wake_lock; diff -u --recursive --new-file v2.1.130/linux/include/linux/apm_bios.h linux/include/linux/apm_bios.h --- v2.1.130/linux/include/linux/apm_bios.h Fri Oct 9 13:27:15 1998 +++ linux/include/linux/apm_bios.h Sat Nov 28 17:18:54 1998 @@ -77,6 +77,7 @@ extern struct apm_bios_info apm_bios_info; extern void apm_bios_init(void); +extern void apm_setup(char *, int *); extern int apm_register_callback(int (*callback)(apm_event_t)); extern void apm_unregister_callback(int (*callback)(apm_event_t)); diff -u --recursive --new-file v2.1.130/linux/include/linux/linkage.h linux/include/linux/linkage.h --- v2.1.130/linux/include/linux/linkage.h Fri Oct 9 13:27:16 1998 +++ linux/include/linux/linkage.h Tue Dec 1 11:28:24 1998 @@ -2,9 +2,15 @@ #define _LINUX_LINKAGE_H #ifdef __cplusplus -#define asmlinkage extern "C" +#define CPP_ASMLINKAGE extern "C" #else -#define asmlinkage +#define CPP_ASMLINKAGE +#endif + +#if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7) +#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) +#else +#define asmlinkage CPP_ASMLINKAGE #endif #define SYMBOL_NAME_STR(X) #X diff -u --recursive --new-file v2.1.130/linux/include/linux/lp.h linux/include/linux/lp.h --- v2.1.130/linux/include/linux/lp.h Thu Nov 19 09:56:29 1998 +++ linux/include/linux/lp.h Fri Nov 27 10:23:11 1998 @@ -25,10 +25,9 @@ #define LP_NOPA 0x0010 #define LP_ERR 0x0020 #define LP_ABORT 0x0040 -#ifdef LP_NEED_CAREFUL -#define LP_CAREFUL 0x0080 -#endif +#define LP_CAREFUL 0x0080 /* obsoleted -arca */ #define LP_ABORTOPEN 0x0100 +#define LP_TRUST_IRQ 0x0200 /* timeout for each character. This is relative to bus cycles -- it * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you @@ -41,13 +40,10 @@ #define LP_INIT_CHAR 1000 /* The parallel port specs apparently say that there needs to be - * a .5usec wait before and after the strobe. Since there are wildly - * different computers running linux, I can't come up with a perfect - * value so if 20 is not good for you use `tunelp /dev/lp? -w ?`. - * You can also set it to 0 if your printer handle that. + * a .5usec wait before and after the strobe. */ -#define LP_INIT_WAIT 20 +#define LP_INIT_WAIT 1 /* This is the amount of time that the driver waits for the printer to * catch up when the printer's buffer appears to be filled. If you @@ -70,11 +66,10 @@ or 0 for polling (no IRQ) */ #define LPGETIRQ 0x0606 /* get the current IRQ number */ #define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */ -#ifdef LP_NEED_CAREFUL +/* NOTE: LPCAREFUL is obsoleted and it' s always the default right now -arca */ #define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off- line, and error indicators good on all writes, FALSE to ignore them. Default is ignore. */ -#endif #define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error, FALSE to ignore error. Default is ignore. */ #define LPGETSTATUS 0x060b /* return LP_S(minor) */ @@ -83,6 +78,7 @@ #define LPGETSTATS 0x060d /* get statistics (struct lp_stats) */ #endif #define LPGETFLAGS 0x060e /* get status flags */ +#define LPTRUSTIRQ 0x060f /* set/unset the LP_TRUST_IRQ flag */ /* timeout for printk'ing a timeout, in jiffies (100ths of a second). This is also used for re-checking error conditions if LP_ABORT is @@ -96,7 +92,7 @@ #define LP_TIME(minor) lp_table[(minor)].time /* wait time */ #define LP_WAIT(minor) lp_table[(minor)].wait /* strobe wait */ #define LP_IRQ(minor) lp_table[(minor)].dev->port->irq /* interrupt # */ - /* 0 means polled */ + /* PARPORT_IRQ_NONE means polled */ #ifdef LP_STATS #define LP_STAT(minor) lp_table[(minor)].stats /* statistics area */ #endif diff -u --recursive --new-file v2.1.130/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h --- v2.1.130/linux/include/linux/nfs_fs.h Fri Nov 27 13:09:29 1998 +++ linux/include/linux/nfs_fs.h Tue Dec 1 14:07:51 1998 @@ -222,7 +222,6 @@ extern int nfs_wb_all(struct inode *); extern int nfs_wb_page(struct inode *, struct page *); extern int nfs_wb_pid(struct inode *, pid_t); -extern int nfs_wb_area(struct inode *, off_t, off_t); /* * Invalidate write-backs, possibly trying to write them diff -u --recursive --new-file v2.1.130/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.130/linux/include/linux/pci.h Fri Nov 27 13:09:29 1998 +++ linux/include/linux/pci.h Tue Dec 1 14:02:25 1998 @@ -615,6 +615,7 @@ #define PCI_DEVICE_ID_MADGE_C155S 0x1001 #define PCI_VENDOR_ID_3COM 0x10b7 +#define PCI_DEVICE_ID_3COM_3C985 0x0001 #define PCI_DEVICE_ID_3COM_3C339 0x3390 #define PCI_DEVICE_ID_3COM_3C590 0x5900 #define PCI_DEVICE_ID_3COM_3C595TX 0x5950 diff -u --recursive --new-file v2.1.130/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.1.130/linux/include/linux/swap.h Mon Sep 28 10:51:35 1998 +++ linux/include/linux/swap.h Tue Dec 1 11:28:24 1998 @@ -107,8 +107,8 @@ int next; /* swapfile to be used next */ }; extern struct swap_list_t swap_list; -int sys_swapoff(const char *); -int sys_swapon(const char *, int); +asmlinkage int sys_swapoff(const char *); +asmlinkage int sys_swapon(const char *, int); /* * vm_ops not present page codes for shared memory. diff -u --recursive --new-file v2.1.130/linux/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h --- v2.1.130/linux/include/linux/umsdos_fs.h Wed Sep 9 14:51:13 1998 +++ linux/include/linux/umsdos_fs.h Tue Dec 1 14:09:32 1998 @@ -1,7 +1,9 @@ #ifndef LINUX_UMSDOS_FS_H #define LINUX_UMSDOS_FS_H -/* #define UMSDOS_DEBUG 1 */ + +#define UMS_DEBUG 1 /* define for check_* functions */ +/*#define UMSDOS_DEBUG 1*/ #define UMSDOS_PARANOIA 1 #define UMSDOS_VERSION 0 diff -u --recursive --new-file v2.1.130/linux/include/linux/umsdos_fs.p linux/include/linux/umsdos_fs.p --- v2.1.130/linux/include/linux/umsdos_fs.p Mon Sep 28 10:51:36 1998 +++ linux/include/linux/umsdos_fs.p Sun Nov 29 11:43:13 1998 @@ -57,7 +57,6 @@ void umsdos_setup_dir(struct dentry *); void umsdos_set_dirinfo_new(struct dentry *, off_t); -int umsdos_isinit (struct inode *inode); void umsdos_patch_dentry_inode (struct dentry *, off_t); int umsdos_get_dirowner (struct inode *inode, struct inode **result); diff -u --recursive --new-file v2.1.130/linux/init/main.c linux/init/main.c --- v2.1.130/linux/init/main.c Fri Nov 27 13:09:29 1998 +++ linux/init/main.c Sun Nov 29 10:37:02 1998 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,10 @@ # include #endif +#ifdef CONFIG_APM +#include +#endif + /* * Versions of gcc older than that listed below may actually compile * and link okay, but the end product can have subtle run time bugs. @@ -864,6 +869,9 @@ #endif #ifdef CONFIG_PARIDE_PG { "pg.", pg_setup }, +#endif +#ifdef CONFIG_APM + { "apm=", apm_setup }, #endif { 0, 0 } }; diff -u --recursive --new-file v2.1.130/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.130/linux/kernel/fork.c Fri Nov 27 13:09:29 1998 +++ linux/kernel/fork.c Fri Nov 27 10:17:08 1998 @@ -137,7 +137,7 @@ { struct task_struct **tslot = NULL; - if (!current->uid || (nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT)) + if ((nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) || !current->uid) tslot = get_free_taskslot(); return tslot; } diff -u --recursive --new-file v2.1.130/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.130/linux/mm/filemap.c Fri Nov 27 13:09:30 1998 +++ linux/mm/filemap.c Fri Nov 27 10:29:12 1998 @@ -200,8 +200,8 @@ struct page * page; int count_max, count_min; - count_max = (limit<<1) >> (priority>>1); - count_min = (limit<<1) >> (priority); + count_max = limit; + count_min = (limit<<2) >> (priority); page = mem_map + clock; do { @@ -214,7 +214,15 @@ if (shrink_one_page(page, gfp_mask)) return 1; count_max--; - if (page->inode || page->buffers) + /* + * If the page we looked at was recyclable but we didn't + * reclaim it (presumably due to PG_referenced), don't + * count it as scanned. This way, the more referenced + * page cache pages we encounter, the more rapidly we + * will age them. + */ + if (atomic_read(&page->count) != 1 || + (!page->inode && !page->buffers)) count_min--; page++; clock++; diff -u --recursive --new-file v2.1.130/linux/mm/swap.c linux/mm/swap.c --- v2.1.130/linux/mm/swap.c Fri Nov 27 13:09:30 1998 +++ linux/mm/swap.c Fri Nov 27 10:15:29 1998 @@ -62,13 +62,13 @@ buffer_mem_t buffer_mem = { 5, /* minimum percent buffer */ - 25, /* borrow percent buffer */ + 10, /* borrow percent buffer */ 60 /* maximum percent buffer */ }; buffer_mem_t page_cache = { 5, /* minimum percent page cache */ - 30, /* borrow percent page cache */ + 15, /* borrow percent page cache */ 75 /* maximum */ }; diff -u --recursive --new-file v2.1.130/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.130/linux/mm/vmscan.c Fri Nov 27 13:09:31 1998 +++ linux/mm/vmscan.c Mon Nov 30 16:05:40 1998 @@ -431,7 +431,7 @@ kmem_cache_reap(gfp_mask); if (buffer_over_borrow() || pgcache_over_borrow()) - shrink_mmap(i, gfp_mask); + state = 0; switch (state) { do { diff -u --recursive --new-file v2.1.130/linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- v2.1.130/linux/net/ipv4/Config.in Mon Oct 5 13:13:48 1998 +++ linux/net/ipv4/Config.in Fri Nov 27 10:13:53 1998 @@ -31,21 +31,23 @@ define_bool CONFIG_NETLINK_DEV y fi fi - bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY - bool 'IP: always defragment' CONFIG_IP_ALWAYS_DEFRAG + bool 'IP: always defragment (required for masquerading)' CONFIG_IP_ALWAYS_DEFRAG fi fi if [ "$CONFIG_IP_FIREWALL" = "y" ]; then - bool 'IP: masquerading' CONFIG_IP_MASQUERADE - if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then - comment 'Protocol-specific masquerading support will be built as modules.' - bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP - comment 'Protocol-specific masquerading support will be built as modules.' - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD - if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then - tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW - tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW + if [ "$CONFIG_IP_ALWAYS_DEFRAG" != "n" ]; then + bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY + bool 'IP: masquerading' CONFIG_IP_MASQUERADE + if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then + comment 'Protocol-specific masquerading support will be built as modules.' + bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP + comment 'Protocol-specific masquerading support will be built as modules.' + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD + if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then + tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW + tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW + fi fi fi fi diff -u --recursive --new-file v2.1.130/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.130/linux/net/ipv4/tcp_ipv4.c Sun Nov 8 14:03:15 1998 +++ linux/net/ipv4/tcp_ipv4.c Mon Nov 30 16:43:32 1998 @@ -265,7 +265,7 @@ struct tcp_bind_bucket *tb; int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; - int remaining = high - low; + int remaining = high - low + 1; int rover; SOCKHASH_LOCK();