diff -u --recursive --new-file v2.3.27/linux/CREDITS linux/CREDITS --- v2.3.27/linux/CREDITS Thu Nov 11 20:11:30 1999 +++ linux/CREDITS Fri Nov 12 04:36:13 1999 @@ -1046,6 +1046,17 @@ S: 8103 Rein S: Austria +N: Jan Kara +E: jack@atrey.karlin.mff.cuni.cz +E: jack@suse.cz +D: Quota fixes for 2.2 kernel +D: Quota fixes for 2.3 kernel +D: Few other fixes in filesystem area (buffer cache, isofs, loopback) +W: http://atrey.karlin.mff.cuni.cz/~jack/ +S: Krosenska' 543 +S: 181 00 Praha 8 +S: Czech Republic + N: Jan "Yenya" Kasprzak E: kas@fi.muni.cz D: Author of the COSA/SRP sync serial board driver. diff -u --recursive --new-file v2.3.27/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.27/linux/Documentation/Configure.help Thu Nov 11 20:11:30 1999 +++ linux/Documentation/Configure.help Fri Nov 12 10:12:11 1999 @@ -685,17 +685,8 @@ Please read the comments at the top of drivers/block/hpt366.c -HPT366 (EXPERIMENTAL) -CONFIG_BLK_DEV_HPT366_SHARED - This requires CONFIG_BLK_DEV_HPT366. - It appears that there are different versions or releases of this hardware - by ABit. Since some cases the second channel of the onboard chipset works - and others fail, it is default disabled. This is required to be set if you - want to attempt the setup of the second channel. - - JUMBO WARNING, do not boot a kernel with this enabled if it is your only - one. You may not be able to get back into your machine without physically - detaching the attached devices. +HPT366 Fast Interrupt support (EXPERIMENTAL) +HPT366_FAST_IRQ_PREDICTION If unsure, say N. diff -u --recursive --new-file v2.3.27/linux/Makefile linux/Makefile --- v2.3.27/linux/Makefile Thu Nov 11 20:11:31 1999 +++ linux/Makefile Thu Nov 11 20:10:44 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 27 +SUBLEVEL = 28 EXTRAVERSION = 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.3.27/linux/arch/arm/kernel/ioport.c linux/arch/arm/kernel/ioport.c --- v2.3.27/linux/arch/arm/kernel/ioport.c Fri Oct 22 13:21:44 1999 +++ linux/arch/arm/kernel/ioport.c Fri Nov 12 04:29:47 1999 @@ -4,6 +4,7 @@ * IO permission support for ARM. */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile --- v2.3.27/linux/arch/i386/boot/Makefile Fri Oct 22 13:21:45 1999 +++ linux/arch/i386/boot/Makefile Thu Nov 11 19:11:18 1999 @@ -51,11 +51,11 @@ bootsect.s: bootsect.S Makefile $(BOOT_INCL) $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ -bbootsect: bbootsect.o - $(LD) -Ttext 0x0 -s -oformat binary $< -o $@ +bbootsect: bbootsect.o bsetup.o + $(LD) -Ttext 0x0 -R bsetup.o -s -oformat binary $< -o $@ bbootsect.o: bbootsect.s - $(AS) --defsym bootsect_kludge=0x220 -o $@ $< + $(AS) -o $@ $< bbootsect.s: bootsect.S Makefile $(BOOT_INCL) $(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ diff -u --recursive --new-file v2.3.27/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.3.27/linux/arch/i386/boot/setup.S Fri Oct 22 13:21:45 1999 +++ linux/arch/i386/boot/setup.S Thu Nov 11 19:11:18 1999 @@ -783,7 +783,7 @@ empty_8042: pushl %ecx - movl $0xFFFFFF, %ecx + movl $0x00FFFFFF, %ecx empty_8042_loop: decl %ecx diff -u --recursive --new-file v2.3.27/linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S --- v2.3.27/linux/arch/i386/boot/video.S Fri Oct 22 13:21:45 1999 +++ linux/arch/i386/boot/video.S Thu Nov 11 19:11:18 1999 @@ -1008,7 +1008,7 @@ vesa1: # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst. # XXX: lodsw %gs:(%si), %ax # Get next mode in the list - .byte 0x66, 0x65, 0xAD + .byte 0x65, 0xAD # %gs seg prefix + lodsw cmpw $0xffff, %ax # End of the table? jz vesar diff -u --recursive --new-file v2.3.27/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.3.27/linux/arch/i386/kernel/smp.c Sat Oct 9 11:47:50 1999 +++ linux/arch/i386/kernel/smp.c Fri Nov 12 04:29:47 1999 @@ -8,7 +8,6 @@ * later. */ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c --- v2.3.27/linux/arch/i386/lib/usercopy.c Mon Oct 11 15:38:14 1999 +++ linux/arch/i386/lib/usercopy.c Fri Nov 12 04:29:47 1999 @@ -5,6 +5,7 @@ * Copyright 1997 Andi Kleen * Copyright 1997 Linus Torvalds */ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/kernel/sun3-head.S linux/arch/m68k/kernel/sun3-head.S --- v2.3.27/linux/arch/m68k/kernel/sun3-head.S Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/kernel/sun3-head.S Fri Nov 12 04:29:47 1999 @@ -1,4 +1,3 @@ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.3.27/linux/arch/m68k/mac/macints.c Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/mac/macints.c Fri Nov 12 04:29:47 1999 @@ -115,7 +115,6 @@ * the SCC ourselves and only call the handler for the appopriate channel. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/mac/psc.c linux/arch/m68k/mac/psc.c --- v2.3.27/linux/arch/m68k/mac/psc.c Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/mac/psc.c Fri Nov 12 04:29:47 1999 @@ -13,7 +13,6 @@ * they aren't actually interrupt lines but data lines (to the DSP?) */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/math-emu/fp_entry.S linux/arch/m68k/math-emu/fp_entry.S --- v2.3.27/linux/arch/m68k/math-emu/fp_entry.S Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/math-emu/fp_entry.S Fri Nov 12 04:29:47 1999 @@ -35,6 +35,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/math-emu/fp_util.S linux/arch/m68k/math-emu/fp_util.S --- v2.3.27/linux/arch/m68k/math-emu/fp_util.S Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/math-emu/fp_util.S Fri Nov 12 04:29:47 1999 @@ -35,6 +35,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "fp_emu.h" /* diff -u --recursive --new-file v2.3.27/linux/arch/m68k/sun3/prom/console.c linux/arch/m68k/sun3/prom/console.c --- v2.3.27/linux/arch/m68k/sun3/prom/console.c Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/sun3/prom/console.c Fri Nov 12 04:29:47 1999 @@ -5,7 +5,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/sun3/prom/misc.c linux/arch/m68k/sun3/prom/misc.c --- v2.3.27/linux/arch/m68k/sun3/prom/misc.c Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/sun3/prom/misc.c Fri Nov 12 04:29:47 1999 @@ -5,7 +5,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/m68k/sun3/sun3ints.c linux/arch/m68k/sun3/sun3ints.c --- v2.3.27/linux/arch/m68k/sun3/sun3ints.c Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/sun3/sun3ints.c Fri Nov 12 04:29:47 1999 @@ -6,7 +6,6 @@ * for more details. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c --- v2.3.27/linux/arch/ppc/8xx_io/commproc.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/8xx_io/commproc.c Fri Nov 12 04:29:47 1999 @@ -21,7 +21,6 @@ * applications that require more DP ram, we can expand the boundaries * but then we have to be careful of any downloaded microcode. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h --- v2.3.27/linux/arch/ppc/8xx_io/commproc.h Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/8xx_io/commproc.h Fri Nov 12 04:29:47 1999 @@ -18,6 +18,7 @@ #ifndef __CPM_8XX__ #define __CPM_8XX__ +#include #include /* CPM Command register. diff -u --recursive --new-file v2.3.27/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c --- v2.3.27/linux/arch/ppc/8xx_io/enet.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/8xx_io/enet.c Fri Nov 12 04:29:47 1999 @@ -22,6 +22,7 @@ * small packets. * */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c --- v2.3.27/linux/arch/ppc/8xx_io/fec.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/8xx_io/fec.c Fri Nov 12 04:29:47 1999 @@ -16,6 +16,7 @@ * small packets. * */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/amiga/ints.c linux/arch/ppc/amiga/ints.c --- v2.3.27/linux/arch/ppc/amiga/ints.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/amiga/ints.c Fri Nov 12 04:29:47 1999 @@ -5,7 +5,6 @@ * Needed to drive the m68k emulating IRQ hardware on the PowerUp boards. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c --- v2.3.27/linux/arch/ppc/kernel/pmac_support.c Sun Nov 7 16:37:34 1999 +++ linux/arch/ppc/kernel/pmac_support.c Fri Nov 12 04:29:47 1999 @@ -1,6 +1,7 @@ /* * Miscellaneous procedures for dealing with the PowerMac hardware. */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/kernel/ppc8xx_pic.c linux/arch/ppc/kernel/ppc8xx_pic.c --- v2.3.27/linux/arch/ppc/kernel/ppc8xx_pic.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/ppc8xx_pic.c Fri Nov 12 04:29:47 1999 @@ -1,4 +1,4 @@ - +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/ppc/kernel/ppc8xx_pic.h linux/arch/ppc/kernel/ppc8xx_pic.h --- v2.3.27/linux/arch/ppc/kernel/ppc8xx_pic.h Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/ppc8xx_pic.h Fri Nov 12 04:29:47 1999 @@ -1,7 +1,7 @@ - #ifndef _PPC_KERNEL_PPC8xx_H #define _PPC_KERNEL_PPC8xx_H +#include #include "local_irq.h" extern struct hw_interrupt_type ppc8xx_pic; diff -u --recursive --new-file v2.3.27/linux/arch/ppc/kernel/qspan_pci.c linux/arch/ppc/kernel/qspan_pci.c --- v2.3.27/linux/arch/ppc/kernel/qspan_pci.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/qspan_pci.c Fri Nov 12 04:29:47 1999 @@ -15,6 +15,7 @@ * we have switched the chip select. */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/sh/kernel/irq_onchip.c linux/arch/sh/kernel/irq_onchip.c --- v2.3.27/linux/arch/sh/kernel/irq_onchip.c Sun Nov 7 16:37:34 1999 +++ linux/arch/sh/kernel/irq_onchip.c Fri Nov 12 04:29:47 1999 @@ -8,6 +8,7 @@ * */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S --- v2.3.27/linux/arch/sparc64/kernel/trampoline.S Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/trampoline.S Fri Nov 12 04:29:47 1999 @@ -4,8 +4,6 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ -#include - #include #include #include diff -u --recursive --new-file v2.3.27/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.3.27/linux/arch/sparc64/mm/ultra.S Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/mm/ultra.S Fri Nov 12 04:29:47 1999 @@ -4,8 +4,6 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ -#include - #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.27/linux/drivers/block/Config.in Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/Config.in Fri Nov 12 10:12:11 1999 @@ -53,6 +53,9 @@ fi bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210 + if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_AEC6210" = "y" ]; then + bool ' AEC6210 Tuning support' CONFIG_BLK_DEV_AEC6210_TUNING + fi if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_X86" = "y" ]; then bool ' ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3 @@ -65,7 +68,10 @@ if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then bool ' HPT34X DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT34X_DMA fi - bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 + bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 + if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT366" = "y" ]; then + bool ' HPT366 Fast Interrupt support (EXPERIMENTAL)' HPT366_FAST_IRQ_PREDICTION + fi fi if [ "$CONFIG_X86" = "y" ]; then bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX @@ -219,6 +225,7 @@ fi if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ + "$CONFIG_BLK_DEV_AEC6210" = "y" -o \ "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \ "$CONFIG_BLK_DEV_CMD640" = "y" -o \ "$CONFIG_BLK_DEV_CY82C693" = "y" -o \ diff -u --recursive --new-file v2.3.27/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.3.27/linux/drivers/block/Makefile Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/Makefile Fri Nov 12 10:12:11 1999 @@ -243,11 +243,11 @@ ###Collect ifeq ($(CONFIG_BLK_DEV_IDE),y) - LX_OBJS += ide.o + LX_OBJS += ide.o ide-features.o L_OBJS += ide-probe.o $(IDE_OBJS) else ifeq ($(CONFIG_BLK_DEV_IDE),m) - MIX_OBJS += ide.o $(IDE_OBJS) + MIX_OBJS += ide.o ide-features.o $(IDE_OBJS) M_OBJS += ide-mod.o ide-probe-mod.o endif endif @@ -374,8 +374,8 @@ include $(TOPDIR)/Rules.make -ide-mod.o: ide.o $(IDE_OBJS) - $(LD) $(LD_RFLAG) -r -o $@ ide.o $(IDE_OBJS) +ide-mod.o: ide.o ide-features.o $(IDE_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-features.o $(IDE_OBJS) ide-probe-mod.o: ide-probe.o ide-geometry.o $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o diff -u --recursive --new-file v2.3.27/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c --- v2.3.27/linux/drivers/block/aec6210.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/aec6210.c Fri Nov 12 10:12:11 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/aec6210.c Version 0.02 Sept. 3, 1999 + * linux/drivers/block/aec6210.c Version 0.03 Nov. 12, 1999 * * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) * May be copied or modified under the terms of the GNU General Public License @@ -51,10 +51,225 @@ #include #include +#include "ide_modes.h" + +#define ACARD_DEBUG_DRIVE_INFO 1 + +#ifdef CONFIG_BLK_DEV_AEC6210_TUNING + +struct chipset_bus_clock_list_entry { + byte xfer_speed; + unsigned short chipset_settings; + byte ultra_settings; +}; + +struct chipset_bus_clock_list_entry aec6210_base [] = { + { XFER_UDMA_2, 0x0401, 0x02 }, + { XFER_UDMA_1, 0x0401, 0x01 }, + { XFER_UDMA_0, 0x0401, 0x01 }, + + { XFER_MW_DMA_2, 0x0401, 0x00 }, + { XFER_MW_DMA_1, 0x0402, 0x00 }, + { XFER_MW_DMA_0, 0x070a, 0x00 }, + + { XFER_PIO_4, 0x0401, 0x00 }, + { XFER_PIO_3, 0x0403, 0x00 }, + { XFER_PIO_2, 0x0708, 0x00 }, + { XFER_PIO_1, 0x070a, 0x00 }, + { XFER_PIO_0, 0x0700, 0x00 }, + { 0, 0x0000, 0x00 } +}; + +extern char *ide_xfer_verbose (byte xfer_rate); + /* * TO DO: active tuning and correction of cards without a bios. */ +static unsigned short pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) { + return chipset_table->chipset_settings; + } + return 0x0000; +} + +static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) { + return chipset_table->ultra_settings; + } + return 0x00; +} + +static int aec6210_tune_chipset (ide_drive_t *drive, byte speed) +{ + ide_hwif_t *hwif = HWIF(drive); + + int err; + byte drive_pci; + unsigned short drive_conf = 0x0000; + byte ultra = 0x00, ultra_conf = 0x00; + byte tmp1 = 0x00, tmp2 = 0x00; + + int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + + switch(drive_number) { + case 0: drive_pci = 0x40; break; + case 1: drive_pci = 0x42; break; + case 2: drive_pci = 0x44; break; + case 3: drive_pci = 0x46; break; + default: return -1; + } + + pci_read_config_word(HWIF(drive)->pci_dev, drive_pci, &drive_conf); + drive_conf = pci_bus_clock_list(speed, aec6210_base); + pci_write_config_word(HWIF(drive)->pci_dev, drive_pci, drive_conf); + + pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &ultra); + tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number)))); + ultra_conf = pci_bus_clock_list_ultra(speed, aec6210_base); + tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number)))); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x54, tmp2); + + err = ide_config_drive_speed(drive, speed); + +#if ACARD_DEBUG_DRIVE_INFO + printk("%s: %s drive%d 0x04%x 0x02%x 0x02%x 0x02%x 0x02%x\n", + drive->name, ide_xfer_verbose(speed), drive_number, + drive_conf, ultra, tmp1, ultra_conf, tmp2); +#endif /* ACARD_DEBUG_DRIVE_INFO */ + + return(err); +} + +static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +{ + struct hd_driveid *id = drive->id; + byte speed = -1; + + if (drive->media != ide_disk) + return ((int) ide_dma_off_quietly); + + if (((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008) || + (id->dma_ultra & 0x0004)) && (ultra)) { + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0002) && (ultra)) { + speed = XFER_UDMA_1; + } else if ((id->dma_ultra & 0x0001) && (ultra)) { + speed = XFER_UDMA_0; + } else if (id->dma_mword & 0x0004) { + speed = XFER_MW_DMA_2; + } else if (id->dma_mword & 0x0002) { + speed = XFER_MW_DMA_1; + } else if (id->dma_mword & 0x0001) { + speed = XFER_MW_DMA_0; + } else if (id->dma_1word & 0x0004) { + speed = XFER_SW_DMA_2; + } else if (id->dma_1word & 0x0002) { + speed = XFER_SW_DMA_1; + } else if (id->dma_1word & 0x0001) { + speed = XFER_SW_DMA_0; + } else { + return ((int) ide_dma_off_quietly); + } + (void) aec6210_tune_chipset(drive, speed); + + return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + ((id->dma_1word >> 8) & 7) ? ide_dma_on : + ide_dma_off_quietly); +} + +static void aec6210_tune_drive (ide_drive_t *drive, byte pio) +{ + byte speed; + + switch(pio) { + case 5: + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + case 4: + speed = XFER_PIO_4; break; + case 3: + speed = XFER_PIO_3; break; + case 2: + speed = XFER_PIO_2; break; + case 1: + speed = XFER_PIO_1; break; + default: + speed = XFER_PIO_0; break; + } + (void) aec6210_tune_chipset(drive, speed); +} + +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x001F) { + /* Force if Capable UltraDMA */ + dma_func = config_chipset_for_dma(drive, 1); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x0007)) { + /* Force if Capable regular DMA modes */ + dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + aec6210_tune_drive(drive, 5); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + +/* + * aec6210_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. + */ +int aec6210_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} +#endif /* CONFIG_BLK_DEV_AEC6210_TUNING */ + unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name) { if (dev->resource[PCI_ROM_RESOURCE].start) { @@ -62,4 +277,45 @@ printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); } return dev->irq; +} + +void __init ide_init_aec6210 (ide_hwif_t *hwif) +{ +#ifdef CONFIG_BLK_DEV_AEC6210_TUNING + hwif->tuneproc = &aec6210_tune_drive; + + if (hwif->dma_base) { + hwif->dmaproc = &aec6210_dmaproc; + hwif->drives[0].autotune = 0; + hwif->drives[1].autotune = 0; + } else { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } +#endif /* CONFIG_BLK_DEV_AEC6210_TUNING */ +} + +void __init ide_dmacapable_aec6210 (ide_hwif_t *hwif, unsigned long dmabase) +{ + byte dma_new = 0; + byte dma_old = inb(dmabase+2); + byte reg54h = 0; + byte masterdma = hwif->channel ? 0x30 : 0x03; + byte slavedma = hwif->channel ? 0xc0 : 0x0c; + unsigned long flags; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + + dma_new = dma_old; + + pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); + + if (reg54h & masterdma) dma_new |= 0x20; + if (reg54h & slavedma) dma_new |= 0x40; + if (dma_new != dma_old) outb(dma_new, dmabase+2); + + __restore_flags(flags); /* local CPU only */ + + ide_setup_dma(hwif, dmabase, 8); } diff -u --recursive --new-file v2.3.27/linux/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c --- v2.3.27/linux/drivers/block/ali14xx.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/ali14xx.c Fri Nov 12 10:12:11 1999 @@ -204,11 +204,11 @@ { /* auto-detect IDE controller port */ if (!findPort()) { - printk("ali14xx: not found\n"); + printk("\nali14xx: not found"); return; } - printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn); + printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn); ide_hwifs[0].chipset = ide_ali14xx; ide_hwifs[1].chipset = ide_ali14xx; ide_hwifs[0].tuneproc = &ali14xx_tune_drive; @@ -219,7 +219,7 @@ /* initialize controller registers */ if (!initRegisters()) { - printk("ali14xx: Chip initialization failed\n"); + printk("\nali14xx: Chip initialization failed"); return; } } diff -u --recursive --new-file v2.3.27/linux/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c --- v2.3.27/linux/drivers/block/alim15x3.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/alim15x3.c Fri Nov 12 10:12:11 1999 @@ -693,6 +693,31 @@ chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; } + if (m5229_revision == 0x20) { + /* + * check M1533 revision (offset 0x08) + */ + pci_read_config_byte(isa_dev, 0x08, &tmpbyte); + if (tmpbyte == 0x0A) { + unsigned long flags; + pci_read_config_byte(dev, 0x4e, &tmpbyte); + save_flags(flags); + cli(); + /* + * set bit 6 + */ + pci_write_config_byte(dev, 0x4e, tmpbyte | 0x40); + restore_flags(flags); + + /* + * this special version is similar to revision 0xC2 + * but does not support UDMA66 + * (cable_80_pin[0] = 0; cable_80_pin[1] = 0;) + */ + m5229_revision = 0xC2; + } + } + return 0; } @@ -742,7 +767,7 @@ } hwif->tuneproc = &ali15x3_tune_drive; - if ((hwif->dma_base) && (m5229_revision >= 0xC1)) { + if ((hwif->dma_base) && (m5229_revision >= 0x20)) { /* * M1543C or newer for DMAing */ diff -u --recursive --new-file v2.3.27/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c --- v2.3.27/linux/drivers/block/cmd640.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/cmd640.c Fri Nov 12 10:12:11 1999 @@ -686,6 +686,7 @@ d.cycle_time, d.overridden ? " (overriding vendor mode)" : ""); display_clocks(index); + return; } #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ diff -u --recursive --new-file v2.3.27/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.3.27/linux/drivers/block/cpqarray.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/block/cpqarray.c Fri Nov 12 04:29:47 1999 @@ -22,6 +22,7 @@ * driver, you'll probably need the Compaq Array Controller Interface * Specificiation (Document number ECG086/1198) */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c --- v2.3.27/linux/drivers/block/hpt366.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/hpt366.c Fri Nov 12 10:12:11 1999 @@ -218,7 +218,8 @@ { struct hd_driveid *id = drive->id; byte speed = 0x00; - unsigned int reg40 = 0; + byte reg51h = 0; + unsigned int reg40 = 0; int rval; if ((id->dma_ultra & 0x0010) && @@ -258,15 +259,22 @@ return ((int) ide_dma_off_quietly); } - /* Disable the "fast interrupt" prediction. + pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); + +#ifdef HPT366_FAST_IRQ_PREDICTION + /* + * Some drives prefer/allow for the method of handling interrupts. + */ + if (!(reg51h & 0x80)) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80); +#else /* ! HPT366_FAST_IRQ_PREDICTION */ + /* + * Disable the "fast interrupt" prediction. * Instead, always wait for the real interrupt from the drive! */ - { - byte reg51h = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); - if (reg51h & 0x80) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); - } + if (reg51h & 0x80) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); +#endif /* HPT366_FAST_IRQ_PREDICTION */ /* * Preserve existing PIO settings: diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v2.3.27/linux/drivers/block/ide-cd.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/ide-cd.c Fri Nov 12 10:12:11 1999 @@ -276,7 +276,6 @@ #define IDECD_VERSION "4.56" -#include #include #include #include @@ -539,7 +538,7 @@ /* Returns 0 if the request should be continued. Returns 1 if the request was ended. */ -static int cdrom_decode_status (ide_drive_t *drive, int good_stat, +static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; @@ -570,7 +569,7 @@ pc->stat = 1; cdrom_end_request (1, drive); - ide_error (drive, "request sense failure", stat); + *startstop = ide_error (drive, "request sense failure", stat); return 1; } else if (cmd == PACKET_COMMAND) { @@ -640,7 +639,7 @@ } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ - ide_error (drive, "cdrom_decode_status", stat); + *startstop = ide_error (drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ @@ -656,6 +655,7 @@ } /* Retry, or handle the next request. */ + *startstop = ide_stopped; return 1; } @@ -682,13 +682,15 @@ called when the interrupt from the drive arrives. Otherwise, HANDLER will be called immediately after the drive is prepared for the transfer. */ -static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, +static ide_startstop_t cdrom_start_packet_command (ide_drive_t *drive, int xferlen, ide_handler_t *handler) { + ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; /* Wait for the controller to be idle. */ - if (ide_wait_stat(drive, 0, BUSY_STAT, WAIT_READY)) return 1; + if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) + return startstop; if (info->dma) info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); @@ -709,12 +711,11 @@ if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - (*handler) (drive); + return (*handler) (drive); } - - return 0; } /* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. @@ -722,7 +723,7 @@ by cdrom_start_packet_command. HANDLER is the interrupt handler to call when the command completes or there's data ready. */ -static int cdrom_transfer_packet_command (ide_drive_t *drive, +static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, unsigned char *cmd_buf, int cmd_len, ide_handler_t *handler) { @@ -730,14 +731,16 @@ /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ int stat_dum; + ide_startstop_t startstop; /* Check for errors. */ - if (cdrom_decode_status (drive, DRQ_STAT, &stat_dum)) - return 1; + if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum)) + return startstop; } else { + ide_startstop_t startstop; /* Otherwise, we must wait for DRQ to get set. */ - if (ide_wait_stat (drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) - return 1; + if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) + return startstop; } /* Arm the interrupt handler. */ @@ -746,7 +749,7 @@ /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len); - return 0; + return ide_started; } @@ -843,12 +846,13 @@ /* * Interrupt routine. Called when a read request has completed. */ -static void cdrom_read_intr (ide_drive_t *drive) +static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) { int stat; int ireason, len, sectors_to_transfer, nskip; struct cdrom_info *info = drive->driver_data; int i, dma = info->dma, dma_error = 0; + ide_startstop_t startstop; struct request *rq = HWGROUP(drive)->rq; @@ -859,19 +863,18 @@ HWIF(drive)->dmaproc(ide_dma_off, drive); } - if (cdrom_decode_status (drive, 0, &stat)) - return; + if (cdrom_decode_status (&startstop, drive, 0, &stat)) + return startstop; if (dma) { - if (dma_error) { - ide_error (drive, "dma error", stat); - return; - } - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return; + if (!dma_error) { + for (i = rq->nr_sectors; i > 0;) { + i -= rq->current_nr_sectors; + ide_end_request(1, HWGROUP(drive)); + } + return ide_stopped; + } else + return ide_error (drive, "dma error", stat); } /* Read the interrupt reason and the transfer length. */ @@ -888,11 +891,12 @@ cdrom_end_request (0, drive); } else cdrom_end_request (1, drive); - return; + return ide_stopped; } /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason (drive, len, ireason)) return; + if (cdrom_read_check_ireason (drive, len, ireason)) + return ide_stopped; /* Assume that the drive will always provide data in multiples of at least SECTOR_SIZE, as it gets hairy to keep track @@ -907,7 +911,7 @@ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; } cdrom_end_request (0, drive); - return; + return ide_stopped; } /* The number of sectors we need to read from the drive. */ @@ -967,6 +971,7 @@ /* Done moving data! Wait for another interrupt. */ ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); + return ide_started; } /* @@ -1031,7 +1036,7 @@ * However, for drq_interrupt devices, it is called from an interrupt * when the drive is ready to accept the command. */ -static void cdrom_start_read_continuation (ide_drive_t *drive) +static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) { struct packet_command pc; struct request *rq = HWGROUP(drive)->rq; @@ -1058,7 +1063,7 @@ printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n", drive->name, rq->current_nr_sectors); cdrom_end_request (0, drive); - return; + return ide_stopped; } sector -= nskip; nsect += nskip; @@ -1083,7 +1088,7 @@ put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]); /* Send the command to the drive and return. */ - (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), + return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_read_intr); } @@ -1092,14 +1097,15 @@ #define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ #define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ -static void cdrom_seek_intr (ide_drive_t *drive) +static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; int stat; static int retry = 10; + ide_startstop_t startstop; - if (cdrom_decode_status (drive, 0, &stat)) - return; + if (cdrom_decode_status (&startstop, drive, 0, &stat)) + return startstop; CDROM_CONFIG_FLAGS(drive)->seeking = 1; if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { @@ -1108,9 +1114,10 @@ drive->dsc_overlap = 0; } } + return ide_stopped; } -static void cdrom_start_seek_continuation (ide_drive_t *drive) +static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) { struct packet_command pc; struct request *rq = HWGROUP(drive)->rq; @@ -1125,16 +1132,16 @@ memset (&pc.c, 0, sizeof (pc.c)); pc.c[0] = GPCMD_SEEK; put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr); + return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr); } -static void cdrom_start_seek (ide_drive_t *drive, unsigned int block) +static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) { struct cdrom_info *info = drive->driver_data; info->dma = 0; info->start_seek = jiffies; - cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); + return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); } /* Fix up a possibly partially-processed request so that we can @@ -1153,7 +1160,7 @@ /* * Start a read request from the CD-ROM. */ -static void cdrom_start_read (ide_drive_t *drive, unsigned int block) +static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; @@ -1173,8 +1180,9 @@ /* Satisfy whatever we can of this request from our cached sector. */ if (cdrom_read_from_buffer(drive)) - return; + return ide_stopped; + /* Clear the local sector buffer. */ info->nsectors_buffered = 0; /* use dma, if possible. */ @@ -1185,7 +1193,7 @@ info->dma = 0; /* Start sending the read request to the drive. */ - cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); + return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); } /**************************************************************************** @@ -1198,15 +1206,16 @@ struct atapi_request_sense *reqbuf); /* Interrupt routine for packet command completion. */ -static void cdrom_pc_intr (ide_drive_t *drive) +static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) { int ireason, len, stat, thislen; struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *)rq->buffer; + ide_startstop_t startstop; /* Check for errors. */ - if (cdrom_decode_status (drive, 0, &stat)) - return; + if (cdrom_decode_status (&startstop, drive, 0, &stat)) + return startstop; /* Read the interrupt reason and the transfer length. */ ireason = IN_BYTE (IDE_NSECTOR_REG); @@ -1239,15 +1248,25 @@ pc->stat = 1; cdrom_end_request (1, drive); } - return; + return ide_stopped; } /* Figure out how much data to transfer. */ thislen = pc->buflen; + if (thislen < 0) thislen = -thislen; if (thislen > len) thislen = len; /* The drive wants to be written to. */ if ((ireason & 3) == 0) { + /* Check that we want to write. */ + if (pc->buflen > 0) { + printk ("%s: cdrom_pc_intr: Drive wants " + "to transfer data the wrong way!\n", + drive->name); + pc->stat = 1; + thislen = 0; + } + /* Transfer the data. */ atapi_output_bytes (drive, pc->buffer, thislen); @@ -1266,6 +1285,14 @@ /* Same drill for reading. */ else if ((ireason & 3) == 2) { + /* Check that we want to read. */ + if (pc->buflen < 0) { + printk ("%s: cdrom_pc_intr: Drive wants to " + "transfer data the wrong way!\n", + drive->name); + pc->stat = 1; + thislen = 0; + } /* Transfer the data. */ atapi_input_bytes (drive, pc->buffer, thislen); @@ -1290,21 +1317,22 @@ /* Now we wait for another interrupt. */ ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); + return ide_started; } -static void cdrom_do_pc_continuation (ide_drive_t *drive) +static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *)rq->buffer; /* Send the command to the drive and return. */ - cdrom_transfer_packet_command (drive, pc->c, + return cdrom_transfer_packet_command (drive, pc->c, sizeof (pc->c), &cdrom_pc_intr); } -static void cdrom_do_packet_command (ide_drive_t *drive) +static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) { int len; struct request *rq = HWGROUP(drive)->rq; @@ -1316,7 +1344,7 @@ len = pc->buflen; /* Start sending the command to the drive. */ - cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation); + return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation); } @@ -1401,51 +1429,50 @@ /**************************************************************************** * cdrom driver request routine. */ -static -void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t +ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) { + ide_startstop_t action; struct cdrom_info *info = drive->driver_data; switch (rq->cmd) { - case READ: { - if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; - int stat = GET_STAT(); - - if ((stat & SEEK_STAT) != SEEK_STAT) { - if (elpased < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, IDECD_SEEK_TIMER); - return; + case READ: { + if (CDROM_CONFIG_FLAGS(drive)->seeking) { + unsigned long elpased = jiffies - info->start_seek; + int stat = GET_STAT(); + + if ((stat & SEEK_STAT) != SEEK_STAT) { + if (elpased < IDECD_SEEK_TIMEOUT) { + ide_stall_queue(drive, IDECD_SEEK_TIMER); + return ide_stopped; + } + printk ("%s: DSC timeout\n", drive->name); } - printk ("%s: DSC timeout\n", drive->name); + CDROM_CONFIG_FLAGS(drive)->seeking = 0; } - CDROM_CONFIG_FLAGS(drive)->seeking = 0; + if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) + action = cdrom_start_seek (drive, block); + else + action = cdrom_start_read (drive, block); + info->last_block = block; + return action; } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) - cdrom_start_seek (drive, block); - else - cdrom_start_read (drive, block); - info->last_block = block; - break; - } - case PACKET_COMMAND: - case REQUEST_SENSE_COMMAND: { - cdrom_do_packet_command(drive); - break; - } + case PACKET_COMMAND: + case REQUEST_SENSE_COMMAND: { + return cdrom_do_packet_command(drive); + } - case RESET_DRIVE_COMMAND: { - cdrom_end_request(1, drive); - ide_do_reset(drive); - break; - } + case RESET_DRIVE_COMMAND: { + cdrom_end_request(1, drive); + return ide_do_reset(drive); + } - default: { - printk("ide-cd: bad cmd %d\n", rq -> cmd); - cdrom_end_request(0, drive); - break; - } + default: { + printk("ide-cd: bad cmd %d\n", rq -> cmd); + cdrom_end_request(0, drive); + return ide_stopped; + } } } @@ -2367,8 +2394,13 @@ if (drive->using_dma) { if ((drive->id->field_valid & 4) && - (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) { - printk(", UDMA"); /* UDMA BIOS-enabled! */ + (drive->id->word93 & 0x2000) && + (HWIF(drive)->udma_four) && + (drive->id->dma_ultra & (drive->id->dma_ultra >> 11) & 3)) { + printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ + } else if ((drive->id->field_valid & 4) && + (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) { + printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ } else if (drive->id->field_valid & 4) { printk(", (U)DMA"); /* Can be BIOS-enabled! */ } else { diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c --- v2.3.27/linux/drivers/block/ide-disk.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/ide-disk.c Fri Nov 12 10:12:11 1999 @@ -133,7 +133,7 @@ /* * read_intr() is the handler for disk read/multread interrupts */ -static void read_intr (ide_drive_t *drive) +static ide_startstop_t read_intr (ide_drive_t *drive) { byte stat; int i; @@ -141,8 +141,7 @@ struct request *rq; if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - ide_error(drive, "read_intr", stat); - return; + return ide_error(drive, "read_intr", stat); } msect = drive->mult_count; @@ -154,12 +153,6 @@ msect -= nsect; } else nsect = 1; - /* - * PIO input can take longish times, so we drop the spinlock. - * On SMP, bad things might happen if syscall level code adds - * a new request while we do this PIO, so we just freeze all - * request queue handling while doing the PIO. FIXME - */ idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); #ifdef DEBUG printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", @@ -176,21 +169,24 @@ if (msect) goto read_next; ide_set_handler (drive, &read_intr, WAIT_CMD, NULL); + return ide_started; } + return ide_stopped; } /* * write_intr() is the handler for disk write interrupts */ -static void write_intr (ide_drive_t *drive) +static ide_startstop_t write_intr (ide_drive_t *drive) { byte stat; int i; ide_hwgroup_t *hwgroup = HWGROUP(drive); struct request *rq = hwgroup->rq; - int error = 0; - if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { + if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { + printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat); + } else { #ifdef DEBUG printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", drive->name, rq->sector, (unsigned long) rq->buffer, @@ -207,26 +203,30 @@ if (i > 0) { idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); + return ide_started; } - goto out; + return ide_stopped; } - } else - error = 1; -out: - if (error) - ide_error(drive, "write_intr", stat); + printk("%s: write_intr error2: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat); + } + return ide_error(drive, "write_intr", stat); } /* * ide_multwrite() transfers a block of up to mcount sectors of data * to a drive as part of a disk multiple-sector write operation. + * + * Returns 0 if successful; returns 1 if request had to be aborted due to corrupted buffer list. */ -void ide_multwrite (ide_drive_t *drive, unsigned int mcount) +int ide_multwrite (ide_drive_t *drive, unsigned int mcount) { - struct request *rq = &HWGROUP(drive)->wrq; + ide_hwgroup_t *hwgroup= HWGROUP(drive); + struct request *rq = &hwgroup->wrq; + + do { + unsigned long flags; + unsigned int nsect = rq->current_nr_sectors; - do { - unsigned int nsect = rq->current_nr_sectors; if (nsect > mcount) nsect = mcount; mcount -= nsect; @@ -237,6 +237,7 @@ drive->name, rq->sector, (unsigned long) rq->buffer, nsect, rq->nr_sectors - nsect); #endif + spin_lock_irqsave(&io_request_lock, flags); /* Is this really necessary? */ #ifdef CONFIG_BLK_DEV_PDC4030 rq->sector += nsect; #endif @@ -247,32 +248,36 @@ rq->current_nr_sectors = rq->bh->b_size>>9; rq->buffer = rq->bh->b_data; } else { - panic("%s: buffer list corrupted\n", drive->name); - break; + spin_unlock_irqrestore(&io_request_lock, flags); + printk("%s: buffer list corrupted\n", drive->name); + ide_end_request(0, hwgroup); + return 1; } } else { rq->buffer += nsect << 9; } + spin_unlock_irqrestore(&io_request_lock, flags); } while (mcount); + return 0; } /* * multwrite_intr() is the handler for disk multwrite interrupts */ -static void multwrite_intr (ide_drive_t *drive) +static ide_startstop_t multwrite_intr (ide_drive_t *drive) { byte stat; int i; ide_hwgroup_t *hwgroup = HWGROUP(drive); struct request *rq = &hwgroup->wrq; - int error = 0; if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { if (stat & DRQ_STAT) { if (rq->nr_sectors) { - ide_multwrite(drive, drive->mult_count); + if (ide_multwrite(drive, drive->mult_count)) + return ide_stopped; ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); - goto out; + return ide_started; } } else { if (!rq->nr_sectors) { /* all done? */ @@ -281,20 +286,17 @@ i -= rq->current_nr_sectors; ide_end_request(1, hwgroup); } - goto out; + return ide_stopped; } } - } else - error = 1; -out: - if (error) - ide_error(drive, "multwrite_intr", stat); + } + return ide_error(drive, "multwrite_intr", stat); } /* * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. */ -static void set_multmode_intr (ide_drive_t *drive) +static ide_startstop_t set_multmode_intr (ide_drive_t *drive) { byte stat = GET_STAT(); @@ -309,28 +311,31 @@ drive->special.b.recalibrate = 1; (void) ide_dump_status(drive, "set_multmode", stat); } + return ide_stopped; } /* * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. */ -static void set_geometry_intr (ide_drive_t *drive) +static ide_startstop_t set_geometry_intr (ide_drive_t *drive) { byte stat = GET_STAT(); if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - ide_error(drive, "set_geometry_intr", stat); + return ide_error(drive, "set_geometry_intr", stat); + return ide_stopped; } /* * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. */ -static void recal_intr (ide_drive_t *drive) +static ide_startstop_t recal_intr (ide_drive_t *drive) { byte stat = GET_STAT(); if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - ide_error(drive, "recal_intr", stat); + return ide_error(drive, "recal_intr", stat); + return ide_stopped; } /* @@ -338,7 +343,7 @@ * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */ -static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); @@ -375,45 +380,61 @@ } #ifdef CONFIG_BLK_DEV_PDC4030 if (IS_PDC4030_DRIVE) { - extern void do_pdc4030_io(ide_drive_t *, struct request *); - do_pdc4030_io (drive, rq); - return; + extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *); + return do_pdc4030_io (drive, rq); } #endif /* CONFIG_BLK_DEV_PDC4030 */ if (rq->cmd == READ) { #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) - return; + return ide_started; #endif /* CONFIG_BLK_DEV_IDEDMA */ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); - return; + return ide_started; } if (rq->cmd == WRITE) { + ide_startstop_t startstop; #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) - return; + return ide_started; #endif /* CONFIG_BLK_DEV_IDEDMA */ OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); - if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { + if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); - return; + return startstop; } if (!drive->unmask) __cli(); /* local CPU only */ if (drive->mult_count) { - HWGROUP(drive)->wrq = *rq; /* scratchpad */ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + /* + * Ugh.. this part looks ugly because we MUST set up + * the interrupt handler before outputting the first block + * of data to be written. If we hit an error (corrupted buffer list) + * in ide_multwrite(), then we need to remove the handler/timer + * before returning. Fortunately, this NEVER happens (right?). + */ + hwgroup->wrq = *rq; /* scratchpad */ ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); - ide_multwrite(drive, drive->mult_count); + if (ide_multwrite(drive, drive->mult_count)) { + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + hwgroup->handler = NULL; + del_timer(&hwgroup->timer); + spin_unlock_irqrestore(&io_request_lock, flags); + return ide_stopped; + } } else { ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); } - return; + return ide_started; } printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); ide_end_request(0, HWGROUP(drive)); + return ide_stopped; } static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) @@ -472,7 +493,7 @@ return (drive->capacity - drive->sect0); } -static void idedisk_special (ide_drive_t *drive) +static ide_startstop_t idedisk_special (ide_drive_t *drive) { special_t *s = &drive->special; @@ -498,7 +519,9 @@ int special = s->all; s->all = 0; printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); + return ide_stopped; } + return IS_PDC4030_DRIVE ? ide_stopped : ide_started; } static void idedisk_pre_reset (ide_drive_t *drive) @@ -620,7 +643,7 @@ return -EBUSY; drive->nowerr = arg; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c --- v2.3.27/linux/drivers/block/ide-dma.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/ide-dma.c Fri Nov 12 10:12:11 1999 @@ -186,7 +186,7 @@ /* * dma_intr() is the handler for disk read/write DMA interrupts */ -void ide_dma_intr (ide_drive_t *drive) +ide_startstop_t ide_dma_intr (ide_drive_t *drive) { int i; byte stat, dma_stat; @@ -201,12 +201,11 @@ i -= rq->current_nr_sectors; ide_end_request(1, HWGROUP(drive)); } - return; + return ide_stopped; } printk("%s: dma_intr: bad DMA status\n", drive->name); } - ide__sti(); /* local CPU only */ - ide_error(drive, "dma_intr", stat); + return ide_error(drive, "dma_intr", stat); } /* diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-features.c linux/drivers/block/ide-features.c --- v2.3.27/linux/drivers/block/ide-features.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/ide-features.c Fri Nov 12 10:12:11 1999 @@ -0,0 +1,275 @@ +/* + * linux/drivers/block/ide-features.c + * + * Copyright (C) 1999 Linus Torvalds & authors (see below) + * + * Andre Hedrick + * + * Extracts if ide.c to address the evolving transfer rate code for + * the SETFEATURES_XFER callouts. Below are original authors of some or + * various parts of any given function below. + * + * Mark Lord + * Gadi Oxman + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * + */ +char *ide_xfer_verbose (byte xfer_rate) +{ + switch(xfer_rate) { + case XFER_UDMA_4: return("UDMA 4"); + case XFER_UDMA_3: return("UDMA 3"); + case XFER_UDMA_2: return("UDMA 2"); + case XFER_UDMA_1: return("UDMA 1"); + case XFER_UDMA_0: return("UDMA 0"); + case XFER_MW_DMA_2: return("MW DMA 2"); + case XFER_MW_DMA_1: return("MW DMA 1"); + case XFER_MW_DMA_0: return("MW DMA 0"); + case XFER_SW_DMA_2: return("SW DMA 2"); + case XFER_SW_DMA_1: return("SW DMA 1"); + case XFER_SW_DMA_0: return("SW DMA 0"); + case XFER_PIO_4: return("PIO 4"); + case XFER_PIO_3: return("PIO 3"); + case XFER_PIO_2: return("PIO 2"); + case XFER_PIO_1: return("PIO 1"); + case XFER_PIO_0: return("PIO 0"); + case XFER_PIO_SLOW: return("PIO SLOW"); + default: return("XFER ERROR"); + } +} + +/* + * + */ +char *ide_media_verbose (ide_drive_t *drive) +{ + switch (drive->media) { + case ide_disk: return("disk "); + case ide_cdrom: return("cdrom "); + case ide_tape: return("tape "); + case ide_floppy: return("floppy"); + default: return("??????"); + } +} + +int ide_driveid_update (ide_drive_t *drive) +{ + /* + * Re-read drive->id for possible DMA mode + * change (copied from ide-probe.c) + */ + struct hd_driveid *id; + unsigned long timeout, irqs, flags; + + probe_irq_off(probe_irq_on()); + irqs = probe_irq_on(); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + ide_delay_50ms(); + OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (0 < (signed long)(jiffies - timeout)) { + if (irqs) + (void) probe_irq_off(irqs); + return 0; /* drive timed-out */ + } + ide_delay_50ms(); /* give drive a breather */ + } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); + ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ + if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) + return 0; + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only; some systems need this */ + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + ide_input_data(drive, id, SECTOR_WORDS); + (void) GET_STAT(); /* clear drive IRQ */ + ide__sti(); /* local CPU only */ + __restore_flags(flags); /* local CPU only */ + ide_fix_driveid(id); + if (id && id->cyls) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ +#ifdef DEBUG + printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n", + drive->name, id->dma_ultra, id->dma_mword, id->dma_1word); +#endif + kfree(id); + } + return 1; +} + +/* + * Similar to ide_wait_stat(), except it never calls ide_error internally. + * This is a kludge to handle the new ide_config_drive_speed() function, + * and should not otherwise be used anywhere. Eventually, the tuneproc's + * should be updated to return ide_startstop_t, in which case we can get + * rid of this abomination again. :) -ml + */ +int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout) +{ + byte stat; + int i; + unsigned long flags; + + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ + if ((stat = GET_STAT()) & BUSY_STAT) { + __save_flags(flags); /* local CPU only */ + ide__sti(); /* local CPU only */ + timeout += jiffies; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (0 < (signed long)(jiffies - timeout)) { + __restore_flags(flags); /* local CPU only */ + (void)ide_dump_status(drive, "ide_wait_noerr", stat); + return 1; + } + } + __restore_flags(flags); /* local CPU only */ + } + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), good, bad)) + return 0; + } + (void)ide_dump_status(drive, "ide_wait_noerr", stat); + return 1; +} + + +/* + * Verify that we are doing an approved SETFEATURES_XFER with respect + * to the hardware being able to support request. Since some hardware + * can improperly report capabilties, we check to see if the host adapter + * in combination with the device (usually a disk) properly detect + * and acknowledge each end of the ribbon. + */ +int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature) +{ + if ((cmd == WIN_SETFEATURES) && + (nsect > XFER_UDMA_2) && + (feature == SETFEATURES_XFER)) { + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name); + return 1; + } + if ((drive->id->word93 & 0x2000) == 0) { + printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name); + return 1; + } + } + return 0; +} + +/* + * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. + * 1 : Safe to update drive->id DMA registers. + * 0 : OOPs not allowed. + */ +int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature) +{ + struct hd_driveid *id = drive->id; + + if ((cmd == WIN_SETFEATURES) && + (nsect >= XFER_SW_DMA_0) && + (feature == SETFEATURES_XFER) && + (id->dma_ultra || id->dma_mword || id->dma_1word)) + return 1; + return 0; +} + +int ide_config_drive_speed (ide_drive_t *drive, byte speed) +{ + unsigned long flags; + int err; + byte stat; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + + /* + * Don't use ide_wait_cmd here - it will + * attempt to set_geometry and recalibrate, + * but for some reason these don't work at + * this point (lost interrupt). + */ + SELECT_DRIVE(HWIF(drive), drive); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + OUT_BYTE(speed, IDE_NSECTOR_REG); + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + + err = ide_wait_noerr(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); + +#if 0 + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); +#endif + + __restore_flags(flags); /* local CPU only */ + + stat = GET_STAT(); + if (stat != DRIVE_READY) + (void) ide_dump_status(drive, "set_drive_speed_status", stat); + + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + + switch(speed) { + case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; + case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; + case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; + case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; + case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; + case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; + case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; + case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; + case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; + case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; + case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; + default: break; + } + return(err); +} + +EXPORT_SYMBOL(ide_driveid_update); +EXPORT_SYMBOL(ide_wait_noerr); +EXPORT_SYMBOL(ide_ata66_check); +EXPORT_SYMBOL(set_transfer); +EXPORT_SYMBOL(ide_config_drive_speed); + diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c --- v2.3.27/linux/drivers/block/ide-floppy.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/ide-floppy.c Fri Nov 12 10:12:11 1999 @@ -830,7 +830,7 @@ * idefloppy_pc_intr is the usual interrupt handler which will be called * during a packet command. */ -static void idefloppy_pc_intr (ide_drive_t *drive) +static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_status_reg_t status; @@ -875,24 +875,22 @@ rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } idefloppy_retry_pc (drive); /* Retry operation */ - return; + return ide_stopped; /* queued, but not started */ } pc->error = 0; if (floppy->failed_pc == pc) floppy->failed_pc=NULL; pc->callback(drive); /* Command finished - Call the callback function */ - return; + return ide_stopped; } #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n"); (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ @@ -901,14 +899,12 @@ if (ireason.b.cod) { printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ temp = pc->actually_transferred + bcount.all; @@ -917,7 +913,7 @@ printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); idefloppy_discard_data (drive,bcount.all); ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); - return; + return ide_started; } #if IDEFLOPPY_DEBUG_LOG printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); @@ -939,31 +935,33 @@ pc->current_position+=bcount.all; ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + return ide_started; } -static void idefloppy_transfer_pc (ide_drive_t *drive) +static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive) { + ide_startstop_t startstop; idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_ireason_reg_t ireason; - if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); - return; + return startstop; } ireason.all=IN_BYTE (IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ + return ide_started; } /* * Issue a packet command */ -static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) +static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_bcount_reg_t bcount; @@ -991,7 +989,7 @@ } floppy->failed_pc=NULL; pc->callback(drive); - return; + return ide_stopped; } #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Retry number - %d\n",pc->retries); @@ -1027,9 +1025,10 @@ if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD, NULL); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - idefloppy_transfer_pc (drive); + return idefloppy_transfer_pc (drive); } } @@ -1135,7 +1134,7 @@ /* * idefloppy_do_request is our request handling function. */ -static void idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t *pc; @@ -1152,7 +1151,7 @@ else printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); idefloppy_end_request (0, HWGROUP(drive)); - return; + return ide_stopped; } switch (rq->cmd) { case READ: @@ -1160,7 +1159,7 @@ if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { printk ("%s: unsupported r/w request size\n", drive->name); idefloppy_end_request (0, HWGROUP(drive)); - return; + return ide_stopped; } pc = idefloppy_next_pc_storage (drive); idefloppy_create_rw_cmd (floppy, pc, rq, block); @@ -1171,10 +1170,10 @@ default: printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd); idefloppy_end_request (0,HWGROUP (drive)); - return; + return ide_stopped; } pc->rq = rq; - idefloppy_issue_pc (drive, pc); + return idefloppy_issue_pc (drive, pc); } /* diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-geometry.c linux/drivers/block/ide-geometry.c --- v2.3.27/linux/drivers/block/ide-geometry.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/block/ide-geometry.c Fri Nov 12 10:12:11 1999 @@ -1,6 +1,7 @@ /* * linux/drivers/block/ide-geometry.c */ +#include #include #include @@ -65,9 +66,7 @@ drive->head = drive->bios_head = *(BIOS+2); drive->sect = drive->bios_sect = *(BIOS+14); drive->ctl = *(BIOS+8); -#if 0 drive->present = 1; -#endif } BIOS += 16; } diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.3.27/linux/drivers/block/ide-pci.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/ide-pci.c Fri Nov 12 10:12:11 1999 @@ -49,6 +49,7 @@ #define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) #define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) #define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) +#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) #define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) #define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) @@ -61,66 +62,17 @@ #define IDE_IGNORE ((void *)-1) -#ifdef CONFIG_BLK_DEV_TRM290 -extern void ide_init_trm290(ide_hwif_t *); -#define INIT_TRM290 &ide_init_trm290 -#else -#define INIT_TRM290 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_OPTI621 -extern void ide_init_opti621(ide_hwif_t *); -#define INIT_OPTI621 &ide_init_opti621 -#else -#define INIT_OPTI621 NULL -#endif - -#ifdef CONFIG_BLK_DEV_NS87415 -extern void ide_init_ns87415(ide_hwif_t *); -#define INIT_NS87415 &ide_init_ns87415 -#else -#define INIT_NS87415 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_CMD646 -extern void ide_init_cmd646(ide_hwif_t *); -#define INIT_CMD646 &ide_init_cmd646 -#else -#ifdef __sparc_v9__ -#define INIT_CMD646 IDE_IGNORE -#else -#define INIT_CMD646 NULL -#endif -#endif - -#ifdef CONFIG_BLK_DEV_SL82C105 -extern void ide_init_sl82c105(ide_hwif_t *); -#define INIT_W82C105 &ide_init_sl82c105 -#else -#define INIT_W82C105 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_RZ1000 -extern void ide_init_rz1000(ide_hwif_t *); -#define INIT_RZ1000 &ide_init_rz1000 -#else -#define INIT_RZ1000 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); -extern unsigned int ata66_via82cxxx(ide_hwif_t *); -extern void ide_init_via82cxxx(ide_hwif_t *); -extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#define PCI_VIA82CXXX &pci_init_via82cxxx -#define ATA66_VIA82CXXX &ata66_via82cxxx -#define INIT_VIA82CXXX &ide_init_via82cxxx -#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx +#ifdef CONFIG_BLK_DEV_AEC6210 +extern unsigned int pci_init_aec6210(struct pci_dev *, const char *); +extern void ide_init_aec6210(ide_hwif_t *); +extern void ide_dmacapable_aec6210(ide_hwif_t *, unsigned long); +#define PCI_AEC6210 &pci_init_aec6210 +#define INIT_AEC6210 &ide_init_aec6210 +#define DMA_AEC6210 &ide_dmacapable_aec6210 #else -#define PCI_VIA82CXXX NULL -#define ATA66_VIA82CXXX NULL -#define INIT_VIA82CXXX NULL -#define DMA_VIA82CXXX NULL +#define PCI_AEC6210 NULL +#define INIT_AEC6210 NULL +#define DMA_AEC6210 NULL #endif #ifdef CONFIG_BLK_DEV_ALI15X3 @@ -139,6 +91,17 @@ #define DMA_ALI15X3 NULL #endif +#ifdef CONFIG_BLK_DEV_CMD646 +extern void ide_init_cmd646(ide_hwif_t *); +#define INIT_CMD646 &ide_init_cmd646 +#else +#ifdef __sparc_v9__ +#define INIT_CMD646 IDE_IGNORE +#else +#define INIT_CMD646 NULL +#endif +#endif + #ifdef CONFIG_BLK_DEV_CY82C693 extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); extern void ide_init_cy82c693(ide_hwif_t *); @@ -149,32 +112,7 @@ #define INIT_CY82C693 NULL #endif -#ifdef CONFIG_BLK_DEV_PDC202XX -extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); -extern unsigned int ata66_pdc202xx(ide_hwif_t *); -extern void ide_init_pdc202xx(ide_hwif_t *); -#define PCI_PDC202XX &pci_init_pdc202xx -#define ATA66_PDC202XX &ata66_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx -#else -#define PCI_PDC202XX NULL -#define ATA66_PDC202XX NULL -#define INIT_PDC202XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_PIIX -extern void ide_init_piix(ide_hwif_t *); -#define INIT_PIIX &ide_init_piix -#else -#define INIT_PIIX NULL -#endif - -#ifdef CONFIG_BLK_DEV_AEC6210 -extern unsigned int pci_init_aec6210(struct pci_dev *, const char *); -#define PCI_AEC6210 &pci_init_aec6210 -#else -#define PCI_AEC6210 NULL -#endif +#define INIT_CX5530 NULL #ifdef CONFIG_BLK_DEV_HPT34X extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); @@ -204,6 +142,52 @@ #define DMA_HPT366 NULL #endif +#ifdef CONFIG_BLK_DEV_NS87415 +extern void ide_init_ns87415(ide_hwif_t *); +#define INIT_NS87415 &ide_init_ns87415 +#else +#define INIT_NS87415 IDE_IGNORE +#endif + +#ifdef CONFIG_BLK_DEV_OPTI621 +extern void ide_init_opti621(ide_hwif_t *); +#define INIT_OPTI621 &ide_init_opti621 +#else +#define INIT_OPTI621 NULL +#endif + +#ifdef CONFIG_BLK_DEV_PDC202XX +extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); +extern unsigned int ata66_pdc202xx(ide_hwif_t *); +extern void ide_init_pdc202xx(ide_hwif_t *); +#define PCI_PDC202XX &pci_init_pdc202xx +#define ATA66_PDC202XX &ata66_pdc202xx +#define INIT_PDC202XX &ide_init_pdc202xx +#else +#define PCI_PDC202XX NULL +#define ATA66_PDC202XX NULL +#define INIT_PDC202XX NULL +#endif + +#ifdef CONFIG_BLK_DEV_PIIX +extern unsigned int pci_init_piix(struct pci_dev *, const char *); +extern void ide_init_piix(ide_hwif_t *); +#define PCI_PIIX &pci_init_piix +#define INIT_PIIX &ide_init_piix +#else +#define PCI_PIIX NULL +#define INIT_PIIX NULL +#endif + +#ifdef CONFIG_BLK_DEV_RZ1000 +extern void ide_init_rz1000(ide_hwif_t *); +#define INIT_RZ1000 &ide_init_rz1000 +#else +#define INIT_RZ1000 IDE_IGNORE +#endif + +#define INIT_SAMURAI NULL + #ifdef CONFIG_BLK_DEV_SIS5513 extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); extern unsigned int ata66_sis5513(ide_hwif_t *); @@ -217,8 +201,35 @@ #define INIT_SIS5513 NULL #endif -#define INIT_SAMURAI NULL -#define INIT_CX5530 NULL +#ifdef CONFIG_BLK_DEV_SL82C105 +extern void ide_init_sl82c105(ide_hwif_t *); +#define INIT_W82C105 &ide_init_sl82c105 +#else +#define INIT_W82C105 IDE_IGNORE +#endif + +#ifdef CONFIG_BLK_DEV_TRM290 +extern void ide_init_trm290(ide_hwif_t *); +#define INIT_TRM290 &ide_init_trm290 +#else +#define INIT_TRM290 IDE_IGNORE +#endif + +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); +extern unsigned int ata66_via82cxxx(ide_hwif_t *); +extern void ide_init_via82cxxx(ide_hwif_t *); +extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); +#define PCI_VIA82CXXX &pci_init_via82cxxx +#define ATA66_VIA82CXXX &ata66_via82cxxx +#define INIT_VIA82CXXX &ide_init_via82cxxx +#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx +#else +#define PCI_VIA82CXXX NULL +#define ATA66_VIA82CXXX NULL +#define INIT_VIA82CXXX NULL +#define DMA_VIA82CXXX NULL +#endif typedef struct ide_pci_enablebit_s { byte reg; /* byte pci reg holding the enable-bit */ @@ -241,8 +252,8 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = { {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, @@ -260,12 +271,13 @@ {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, INIT_AEC6210, DMA_AEC6210, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, {DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 256 }, + {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, @@ -549,7 +561,8 @@ } } if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF)) { + IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) { hwif->irq = hwif->channel ? 15 : 14; goto bypass_umc_dma; } diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.3.27/linux/drivers/block/ide-probe.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/ide-probe.c Fri Nov 12 10:12:11 1999 @@ -402,7 +402,7 @@ if (hwif->noprobe) return; if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { - extern void probe_cmos_for_drives(ide_hwif_t *hwif); + extern void probe_cmos_for_drives(ide_hwif_t *); probe_cmos_for_drives (hwif); } @@ -575,10 +575,6 @@ hwgroup->handler = NULL; hwgroup->drive = NULL; hwgroup->busy = 0; - hwgroup->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED; -#if (DEBUG_SPINLOCK > 0) - printk("hwgroup(%s) spinlock is %p\n", hwif->name, &hwgroup->spinlock); /* FIXME */ -#endif init_timer(&hwgroup->timer); hwgroup->timer.function = &ide_timer_expiry; hwgroup->timer.data = (unsigned long) hwgroup; diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c --- v2.3.27/linux/drivers/block/ide-proc.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/block/ide-proc.c Fri Nov 12 10:12:11 1999 @@ -78,6 +78,11 @@ int (*ali_display_info)(char *, char **, off_t, int, int) = NULL; #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_PIIX +extern byte piix_proc; +int (*piix_display_info)(char *, char **, off_t, int, int) = NULL; +#endif /* CONFIG_BLK_DEV_PIIX */ + #ifdef CONFIG_BLK_DEV_SIS5513 extern byte sis_proc; int (*sis_display_info)(char *, char **, off_t, int, int) = NULL; @@ -372,6 +377,8 @@ case ide_pdc4030: name = "pdc4030"; break; case ide_rz1000: name = "rz1000"; break; case ide_trm290: name = "trm290"; break; + case ide_cmd646: name = "cmd646"; break; + case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; default: name = "(unknown)"; break; } @@ -752,7 +759,6 @@ for (h = 0; h < MAX_HWIFS; h++) { ide_hwif_t *hwif = &ide_hwifs[h]; int exist = (hwif->proc != NULL); - #if 0 if (!hwif->present) continue; @@ -781,6 +787,10 @@ if ((ali_display_info) && (ali_proc)) create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info); #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_PIIX + if ((piix_display_info) && (piix_proc)) + create_proc_info_entry("piix", 0, proc_ide_root, piix_display_info); +#endif /* CONFIG_BLK_DEV_PIIX */ #ifdef CONFIG_BLK_DEV_SIS5513 if ((sis_display_info) && (sis_proc)) create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info); @@ -801,6 +811,10 @@ if ((ali_display_info) && (ali_proc)) remove_proc_entry("ide/ali",0); #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_PIIX + if ((piix_display_info) && (piix_proc)) + remove_proc_entry("ide/piix",0); +#endif /* CONFIG_BLK_DEV_PIIX */ #ifdef CONFIG_BLK_DEV_SIS5513 if ((sis_display_info) && (sis_proc)) remove_proc_entry("ide/sis", 0); @@ -809,6 +823,7 @@ if ((via_display_info) && (via_proc)) remove_proc_entry("ide/via",0); #endif /* CONFIG_BLK_DEV_VIA82CXXX */ + remove_proc_entry("ide/drivers", 0); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v2.3.27/linux/drivers/block/ide-tape.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/ide-tape.c Fri Nov 12 10:12:11 1999 @@ -526,7 +526,7 @@ int b_count; byte *buffer; /* Data buffer */ byte *current_position; /* Pointer into the above buffer */ - void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ + ide_startstop_t (*callback) (ide_drive_t *); /* Called when this packet command is completed */ byte pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */ unsigned int flags; /* Status/Action bit flags */ } idetape_pc_t; @@ -1660,7 +1660,7 @@ } } -static void idetape_request_sense_callback (ide_drive_t *drive) +static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -1674,6 +1674,7 @@ printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); idetape_end_request (0,HWGROUP (drive)); } + return ide_stopped; } /* @@ -1705,7 +1706,7 @@ * last packet command. We queue a request sense packet command in * the head of the request list. */ -static void idetape_retry_pc (ide_drive_t *drive) +static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc; @@ -1718,6 +1719,7 @@ idetape_create_request_sense_cmd (pc); set_bit (IDETAPE_IGNORE_DSC, &tape->flags); idetape_queue_pc_head (drive, pc, rq); + return ide_stopped; } /* @@ -1728,7 +1730,7 @@ * algorithm described before idetape_issue_packet_command. * */ -static void idetape_pc_intr (ide_drive_t *drive) +static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_status_reg_t status; @@ -1784,11 +1786,9 @@ #endif /* IDETAPE_DEBUG_LOG */ if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { printk (KERN_ERR "ide-tape: I/O error in request sense command\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } - idetape_retry_pc (drive); /* Retry operation */ - return; + return idetape_retry_pc (drive); /* Retry operation */ } pc->error = 0; if (test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ @@ -1796,20 +1796,18 @@ tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; idetape_postpone_request (drive); /* Allow ide.c to handle other requests */ - return; + return ide_stopped; } if (tape->failed_pc == pc) tape->failed_pc=NULL; - pc->callback(drive); /* Command finished - Call the callback function */ - return; + return pc->callback(drive); /* Command finished - Call the callback function */ } #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n"); printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ @@ -1818,14 +1816,12 @@ if (ireason.b.cod) { printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ temp = pc->actually_transferred + bcount.all; @@ -1834,7 +1830,7 @@ printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); idetape_discard_data (drive,bcount.all); ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); - return; + return ide_started; } #if IDETAPE_DEBUG_LOG printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n"); @@ -1856,6 +1852,7 @@ pc->current_position+=bcount.all; ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); /* And set the interrupt handler again */ + return ide_started; } /* @@ -1901,16 +1898,17 @@ * */ -static void idetape_transfer_pc(ide_drive_t *drive) +static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; idetape_ireason_reg_t ireason; int retries = 100; + ide_startstop_t startstop; - if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); - return; + return startstop; } ireason.all=IN_BYTE (IDE_IREASON_REG); while (retries-- && (!ireason.b.cod || ireason.b.io)) { @@ -1925,14 +1923,14 @@ } if (!ireason.b.cod || ireason.b.io) { printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ + return ide_started; } -static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) +static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) { idetape_tape_t *tape = drive->driver_data; idetape_bcount_reg_t bcount; @@ -1961,8 +1959,7 @@ pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ } tape->failed_pc=NULL; - pc->callback(drive); - return; + return pc->callback(drive); } #if IDETAPE_DEBUG_LOG printk (KERN_INFO "Retry number - %d\n",pc->retries); @@ -1997,13 +1994,14 @@ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); + return ide_started; } else { OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - idetape_transfer_pc(drive); + return idetape_transfer_pc(drive); } } -static void idetape_media_access_finished (ide_drive_t *drive) +static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; @@ -2013,8 +2011,7 @@ if (status.b.dsc) { if (status.b.check) { /* Error detected */ printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); - idetape_retry_pc (drive); /* Retry operation */ - return; + return idetape_retry_pc (drive); /* Retry operation */ } pc->error = 0; if (tape->failed_pc == pc) @@ -2023,13 +2020,13 @@ pc->error = IDETAPE_ERROR_GENERAL; tape->failed_pc = NULL; } - pc->callback (drive); + return pc->callback (drive); } /* * General packet command callback function. */ -static void idetape_pc_callback (ide_drive_t *drive) +static ide_startstop_t idetape_pc_callback (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -2038,9 +2035,10 @@ #endif /* IDETAPE_DEBUG_LOG */ idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive)); + return ide_stopped; } -static void idetape_rw_callback (ide_drive_t *drive) +static ide_startstop_t idetape_rw_callback (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; @@ -2057,6 +2055,7 @@ idetape_end_request (1, HWGROUP (drive)); else idetape_end_request (tape->pc->error, HWGROUP (drive)); + return ide_stopped; } static void idetape_create_locate_cmd (idetape_pc_t *pc, unsigned int block, byte partition) @@ -2175,7 +2174,7 @@ set_bit (PC_DMA_RECOMMENDED, &pc->flags); } -static void idetape_read_position_callback (ide_drive_t *drive) +static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; idetape_read_position_result_t *result; @@ -2205,6 +2204,7 @@ } } else idetape_end_request (0,HWGROUP (drive)); + return ide_stopped; } static void idetape_create_read_position_cmd (idetape_pc_t *pc) @@ -2218,7 +2218,7 @@ /* * idetape_do_request is our request handling function. */ -static void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc; @@ -2234,24 +2234,23 @@ /* * We do not support buffer cache originated requests. */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue\n", drive->name); + printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd); ide_end_request (0,HWGROUP (drive)); /* Let the common code handle it */ - return; + return ide_stopped; } /* * Retry a failed packet command */ if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - idetape_issue_packet_command (drive, tape->failed_pc); - return; + return idetape_issue_packet_command (drive, tape->failed_pc); } #if IDETAPE_DEBUG_BUGS if (postponed_rq != NULL) if (rq != postponed_rq) { printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); idetape_end_request (0,HWGROUP (drive)); - return; + return ide_stopped; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -2271,15 +2270,16 @@ tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT; } else if ((signed long) (jiffies - tape->dsc_timeout) > 0) { printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name); - if (rq->cmd == IDETAPE_PC_RQ2) + if (rq->cmd == IDETAPE_PC_RQ2) { idetape_media_access_finished (drive); - else - ide_do_reset (drive); - return; + return ide_stopped; + } else { + return ide_do_reset (drive); + } } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; idetape_postpone_request (drive); - return; + return ide_stopped; } switch (rq->cmd) { case IDETAPE_READ_RQ: @@ -2294,20 +2294,20 @@ rq->cmd = IDETAPE_WRITE_RQ; rq->errors = IDETAPE_ERROR_EOD; idetape_end_request (1, HWGROUP(drive)); - return; + return ide_stopped; case IDETAPE_PC_RQ1: pc=(idetape_pc_t *) rq->buffer; rq->cmd = IDETAPE_PC_RQ2; break; case IDETAPE_PC_RQ2: idetape_media_access_finished (drive); - return; + return ide_stopped; default: printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); idetape_end_request (0,HWGROUP (drive)); - return; + return ide_stopped; } - idetape_issue_packet_command (drive, pc); + return idetape_issue_packet_command (drive, pc); } /* diff -u --recursive --new-file v2.3.27/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.3.27/linux/drivers/block/ide.c Thu Nov 11 20:11:32 1999 +++ linux/drivers/block/ide.c Fri Nov 12 10:12:11 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 6.20 July 10, 1999 + * linux/drivers/block/ide.c Version 6.21 November 9, 1999 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -106,15 +106,18 @@ * ATA-66 compliant, but have yet to determine a method * of verification of the 80c cable presence. * Specifically Promise's PDC20262 chipset. + * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old + * hat that clarified original low level driver design. * * Some additional driver compile-time options are in ./include/linux/ide.h * * To do, in likely order of completion: * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f -*/ + * + */ -#define REVISION "Revision: 6.20" -#define VERSION "Id: ide.c 6.20 1999/07/10" +#define REVISION "Revision: 6.21" +#define VERSION "Id: ide.c 6.21 1999/11/10" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -186,7 +189,7 @@ * For really screwy hardware (hey, at least it *can* be used with Linux) * we can enforce a minimum delay time between successive operations. */ -static unsigned long read_timer(void) +static unsigned long read_timer (void) { unsigned long t, flags; int i; @@ -472,7 +475,7 @@ #if 0 udelay(1); /* need to guarantee 400ns since last command was issued */ #endif - if (GET_STAT() & BUSY_STAT) + if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */ return 0; /* drive busy: definitely not interrupting */ return 1; /* drive ready: *might* be interrupting */ } @@ -480,7 +483,7 @@ /* * This is our end_request replacement function. */ -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) +void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup) { struct request *rq; unsigned long flags; @@ -511,18 +514,16 @@ unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); - spin_lock_irqsave(&hwgroup->spinlock, flags); -#ifdef DEBUG + spin_lock_irqsave(&io_request_lock, flags); if (hwgroup->handler != NULL) { printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n", drive->name, hwgroup->handler, handler); } -#endif hwgroup->handler = handler; hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; - add_timer(&(hwgroup->timer)); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + add_timer(&hwgroup->timer); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -557,7 +558,7 @@ } } -static void do_reset1 (ide_drive_t *, int); /* needed below */ +static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */ /* * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms @@ -565,7 +566,7 @@ * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */ -static void atapi_reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); byte stat; @@ -578,14 +579,14 @@ } else { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - return; /* continue polling */ + return ide_started; /* continue polling */ } hwgroup->poll_timeout = 0; /* end of polling */ printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); - do_reset1 (drive, 1); /* do it the old fashioned way */ - return; + return do_reset1 (drive, 1); /* do it the old fashioned way */ } hwgroup->poll_timeout = 0; /* done polling */ + return ide_stopped; } /* @@ -594,7 +595,7 @@ * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */ -static void reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); @@ -603,7 +604,7 @@ if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - return; /* continue polling */ + return ide_started; /* continue polling */ } printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); } else { @@ -635,6 +636,7 @@ } } hwgroup->poll_timeout = 0; /* done polling */ + return ide_stopped; } static void pre_reset (ide_drive_t *drive) @@ -664,7 +666,7 @@ * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */ -static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) { unsigned int unit; unsigned long flags; @@ -683,7 +685,7 @@ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); __restore_flags (flags); /* local CPU only */ - return; + return ide_started; } /* @@ -696,7 +698,7 @@ #if OK_TO_RESET_CONTROLLER if (!IDE_CONTROL_REG) { __restore_flags(flags); - return; + return ide_stopped; } /* * Note that we also set nIEN while resetting the device, @@ -724,14 +726,15 @@ #endif /* OK_TO_RESET_CONTROLLER */ __restore_flags (flags); /* local CPU only */ + return ide_started; } /* * ide_do_reset() is the entry point to the drive/interface reset code. */ -void ide_do_reset (ide_drive_t *drive) +ide_startstop_t ide_do_reset (ide_drive_t *drive) { - do_reset1 (drive, 0); + return do_reset1 (drive, 0); } /* @@ -757,11 +760,8 @@ HWGROUP(drive)->rq = NULL; rq->rq_status = RQ_INACTIVE; spin_unlock_irqrestore(&io_request_lock, flags); - save_flags(flags); /* all CPUs; overkill? */ - cli(); /* all CPUs; overkill? */ if (rq->sem != NULL) up(rq->sem); /* inform originator that rq has been serviced */ - restore_flags(flags); /* all CPUs; overkill? */ } /* @@ -854,19 +854,19 @@ /* * ide_error() takes action based on the error returned by the drive. */ -void ide_error (ide_drive_t *drive, const char *msg, byte stat) +ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) { struct request *rq; byte err; err = ide_dump_status(drive, msg, stat); if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return; + return ide_stopped; /* retry only "normal" I/O: */ if (rq->cmd == IDE_DRIVE_CMD) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); - return; + return ide_stopped; } if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; @@ -875,7 +875,7 @@ /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return; /* some newer drives don't support WIN_SPECIFY */ + return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) ; /* UDMA crc error -- just retry the operation */ else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ @@ -897,19 +897,20 @@ } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; - ide_do_reset(drive); - return; - } else if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) drive->special.b.recalibrate = 1; ++rq->errors; } + return ide_stopped; } /* * Issue a simple drive command * The drive must be selected beforehand. */ -void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) +void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) { ide_set_handler (drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) @@ -921,7 +922,7 @@ /* * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. */ -static void drive_cmd_intr (ide_drive_t *drive) +static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; byte *args = (byte *) rq->buffer; @@ -938,17 +939,17 @@ udelay(100); } - if (OK_STAT(stat, READY_STAT, BAD_STAT)) - ide_end_drive_cmd (drive, stat, GET_ERR()); - else - ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ + ide_end_drive_cmd (drive, stat, GET_ERR()); + return ide_stopped; } /* * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT * commands to a drive. It used to do much more, but has been scaled back. */ -static inline void do_special (ide_drive_t *drive) +static ide_startstop_t do_special (ide_drive_t *drive) { special_t *s = &drive->special; @@ -961,11 +962,12 @@ if (tuneproc != NULL) tuneproc(drive, drive->tune_req); } else if (drive->driver != NULL) { - DRIVER(drive)->special(drive); + return DRIVER(drive)->special(drive); } else if (s->all) { printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); s->all = 0; } + return ide_stopped; } /* @@ -979,12 +981,11 @@ * setting a timer to wake up at half second intervals thereafter, * until timeout is achieved, before timing out. */ -int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout) -{ +int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { byte stat; int i; unsigned long flags; - + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ if ((stat = GET_STAT()) & BUSY_STAT) { __save_flags(flags); /* local CPU only */ @@ -993,7 +994,7 @@ while ((stat = GET_STAT()) & BUSY_STAT) { if (0 < (signed long)(jiffies - timeout)) { __restore_flags(flags); /* local CPU only */ - ide_error(drive, "status timeout", stat); + *startstop = ide_error(drive, "status timeout", stat); return 1; } } @@ -1011,7 +1012,7 @@ if (OK_STAT((stat = GET_STAT()), good, bad)) return 0; } - ide_error(drive, "status error", stat); + *startstop = ide_error(drive, "status error", stat); return 1; } @@ -1019,7 +1020,7 @@ * execute_drive_cmd() issues a special drive command, * usually initiated by ioctl() from the external hdparm program. */ -static void execute_drive_cmd (ide_drive_t *drive, struct request *rq) +static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) { byte *args = rq->buffer; if (args) { @@ -1033,11 +1034,11 @@ OUT_BYTE(args[2],IDE_FEATURE_REG); OUT_BYTE(args[1],IDE_SECTOR_REG); ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return; + return ide_started; } OUT_BYTE(args[2],IDE_FEATURE_REG); ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return; + return ide_started; } else { /* * NULL is actually a valid way of waiting for @@ -1047,21 +1048,21 @@ printk("%s: DRIVE_CMD (null)\n", drive->name); #endif ide_end_drive_cmd(drive, GET_STAT(), GET_ERR()); - return; + return ide_stopped; } } /* * start_request() initiates handling of a new I/O request */ -static inline void start_request (ide_drive_t *drive) +static ide_startstop_t start_request (ide_drive_t *drive) { + ide_startstop_t startstop; unsigned long block, blockend; struct request *rq = drive->queue; unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS; ide_hwif_t *hwif = HWIF(drive); - ide__sti(); /* local CPU only */ #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); #endif @@ -1094,29 +1095,27 @@ #endif SELECT_DRIVE(hwif, drive); - if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { + if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { printk("%s: drive not ready for command\n", drive->name); - return; + return startstop; } if (!drive->special.all) { if (rq->cmd == IDE_DRIVE_CMD) { - execute_drive_cmd(drive, rq); - return; + return execute_drive_cmd(drive, rq); } if (drive->driver != NULL) { - DRIVER(drive)->do_request(drive, rq, block); - return; + return (DRIVER(drive)->do_request(drive, rq, block)); } printk("%s: media type %d not supported\n", drive->name, drive->media); goto kill_rq; } - do_special(drive); - return; + return do_special(drive); kill_rq: if (drive->driver != NULL) DRIVER(drive)->end_request(0, HWGROUP(drive)); else ide_end_request(0, HWGROUP(drive)); + return ide_stopped; } /* @@ -1177,22 +1176,54 @@ } /* - * Caller must have already acquired spinlock using *spinflags + * Issue a new request to a drive from hwgroup + * Caller must have already done spin_lock_irqsave(&io_request_lock, ..); + * + * A hwgroup is a serialized group of IDE interfaces. Usually there is + * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) + * may have both interfaces in a single hwgroup to "serialize" access. + * Or possibly multiple ISA interfaces can share a common IRQ by being grouped + * together into one hwgroup for serialized access. + * + * Note also that several hwgroups can end up sharing a single IRQ, + * possibly along with many other devices. This is especially common in + * PCI-based systems with off-board IDE controller cards. + * + * The IDE driver uses the single global io_request_lock spinlock to protect + * access to the request queues, and to protect the hwgroup->busy flag. + * + * The first thread into the driver for a particular hwgroup sets the + * hwgroup->busy flag to indicate that this hwgroup is now active, + * and then initiates processing of the top request from the request queue. + * + * Other threads attempting entry notice the busy setting, and will simply + * queue their new requests and exit immediately. Note that hwgroup->busy + * remains set even when the driver is merely awaiting the next interrupt. + * Thus, the meaning is "this hwgroup is busy processing a request". + * + * When processing of a request completes, the completing thread or IRQ-handler + * will start the next request from the queue. If no more work remains, + * the driver will clear the hwgroup->busy flag and exit. + * + * The io_request_lock (spinlock) is used to protect all access to the + * hwgroup->busy flag, but is otherwise not needed for most processing in + * the driver. This makes the driver much more friendlier to shared IRQs + * than previous designs, while remaining 100% (?) SMP safe and capable. */ -static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq) +static void ide_do_request (ide_hwgroup_t *hwgroup) { struct blk_dev_struct *bdev; ide_drive_t *drive; ide_hwif_t *hwif; - unsigned long io_flags; + ide_startstop_t startstop; - hwgroup->busy = 1; - while (hwgroup->handler == NULL) { - spin_lock_irqsave(&io_request_lock, io_flags); + ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ + + while (!hwgroup->busy) { + hwgroup->busy = 1; drive = choose_drive(hwgroup); if (drive == NULL) { unsigned long sleep = 0; - hwgroup->rq = NULL; drive = hwgroup->drive; do { @@ -1202,27 +1233,34 @@ if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) sleep = drive->sleep; } while ((drive = drive->next) != hwgroup->drive); - spin_unlock_irqrestore(&io_request_lock, io_flags); if (sleep) { + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) sleep = jiffies + WAIT_MIN_SLEEP; #if 1 if (hwgroup->timer.next || hwgroup->timer.prev) printk("ide_set_handler: timer already active\n"); #endif + hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */ mod_timer(&hwgroup->timer, sleep); + /* we purposely leave hwgroup->busy==1 while sleeping */ } else { /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */ ide_release_lock(&ide_lock); /* for atari only */ + hwgroup->busy = 0; } - hwgroup->busy = 0; - return; + return; /* no more work for this hwgroup (for now) */ } hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && - hwif->io_ports[IDE_CONTROL_OFFSET]) + if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) { /* set nIEN for previous hwif */ OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]); + } hwgroup->hwif = hwif; hwgroup->drive = drive; drive->sleep = 0; @@ -1232,39 +1270,13 @@ if (bdev->current_request == &bdev->plug) /* FIXME: paranoia */ printk("%s: Huh? nuking plugged queue\n", drive->name); bdev->current_request = hwgroup->rq = drive->queue; - spin_unlock_irqrestore(&io_request_lock, io_flags); - -#if 0 - if (hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); - start_request(drive); - spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); - if (hwif->irq != masked_irq) - enable_irq(hwif->irq); -#else - - if (masked_irq && hwif->irq != masked_irq) { - printk("%s: (disable_irq) %smasked_irq %d\n", - drive->name, - masked_irq ? "" : "un_", hwif->irq); - -#if 0 - disable_irq(hwif->irq); -#else - disable_irq_nosync(hwif->irq); -#endif - } - spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); - start_request(drive); - spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); - if (masked_irq && hwif->irq != masked_irq) { - printk("%s: (enable_irq) %smasked_irq %d\n", - drive->name, - masked_irq ? "" : "un_", hwif->irq); - enable_irq(hwif->irq); - } -#endif + spin_unlock(&io_request_lock); + if (!hwif->serialized) /* play it safe with buggy hardware */ + ide__sti(); + startstop = start_request(drive); + spin_lock_irq(&io_request_lock); + if (startstop == ide_stopped) + hwgroup->busy = 0; } } @@ -1278,179 +1290,158 @@ return &hwif->drives[DEVICE_NR(dev) & 1].queue; } -/* - * do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy. - */ -static void do_hwgroup_request (ide_hwgroup_t *hwgroup) -{ - unsigned long flags; - - spin_lock_irqsave(&hwgroup->spinlock, flags); - if (hwgroup->busy) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - return; - } - del_timer(&hwgroup->timer); - ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only */ - ide_do_request(hwgroup, &flags, 0); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); -} - -/* - * ll_rw_blk.c invokes our do_idex_request() function - * with the io_request_spinlock already grabbed. - * Since we need to do our own spinlock's internally, - * on paths that don't necessarily originate through the - * do_idex_request() path, we have to undo the spinlock on entry, - * and restore it again on exit. - * Fortunately, this is mostly a nop for non-SMP kernels. - */ -static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup) -{ - spin_unlock(&io_request_lock); - do_hwgroup_request (hwgroup); - spin_lock_irq(&io_request_lock); -} - void do_ide0_request (void) { - unlock_do_hwgroup_request (ide_hwifs[0].hwgroup); + ide_do_request (ide_hwifs[0].hwgroup); } #if MAX_HWIFS > 1 void do_ide1_request (void) { - unlock_do_hwgroup_request (ide_hwifs[1].hwgroup); + ide_do_request (ide_hwifs[1].hwgroup); } #endif /* MAX_HWIFS > 1 */ #if MAX_HWIFS > 2 void do_ide2_request (void) { - unlock_do_hwgroup_request (ide_hwifs[2].hwgroup); + ide_do_request (ide_hwifs[2].hwgroup); } #endif /* MAX_HWIFS > 2 */ #if MAX_HWIFS > 3 void do_ide3_request (void) { - unlock_do_hwgroup_request (ide_hwifs[3].hwgroup); + ide_do_request (ide_hwifs[3].hwgroup); } #endif /* MAX_HWIFS > 3 */ #if MAX_HWIFS > 4 void do_ide4_request (void) { - unlock_do_hwgroup_request (ide_hwifs[4].hwgroup); + ide_do_request (ide_hwifs[4].hwgroup); } #endif /* MAX_HWIFS > 4 */ #if MAX_HWIFS > 5 void do_ide5_request (void) { - unlock_do_hwgroup_request (ide_hwifs[5].hwgroup); + ide_do_request (ide_hwifs[5].hwgroup); } #endif /* MAX_HWIFS > 5 */ #if MAX_HWIFS > 6 void do_ide6_request (void) { - unlock_do_hwgroup_request (ide_hwifs[6].hwgroup); + ide_do_request (ide_hwifs[6].hwgroup); } #endif /* MAX_HWIFS > 6 */ #if MAX_HWIFS > 7 void do_ide7_request (void) { - unlock_do_hwgroup_request (ide_hwifs[7].hwgroup); + ide_do_request (ide_hwifs[7].hwgroup); } #endif /* MAX_HWIFS > 7 */ #if MAX_HWIFS > 8 void do_ide8_request (void) { - unlock_do_hwgroup_request (ide_hwifs[8].hwgroup); + ide_do_request (ide_hwifs[8].hwgroup); } #endif /* MAX_HWIFS > 8 */ #if MAX_HWIFS > 9 void do_ide9_request (void) { - unlock_do_hwgroup_request (ide_hwifs[9].hwgroup); + ide_do_request (ide_hwifs[9].hwgroup); } #endif /* MAX_HWIFS > 9 */ -static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - unsigned long flags; - ide_drive_t *drive; - - spin_lock_irqsave(&hwgroup->spinlock, flags); - if (hwgroup->handler != NULL) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - return; - } - drive = hwgroup->drive; - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - ide_do_request(hwgroup, &flags, masked_irq); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); -} - +/* + * ide_timer_expiry() is our timeout function for all drive operations. + * But note that it can also be invoked as a result of a "sleep" operation + * triggered by the mod_timer() call in ide_do_request. + */ void ide_timer_expiry (unsigned long data) { - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_drive_t *drive; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_handler_t *handler; + ide_expiry_t *expiry; + unsigned long flags; + unsigned long wait; - spin_lock_irqsave(&hwgroup->spinlock, flags); - drive = hwgroup->drive; - if ((handler = hwgroup->handler) == NULL) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - do_hwgroup_request(hwgroup); - return; - } - - hwgroup->busy = 1; /* should already be "1" */ + spin_lock_irqsave(&io_request_lock, flags); + del_timer(&hwgroup->timer); - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&(hwgroup->timer)); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - return; + if ((handler = hwgroup->handler) == NULL) { + /* + * Either a marginal timeout occured + * (got the interrupt just as timer expired), + * or we were "sleeping" to give other devices a chance. + * Either way, we don't really want to complain about anything. + */ + if (hwgroup->sleeping) { + hwgroup->sleeping = 0; + hwgroup->busy = 0; } - } - - hwgroup->handler = NULL; - - if (hwgroup->poll_timeout != 0) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - handler(drive); - } else if (drive_is_ready(drive)) { - printk("%s: lost interrupt\n", drive->name); - (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - handler(drive); } else { - if (drive->waiting_for_dma) { - (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); - printk("%s: timeout waiting for DMA\n", drive->name); - /* - * need something here for HPT34X.......AMH - * irq timeout: status=0x58 { DriveReady SeekComplete DataRequest } - */ - (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); + ide_drive_t *drive = hwgroup->drive; + hwgroup->handler = NULL; + if (!drive) { + printk("ide_timer_expiry: hwgroup->drive was NULL\n"); + } else { + ide_hwif_t *hwif; + ide_startstop_t startstop; + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); + } + if ((expiry = hwgroup->expiry) != NULL) { + /* continue */ + if ((wait = expiry(drive)) != 0) { + /* reset timer */ + hwgroup->timer.expires = jiffies + wait; + add_timer(&hwgroup->timer); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + } + /* + * We need to simulate a real interrupt when invoking + * the handler() function, which means we need to globally + * mask the specific IRQ: + */ + spin_unlock(&io_request_lock); + hwif = HWIF(drive); + disable_irq(hwif->irq); + __cli(); /* local CPU only, as if we were handling an interrupt */ + if (hwgroup->poll_timeout != 0) { + startstop = handler(drive); + } else if (drive_is_ready(drive)) { + if (drive->waiting_for_dma) + (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); + (void)ide_ack_intr(hwif); + printk("%s: lost interrupt\n", drive->name); + startstop = handler(drive); + } else { + if (drive->waiting_for_dma) { + (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); + printk("%s: timeout waiting for DMA\n", drive->name); + (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); + } + startstop = ide_error(drive, "irq timeout", GET_STAT()); + } + set_recovery_timer(hwif); + drive->service_time = jiffies - drive->service_start; + enable_irq(hwif->irq); + spin_lock_irq(&io_request_lock); + if (startstop == ide_stopped) + hwgroup->busy = 0; } - spin_unlock_irqrestore(&hwgroup->spinlock, flags); - ide_error(drive, "irq timeout", GET_STAT()); } - start_next_request(hwgroup, 0); + ide_do_request(hwgroup); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -1500,6 +1491,7 @@ } } while ((hwif = hwif->next) != hwgroup->hwif); } + /* * entry point for all interrupts, caller does __cli() for us */ @@ -1510,13 +1502,13 @@ ide_hwif_t *hwif; ide_drive_t *drive; ide_handler_t *handler; + ide_startstop_t startstop; - __cli(); /* local CPU only */ - spin_lock_irqsave(&hwgroup->spinlock, flags); + spin_lock_irqsave(&io_request_lock, flags); hwif = hwgroup->hwif; if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); return; } @@ -1542,29 +1534,70 @@ * so we can safely try to do something about it: */ unexpected_intr(irq, hwgroup); +#ifdef CONFIG_BLK_DEV_IDEPCI + } else { + /* + * Whack the status register, just in case we have a leftover pending IRQ. + * + * Unless we are some version of a Promise Ultra66 :: PDC20262. + * We will hang like a rock.... + */ + byte skip_status = ((hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20262) || + (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT366)) ? 1 : 0; + if (!skip_status) + (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); +#endif /* CONFIG_BLK_DEV_IDEPCI */ } - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); return; } drive = hwgroup->drive; - if (!drive || !drive_is_ready(drive)) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + if (!drive) { + /* + * This should NEVER happen, and there isn't much we could do about it here. + */ + spin_unlock_irqrestore(&io_request_lock, flags); return; } + if (!drive_is_ready(drive)) { + /* + * This happens regularly when we share a PCI IRQ with another device. + * Unfortunately, it can also happen with some buggy drives that trigger + * the IRQ before their status register is up to date. Hopefully we have + * enough advance overhead that the latter isn't a problem. + */ + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); + } hwgroup->handler = NULL; - del_timer(&(hwgroup->timer)); - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + del_timer(&hwgroup->timer); + spin_unlock(&io_request_lock); if (drive->unmask) ide__sti(); /* local CPU only */ - handler(drive); /* service this interrupt, may set handler for next interrupt */ + startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ + spin_lock_irq(&io_request_lock); /* * Note that handler() may have set things up for another * interrupt to occur soon, but it cannot happen until * we exit from this routine, because it will be the - * same irq as is currently being serviced here, - * and Linux won't allow another (on any CPU) until we return. + * same irq as is currently being serviced here, and Linux + * won't allow another of the same (on any CPU) until we return. */ - start_next_request(hwgroup, hwif->irq); + set_recovery_timer(HWIF(drive)); + drive->service_time = jiffies - drive->service_start; + if (startstop == ide_stopped) { + if (hwgroup->handler == NULL) { /* paranoia */ + hwgroup->busy = 0; + ide_do_request(hwgroup); + } else { + printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name); + } + } + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -1649,7 +1682,6 @@ rq->rq_dev = MKDEV(major,(drive->select.b.unit)<sem = &sem; - spin_lock_irqsave(&io_request_lock, flags); cur_rq = drive->queue; if (cur_rq == NULL || action == ide_preempt) { @@ -1665,13 +1697,14 @@ rq->next = cur_rq->next; cur_rq->next = rq; } + ide_do_request(hwgroup); spin_unlock_irqrestore(&io_request_lock, flags); - do_hwgroup_request(hwgroup); if (action == ide_wait) { - down(&sem); /* wait for it to be serviced */ - rq->sem = NULL; + down(&sem); /* wait for it to be serviced */ + return rq->errors ? -EIO : 0; /* return -EIO if errors */ } - return rq->errors ? -EIO : 0; /* return -EIO if errors */ + return 0; + } /* @@ -1682,7 +1715,7 @@ * usage == 1 (we need an open channel to use an ioctl :-), so this * is our limit. */ -int ide_revalidate_disk(kdev_t i_rdev) +int ide_revalidate_disk (kdev_t i_rdev) { ide_drive_t *drive; ide_hwgroup_t *hwgroup; @@ -1694,14 +1727,14 @@ major = MAJOR(i_rdev); minor = drive->select.b.unit << PARTN_BITS; hwgroup = HWGROUP(drive); - spin_lock_irqsave(&hwgroup->spinlock, flags); + spin_lock_irqsave(&io_request_lock, flags); if (drive->busy || (drive->usage > 1)) { - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); return -EBUSY; }; drive->busy = 1; MOD_INC_USE_COUNT; - spin_unlock_irqrestore(&hwgroup->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); for (p = 0; p < (1<part[p].nr_sects > 0) { @@ -1767,7 +1800,7 @@ #endif /* CONFIG_KMOD */ } -static int ide_open(struct inode * inode, struct file * filp) +static int ide_open (struct inode * inode, struct file * filp) { ide_drive_t *drive; int rc; @@ -1807,7 +1840,7 @@ * Releasing a block device means we sync() it, so that it can safely * be forgotten about... */ -static int ide_release(struct inode * inode, struct file * file) +static int ide_release (struct inode * inode, struct file * file) { ide_drive_t *drive; @@ -1821,7 +1854,7 @@ return 0; } -int ide_replace_subdriver(ide_drive_t *drive, const char *driver) +int ide_replace_subdriver (ide_drive_t *drive, const char *driver) { if (!drive->present || drive->busy || drive->usage) goto abort; @@ -1979,6 +2012,7 @@ init_hwif_data (index); /* restore hwif data to pristine status */ hwif->hwgroup = old_hwif.hwgroup; hwif->tuneproc = old_hwif.tuneproc; + hwif->resetproc = old_hwif.resetproc; hwif->dmaproc = old_hwif.dmaproc; hwif->dma_base = old_hwif.dma_base; hwif->dma_extra = old_hwif.dma_extra; @@ -2089,7 +2123,7 @@ return ide_register_hw(&hw, NULL); } -void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; @@ -2115,7 +2149,7 @@ kfree(setting); } -void ide_remove_setting(ide_drive_t *drive, char *name) +void ide_remove_setting (ide_drive_t *drive, char *name) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; @@ -2128,7 +2162,7 @@ kfree(setting); } -static ide_settings_t *ide_find_setting_by_ioctl(ide_drive_t *drive, int cmd) +static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) { ide_settings_t *setting = drive->settings; @@ -2140,7 +2174,7 @@ return setting; } -ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) +ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) { ide_settings_t *setting = drive->settings; @@ -2152,7 +2186,7 @@ return setting; } -static void auto_remove_settings(ide_drive_t *drive) +static void auto_remove_settings (ide_drive_t *drive) { ide_settings_t *setting; repeat: @@ -2166,13 +2200,13 @@ } } -int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) +int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) { int val = -EINVAL; unsigned long flags; if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&io_request_lock, flags); switch(setting->data_type) { case TYPE_BYTE: val = *((u8 *) setting->data); @@ -2185,7 +2219,7 @@ val = *((u32 *) setting->data); break; } - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); } return val; } @@ -2195,20 +2229,29 @@ ide_hwgroup_t *hwgroup = HWGROUP(drive); unsigned long timeout = jiffies + (3 * HZ); - spin_lock_irqsave(&hwgroup->spinlock, *flags); + spin_lock_irqsave(&io_request_lock, *flags); while (hwgroup->busy) { - spin_unlock_irqrestore(&hwgroup->spinlock, *flags); - __sti(); /* local CPU only; needed for jiffies */ + unsigned long lflags; + spin_unlock_irqrestore(&io_request_lock, *flags); + __save_flags(lflags); /* local CPU only */ + __sti(); /* local CPU only; needed for jiffies */ if (0 < (signed long)(jiffies - timeout)) { + __restore_flags(lflags); /* local CPU only */ printk("%s: channel busy\n", drive->name); return -EBUSY; } - spin_lock_irqsave(&hwgroup->spinlock, *flags); + __restore_flags(lflags); /* local CPU only */ + spin_lock_irqsave(&io_request_lock, *flags); } return 0; } -int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) +/* + * FIXME: This should be changed to enqueue a special request + * to the driver to change settings, and then wait on a sema for completion. + * The current scheme of polling is kludgey, though safe enough. + */ +int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { unsigned long flags; int i; @@ -2240,7 +2283,7 @@ *p = val; break; } - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } @@ -2254,7 +2297,7 @@ return 0; } -static int set_using_dma(ide_drive_t *drive, int arg) +static int set_using_dma (ide_drive_t *drive, int arg) { if (!drive->driver || !DRIVER(drive)->supports_dma) return -EPERM; @@ -2265,7 +2308,7 @@ return 0; } -static int set_pio_mode(ide_drive_t *drive, int arg) +static int set_pio_mode (ide_drive_t *drive, int arg) { struct request rq; @@ -2280,7 +2323,7 @@ return 0; } -void ide_add_generic_settings(ide_drive_t *drive) +void ide_add_generic_settings (ide_drive_t *drive) { /* * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function @@ -2325,136 +2368,6 @@ while (0 < (signed long)(timeout - jiffies)); } -int ide_config_drive_speed (ide_drive_t *drive, byte speed) -{ - struct hd_driveid *id = drive->id; - unsigned long flags; - int err; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - SELECT_DRIVE(HWIF(drive), drive); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - - err = ide_wait_stat(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); - -#if 0 - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); -#endif - - __restore_flags(flags); /* local CPU only */ - - switch(speed) { - case XFER_UDMA_4: - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - } - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_UDMA_3: - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - } - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_UDMA_2: - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - } - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_UDMA_1: - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - } - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_UDMA_0: - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - } - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_MW_DMA_2: - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - } - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_MW_DMA_1: - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - } - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_MW_DMA_0: - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - } - drive->id->dma_1word &= ~0x0F00; - break; - case XFER_SW_DMA_2: - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - } - break; - case XFER_SW_DMA_1: - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - } - break; - case XFER_SW_DMA_0: - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - } - break; - default: - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - break; - } - - return(err); -} - static int ide_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2509,8 +2422,7 @@ return -EINVAL; if (drive->id == NULL) return -ENOMSG; - if (copy_to_user((char *)arg, (char *)drive->id, - (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) + if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) return -EFAULT; return 0; @@ -2537,28 +2449,16 @@ return -ENOMEM; memcpy(argbuf, args, 4); } - if ((((byte *)arg)[0] == WIN_SETFEATURES) && - (((byte *)arg)[1] > 66) && - (((byte *)arg)[2] == 3)) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name); - goto abort; - } - if ((drive->id->word93 & 0x2000) == 0) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name); - goto abort; - } - } + if (ide_ata66_check(drive, args[0], args[1], args[2])) + goto abort; + err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - if (!err && - (((byte *)arg)[0] == WIN_SETFEATURES) && - (((byte *)arg)[1] >= 16) && - (((byte *)arg)[2] == 3) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) { - /* + if (!err && set_transfer(drive, args[0], args[1], args[2])) { + +#if 1 + ide_driveid_update(drive); +#else /* * Re-read drive->id for possible DMA mode * change (copied from ide-probe.c) */ @@ -2602,6 +2502,7 @@ #endif kfree(id); } +#endif } abort: if (copy_to_user((void *)arg, argbuf, argsize)) @@ -2694,32 +2595,6 @@ } /* - * - */ -char *ide_xfer_verbose (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } -} - -/* * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. */ @@ -2796,7 +2671,7 @@ * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive * "hdx=cdrom" : drive is present, and is a cdrom drive * "hdx=cyl,head,sect" : disk drive is present, with specified geometry - * "hdx=noremap" : do not remap 0->1 even though EZD was detected + * "hdx=noremap" : do not remap 0->1 even though EZD was detected * "hdx=autotune" : driver will attempt to tune interface speed * to the fastest PIO mode supported, * if possible for this drive only. @@ -3198,6 +3073,14 @@ } /* + * __setup("ide", ide_setup); + * #ifdef CONFIG_BLK_DEV_VIA82CXXX + * __setup("splitfifo", ide_setup); + * #endif + * __setup("hd", ide_setup); + */ + +/* * probe_for_hwifs() finds/initializes "known" IDE interfaces */ static void __init probe_for_hwifs (void) @@ -3332,9 +3215,10 @@ return ide_unregister_subdriver(drive); } -static void default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) { ide_end_request(0, HWGROUP(drive)); + return ide_stopped; } static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup) @@ -3372,12 +3256,13 @@ return 0x7fffffff; /* cdrom or tape */ } -static void default_special (ide_drive_t *drive) +static ide_startstop_t default_special (ide_drive_t *drive) { special_t *s = &drive->special; s->all = 0; drive->mult_req = 0; + return ide_stopped; } static void setup_driver_defaults (ide_drive_t *drive) @@ -3577,7 +3462,6 @@ EXPORT_SYMBOL(ide_cmd); EXPORT_SYMBOL(ide_wait_cmd); EXPORT_SYMBOL(ide_delay_50ms); -EXPORT_SYMBOL(ide_config_drive_speed); EXPORT_SYMBOL(ide_stall_queue); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(ide_add_proc_entries); diff -u --recursive --new-file v2.3.27/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c --- v2.3.27/linux/drivers/block/pdc202xx.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/pdc202xx.c Fri Nov 12 10:12:11 1999 @@ -78,6 +78,7 @@ * Released under terms of General Public License */ +#include #include #include #include @@ -220,7 +221,7 @@ int err; unsigned int drive_conf; - byte drive_pci; + byte drive_pci, speed_ok = 0; byte test1, test2, speed = -1; byte AP, BP, CP, DP, TB, TC; unsigned short EP; @@ -278,16 +279,20 @@ switch(drive_number) { case 0: drive_pci = 0x60; pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) { + speed_ok = 1; goto chipset_is_set; + } pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 1: drive_pci = 0x64; pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) { + speed_ok = 1; goto chipset_is_set; + } pci_read_config_byte(dev, 0x60, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -295,16 +300,20 @@ break; case 2: drive_pci = 0x68; pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) { + speed_ok = 1; goto chipset_is_set; + } pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 3: drive_pci = 0x6c; pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) { + speed_ok = 1; goto chipset_is_set; + } pci_read_config_byte(dev, 0x68, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -402,7 +411,8 @@ decode_registers(REG_D, DP); #endif /* PDC202XX_DECODE_REGISTER_INFO */ - err = ide_config_drive_speed(drive, speed); + if (!speed_ok) + err = ide_config_drive_speed(drive, speed); #if PDC202XX_DEBUG_DRIVE_INFO printk("%s: %s drive%d 0x%08x ", diff -u --recursive --new-file v2.3.27/linux/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c --- v2.3.27/linux/drivers/block/pdc4030.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/block/pdc4030.c Fri Nov 12 10:12:11 1999 @@ -158,6 +158,7 @@ ide_hwif_t *hwif2; struct dc_ident ident; int i; + ide_startstop_t startstop; if (!hwif) return 0; @@ -174,7 +175,7 @@ if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { return 0; } - if (ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { + if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { printk(KERN_INFO "%s: Failed Promise read config!\n",hwif->name); return 0; @@ -301,7 +302,7 @@ /* * promise_read_intr() is the handler for disk read/multread interrupts */ -static void promise_read_intr (ide_drive_t *drive) +static ide_startstop_t promise_read_intr (ide_drive_t *drive) { byte stat; int total_remaining; @@ -309,8 +310,7 @@ struct request *rq; if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - ide_error(drive, "promise_read_intr", stat); - return; + return ide_error(drive, "promise_read_intr", stat); } read_again: @@ -367,12 +367,13 @@ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); #endif - return; + return ide_started; } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " "!DRQ !BUSY\n", drive->name); - ide_error(drive, "promise read intr", stat); + return ide_error(drive, "promise read intr", stat); } + return ide_stopped; } /* @@ -383,7 +384,7 @@ * * Once not busy, the end request is called. */ -static void promise_complete_pollfunc(ide_drive_t *drive) +static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); struct request *rq = hwgroup->rq; @@ -392,13 +393,12 @@ if (GET_STAT() & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); - return; /* continue polling... */ + return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: completion timeout - still busy!\n", drive->name); - ide_error(drive, "busy timeout", GET_STAT()); - return; + return ide_error(drive, "busy timeout", GET_STAT()); } hwgroup->poll_timeout = 0; @@ -409,24 +409,24 @@ i -= rq->current_nr_sectors; ide_end_request(1, hwgroup); } + return ide_stopped; } /* * promise_write_pollfunc() is the handler for disk write completion polling. */ -static void promise_write_pollfunc (ide_drive_t *drive) +static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return; /* continue polling... */ + return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); - ide_error (drive, "write timeout", GET_STAT()); - return; + return ide_error (drive, "write timeout", GET_STAT()); } /* @@ -439,7 +439,7 @@ printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); #endif - return; + return ide_started; } /* @@ -449,7 +449,7 @@ * before the final 4 sectors are transfered. There is no interrupt generated * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. */ -static void promise_write (ide_drive_t *drive) +static ide_startstop_t promise_write (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); struct request *rq = &hwgroup->wrq; @@ -465,21 +465,25 @@ * the polling strategy as defined above. */ if (rq->nr_sectors > 4) { - ide_multwrite(drive, rq->nr_sectors - 4); + if (ide_multwrite(drive, rq->nr_sectors - 4)) + return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); + return ide_started; } else { /* * There are 4 or fewer sectors to transfer, do them all in one go * and wait for NOT BUSY. */ - ide_multwrite(drive, rq->nr_sectors); + if (ide_multwrite(drive, rq->nr_sectors)) + return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); #endif + return ide_started; } } @@ -488,7 +492,7 @@ * already set up. It issues a READ or WRITE command to the Promise * controller, assuming LBA has been used to set up the block number. */ -void do_pdc4030_io (ide_drive_t *drive, struct request *rq) +ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) { unsigned long timeout; byte stat; @@ -510,8 +514,7 @@ stat=GET_STAT(); if (stat & DRQ_STAT) { udelay(1); - promise_read_intr(drive); - return; + return promise_read_intr(drive); } if (IN_BYTE(IDE_SELECT_REG) & 0x01) { #ifdef DEBUG_READ @@ -519,29 +522,31 @@ "interrupt\n", drive->name); #endif ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); - return; + return ide_started; } udelay(1); } while (time_before(jiffies, timeout)); printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", drive->name); - + return ide_stopped; } else if (rq->cmd == WRITE) { + ide_startstop_t startstop; OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); - if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { + if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { printk(KERN_ERR "%s: no DRQ after issuing " "PROMISE_WRITE\n", drive->name); - return; + return startstop; } if (!drive->unmask) __cli(); /* local CPU only */ HWGROUP(drive)->wrq = *rq; /* scratchpad */ - promise_write(drive); + return promise_write(drive); } else { printk("KERN_WARNING %s: bad command: %d\n", drive->name, rq->cmd); ide_end_request(0, HWGROUP(drive)); + return ide_stopped; } } diff -u --recursive --new-file v2.3.27/linux/drivers/block/piix.c linux/drivers/block/piix.c --- v2.3.27/linux/drivers/block/piix.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/piix.c Fri Nov 12 10:12:11 1999 @@ -68,6 +68,42 @@ #define PIIX_DEBUG_DRIVE_INFO 0 +#define DISPLAY_PIIX_TIMINGS + +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int piix_get_info(char *, char **, off_t, int, int); +extern int (*piix_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */ +extern char *ide_media_verbose(ide_drive_t *); +static struct pci_dev *bmide_dev; + +static int piix_get_info (char *buffer, char **addr, off_t offset, int count, int dummy) +{ + /* int rc; */ + int piix_who = (bmide_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 4 : 3; + char *p = buffer; + p += sprintf(p, "\n Intel PIIX%d Chipset.\n", piix_who); + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n\n"); + p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "\n"); + p += sprintf(p, "\n"); + +/* + * FIXME.... Add configuration junk data....blah blah...... + */ + + return p-buffer; /* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/* + * Used to set Fifo configuration via kernel command line: + */ + +byte piix_proc = 0; + extern char *ide_xfer_verbose (byte xfer_rate); #ifdef CONFIG_BLK_DEV_PIIX_TUNING @@ -248,6 +284,18 @@ } #endif /* CONFIG_BLK_DEV_PIIX_TUNING */ +unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) + if (!piix_proc) { + piix_proc = 1; + bmide_dev = dev; + piix_display_info = &piix_get_info; + } +#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + void __init ide_init_piix (ide_hwif_t *hwif) { hwif->tuneproc = &piix_tune_drive; @@ -262,5 +310,4 @@ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; } - } diff -u --recursive --new-file v2.3.27/linux/drivers/block/sis5513.c linux/drivers/block/sis5513.c --- v2.3.27/linux/drivers/block/sis5513.c Fri Oct 22 13:21:47 1999 +++ linux/drivers/block/sis5513.c Fri Nov 12 10:12:11 1999 @@ -8,6 +8,7 @@ * Tested and designed on the SiS620/5513 chipset. */ +#include #include #include #include @@ -27,13 +28,35 @@ #include "ide_modes.h" +#define DISPLAY_SIS_TIMINGS #define SIS5513_DEBUG_DRIVE_INFO 0 -#define DISPLAY_SIS_TIMINGS +static struct pci_dev *host_dev = NULL; + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) -static struct pci_dev *host_dev; +#define SIS5513_FLAG_ATA_00 0x00000000 +#define SIS5513_FLAG_ATA_16 0x00000001 +#define SIS5513_FLAG_ATA_33 0x00000002 +#define SIS5513_FLAG_ATA_66 0x00000004 +#define SIS5513_FLAG_LATENCY 0x00000010 + +static const struct { + const char *name; + unsigned short host_id; + unsigned int flags; +} SiSHostChipInfo[] = { + { "SiS530", PCI_DEVICE_ID_SI_530, SIS5513_FLAG_ATA_66, }, + { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, }, + { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, }, + { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, }, + { "SiS5511", PCI_DEVICE_ID_SI_5511, SIS5513_FLAG_ATA_16, }, +}; #if 0 + static struct _pio_mode_mapping { byte data_active; byte recovery; @@ -122,9 +145,6 @@ int rc; char *p = buffer; byte reg,reg1; -#if 0 - byte cyc, rec, act; -#endif u16 reg2, reg3; p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); @@ -213,16 +233,16 @@ byte drive_pci, test1, test2, mask; int err; - byte speed = 0x00; - byte unmask = 0xE0; - byte four_two = 0x00; + byte speed = 0x00, unmask = 0xE0, four_two = 0x00; int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0; if (host_dev) { switch(host_dev->device) { case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: + case PCI_DEVICE_ID_SI_630: unmask = 0xF0; four_two = 0x01; default: @@ -246,13 +266,15 @@ pci_read_config_byte(dev, drive_pci|0x01, &test2); } - if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { + if ((id->dma_ultra & 0x0010) && (ultra) && + (udma_66) && (four_two)) { if (!(test2 & 0x90)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); } speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { + } else if ((id->dma_ultra & 0x0008) && (ultra) && + (udma_66) && (four_two)) { if (!(test2 & 0xA0)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); @@ -438,29 +460,23 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) { struct pci_dev *host; + int i = 0; byte latency = 0; pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - for (host = pci_devices; host; host=host->next) { - if (host->vendor == PCI_VENDOR_ID_SI && - host->device == PCI_DEVICE_ID_SI_620) { + for (i = 0; i < arraysize (SiSHostChipInfo) && !host_dev; i++) { + host = pci_find_device (PCI_VENDOR_ID_SI, + SiSHostChipInfo[i].host_id, + NULL); + if (!host) + continue; + + host_dev = host; + printk(SiSHostChipInfo[i].name); + if (SiSHostChipInfo[i].flags & SIS5513_FLAG_LATENCY) { if (latency != 0x10) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); - host_dev = host; - break; - } else if (host->vendor == PCI_VENDOR_ID_SI && - host->device == PCI_DEVICE_ID_SI_530) { - host_dev = host; - break; - } else if (host->vendor == PCI_VENDOR_ID_SI && - host->device == PCI_DEVICE_ID_SI_5600) { - host_dev = host; - break; - } else if (host->vendor == PCI_VENDOR_ID_SI && - host->device == PCI_DEVICE_ID_SI_5597) { - host_dev = host; - break; } } @@ -468,9 +484,10 @@ byte reg52h = 0; pci_read_config_byte(dev, 0x52, ®52h); - if (!(reg52h & 0x04)) + if (!(reg52h & 0x04)) { /* set IDE controller to operate in Compabitility mode obly */ pci_write_config_byte(dev, 0x52, reg52h|0x04); + } #if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) sis_proc = 1; bmide_dev = dev; @@ -489,7 +506,9 @@ if (host_dev) { switch(host_dev->device) { case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: + case PCI_DEVICE_ID_SI_630: ata66 = (reg48h & mask) ? 0 : 1; default: break; @@ -509,7 +528,9 @@ if (host_dev) { switch(host_dev->device) { case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: + case PCI_DEVICE_ID_SI_630: case PCI_DEVICE_ID_SI_5600: case PCI_DEVICE_ID_SI_5597: hwif->autodma = 1; diff -u --recursive --new-file v2.3.27/linux/drivers/char/drm/bufs.c linux/drivers/char/drm/bufs.c --- v2.3.27/linux/drivers/char/drm/bufs.c Fri Sep 10 23:57:29 1999 +++ linux/drivers/char/drm/bufs.c Fri Nov 12 04:29:47 1999 @@ -30,6 +30,7 @@ */ #define __NO_VERSION__ +#include #include "drmP.h" #include "linux/un.h" diff -u --recursive --new-file v2.3.27/linux/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h --- v2.3.27/linux/drivers/char/drm/drmP.h Fri Sep 10 23:57:29 1999 +++ linux/drivers/char/drm/drmP.h Fri Nov 12 04:29:47 1999 @@ -33,6 +33,7 @@ #define _DRM_P_H_ #ifdef __KERNEL__ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/char/drm/gamma_drv.c linux/drivers/char/drm/gamma_drv.c --- v2.3.27/linux/drivers/char/drm/gamma_drv.c Fri Sep 10 23:57:29 1999 +++ linux/drivers/char/drm/gamma_drv.c Fri Nov 12 04:29:47 1999 @@ -30,6 +30,7 @@ */ #define EXPORT_SYMTAB +#include #include "drmP.h" #include "gamma_drv.h" EXPORT_SYMBOL(gamma_init); diff -u --recursive --new-file v2.3.27/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c --- v2.3.27/linux/drivers/i2o/i2o_pci.c Thu Nov 11 20:11:35 1999 +++ linux/drivers/i2o/i2o_pci.c Fri Nov 12 04:29:47 1999 @@ -16,6 +16,7 @@ * Support polled I2O PCI controllers. */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/isdn/eicon/eicon_isa.h linux/drivers/isdn/eicon/eicon_isa.h --- v2.3.27/linux/drivers/isdn/eicon/eicon_isa.h Thu Nov 11 20:11:37 1999 +++ linux/drivers/isdn/eicon/eicon_isa.h Fri Nov 12 04:29:47 1999 @@ -48,6 +48,7 @@ #define eicon_isa_h #ifdef __KERNEL__ +#include /* Factory defaults for ISA-Cards */ #define EICON_ISA_MEMBASE 0xd0000 diff -u --recursive --new-file v2.3.27/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c --- v2.3.27/linux/drivers/macintosh/via-cuda.c Sat Oct 9 11:47:50 1999 +++ linux/drivers/macintosh/via-cuda.c Fri Nov 12 04:29:47 1999 @@ -9,6 +9,7 @@ * Copyright (C) 1996 Paul Mackerras. */ #include +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.3.27/linux/drivers/net/8390.c Thu Nov 11 20:11:39 1999 +++ linux/drivers/net/8390.c Fri Nov 12 04:29:47 1999 @@ -47,6 +47,7 @@ static const char *version = "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h --- v2.3.27/linux/drivers/net/acenic_firmware.h Tue Sep 7 12:14:06 1999 +++ linux/drivers/net/acenic_firmware.h Fri Nov 12 04:29:47 1999 @@ -1,3 +1,4 @@ +#include /* * Declare these here even if Tigon I support is disabled to avoid * the compiler complaining about undefined symbols. diff -u --recursive --new-file v2.3.27/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c --- v2.3.27/linux/drivers/net/dmfe.c Thu Nov 11 20:11:40 1999 +++ linux/drivers/net/dmfe.c Fri Nov 12 04:29:47 1999 @@ -46,7 +46,6 @@ */ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.3.27/linux/drivers/net/irda/toshoboe.c Wed Oct 27 16:34:12 1999 +++ linux/drivers/net/irda/toshoboe.c Fri Nov 12 04:29:47 1999 @@ -84,6 +84,7 @@ /* No user servicable parts below here */ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/pcmcia/netwave_cs.c linux/drivers/net/pcmcia/netwave_cs.c --- v2.3.27/linux/drivers/net/pcmcia/netwave_cs.c Thu Nov 11 20:11:41 1999 +++ linux/drivers/net/pcmcia/netwave_cs.c Fri Nov 12 04:29:47 1999 @@ -37,6 +37,7 @@ /* To have statistics (just packets sent) define this */ #undef NETWAVE_STATS +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c --- v2.3.27/linux/drivers/net/pcmcia/ray_cs.c Thu Nov 11 20:11:41 1999 +++ linux/drivers/net/pcmcia/ray_cs.c Fri Nov 12 04:29:47 1999 @@ -22,6 +22,7 @@ * =============================================================================*/ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/pcmcia/tulip_cb.c linux/drivers/net/pcmcia/tulip_cb.c --- v2.3.27/linux/drivers/net/pcmcia/tulip_cb.c Thu Nov 11 20:11:41 1999 +++ linux/drivers/net/pcmcia/tulip_cb.c Fri Nov 12 04:29:47 1999 @@ -102,7 +102,6 @@ #error You must compile this driver with "-O". #endif -#include #include #ifdef MODULE #ifdef MODVERSIONS diff -u --recursive --new-file v2.3.27/linux/drivers/net/pcmcia/wavelan_cs.h linux/drivers/net/pcmcia/wavelan_cs.h --- v2.3.27/linux/drivers/net/pcmcia/wavelan_cs.h Thu Nov 11 20:11:41 1999 +++ linux/drivers/net/pcmcia/wavelan_cs.h Fri Nov 12 04:29:47 1999 @@ -358,6 +358,7 @@ /***************************** INCLUDES *****************************/ /* Linux headers that we need */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/setup.c linux/drivers/net/setup.c --- v2.3.27/linux/drivers/net/setup.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/setup.c Fri Nov 12 10:12:11 1999 @@ -309,7 +309,7 @@ static struct net_device dummy_dev = { "dummy" __PAD5, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, dummy_init, }; - register_netdev(&sb1000_dev); + register_netdev(&dummy_dev); } #endif #ifdef CONFIG_EQUALIZER @@ -325,7 +325,7 @@ NULL, /* next device */ eql_init /* set up the rest */ }; - register_netdev(&sb1000_dev); + register_netdev(&eql_dev); } #endif #ifdef CONFIG_APBIF @@ -335,7 +335,7 @@ { "bif" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, bif_init }; - register_netdev(&sb1000_dev); + register_netdev(&bif_dev); } #endif #ifdef CONFIG_NET_SB1000 diff -u --recursive --new-file v2.3.27/linux/drivers/net/starfire.c linux/drivers/net/starfire.c --- v2.3.27/linux/drivers/net/starfire.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/starfire.c Fri Nov 12 04:29:47 1999 @@ -69,7 +69,6 @@ #endif /* Include files, designed to support most kernel versions 2.0.0 and later. */ -#include #ifdef MODULE #ifdef MODVERSIONS #include diff -u --recursive --new-file v2.3.27/linux/drivers/net/wan/cycx_drv.c linux/drivers/net/wan/cycx_drv.c --- v2.3.27/linux/drivers/net/wan/cycx_drv.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/net/wan/cycx_drv.c Thu Nov 11 20:10:36 1999 @@ -15,6 +15,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ +* 1999/11/11 acme set_current_state(TASK_INTERRUPTIBLE), code cleanup +* 1999/11/08 acme init_cyc2x deleted, doing nothing +* 1999/11/06 acme back to read[bw], write[bw] and memcpy_to and +* fromio to use dpmbase ioremaped * 1999/10/26 acme use isa_read[bw], isa_write[bw] and isa_memcpy_to * and fromio * 1999/10/23 acme cleanup to only supports cyclom2x: all the other @@ -58,10 +62,10 @@ #include /* API definitions */ #include /* CYCX firmware module definitions */ #include /* udelay */ -#include /* for inb(), outb(), etc. */ +#include /* read[wl], write[wl], ioremap, iounmap */ #define MOD_VERSION 0 -#define MOD_RELEASE 3 +#define MOD_RELEASE 4 #ifdef MODULE MODULE_AUTHOR("Arnaldo Carvalho de Melo"); @@ -70,30 +74,29 @@ /* Function Prototypes */ /* Module entry points. These are called by the OS and must be public. */ -int init_module (void); -void cleanup_module (void); +int init_module(void); +void cleanup_module(void); /* Hardware-specific functions */ -static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len); -static void cycx_bootcfg (cycxhw_t *hw); +static int load_cyc2x(cycxhw_t *hw, cfm_t *cfm, u32 len); +static void cycx_bootcfg(cycxhw_t *hw); -static int init_cyc2x (cycxhw_t *hw); -static int reset_cyc2x (u32 addr); -static int detect_cyc2x (u32 addr); +static int reset_cyc2x(u32 addr); +static int detect_cyc2x(u32 addr); /* Miscellaneous functions */ -static void delay_cycx (int sec); -static int get_option_index (u32 *optlist, u32 optval); -static u16 checksum (u8 *buf, u32 len); +static void delay_cycx(int sec); +static int get_option_index(u32 *optlist, u32 optval); +static u16 checksum(u8 *buf, u32 len); #define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET) -#define cyc2x_readb(b) isa_readb(b) -#define cyc2x_readw(b) isa_readw(b) -#define cyc2x_writeb(b, addr) isa_writeb(b, addr) -#define cyc2x_writew(w, addr) isa_writew(w, addr) -#define cyc2x_memcpy_toio(addr, buf, len) isa_memcpy_toio((addr), buf, len) -#define cyc2x_memcpy_fromio(buf, addr, len) isa_memcpy_fromio(buf, (addr), len) +#define cyc2x_readb(b) readb(b) +#define cyc2x_readw(b) readw(b) +#define cyc2x_writeb(b, addr) writeb(b, addr) +#define cyc2x_writew(w, addr) writew(w, addr) +#define cyc2x_memcpy_toio(addr, buf, len) memcpy_toio((addr), buf, len) +#define cyc2x_memcpy_fromio(buf, addr, len) memcpy_fromio(buf, (addr), len) /* Global Data */ @@ -125,7 +128,7 @@ * < 0 error. * Context: process */ #ifdef MODULE -int init_module (void) +int init_module(void) { printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE, copyright); @@ -133,7 +136,7 @@ } /* Module 'remove' entry point. * o release all remaining system resources */ -void cleanup_module (void) +void cleanup_module(void) { } #endif @@ -148,21 +151,14 @@ * Return: 0 ok. * < 0 error */ EXPORT_SYMBOL(cycx_setup); -int cycx_setup (cycxhw_t *hw, void *cfm, u32 len) +int cycx_setup(cycxhw_t *hw, void *cfm, u32 len) { - if (!detect_cyc2x(hw->dpmbase)) { - printk(KERN_ERR "%s: adapter Cyclom 2X not found at " - "address 0x%lX!\n", - modname, (unsigned long) hw->dpmbase); - return -EINVAL; - } - - printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lx.\n", - modname, (unsigned long) hw->dpmbase); + unsigned long dpmbase = hw->dpmbase; + int err; /* Verify IRQ configuration options */ if (!get_option_index(cycx_2x_irq_options, hw->irq)) { - printk (KERN_ERR "%s: IRQ %d is illegal!\n", modname, hw->irq); + printk(KERN_ERR "%s: IRQ %d is illegal!\n", modname, hw->irq); return -EINVAL; } @@ -171,34 +167,50 @@ printk(KERN_ERR "%s: you must specify the dpm address!\n", modname); return -EINVAL; - } - else if (!get_option_index(cyc2x_dpmbase_options, hw->dpmbase)) { + } else if (!get_option_index(cyc2x_dpmbase_options, hw->dpmbase)) { printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n", - modname, (unsigned long) hw->dpmbase); + modname, dpmbase); return -EINVAL; } + hw->dpmbase = (u32)ioremap(dpmbase, CYCX_WINDOWSIZE); hw->dpmsize = CYCX_WINDOWSIZE; - init_cyc2x(hw); + if (!detect_cyc2x(hw->dpmbase)) { + printk(KERN_ERR "%s: adapter Cyclom 2X not found at " + "address 0x%lX!\n", modname, dpmbase); + return -EINVAL; + } - printk(KERN_INFO "%s: dual-port memory window is set at 0x%lX.\n", - modname, (unsigned long) hw->dpmbase); + printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n", + modname, dpmbase); /* Load firmware. If loader fails then shut down adapter */ - return load_cyc2x(hw, cfm, len); + err = load_cyc2x(hw, cfm, len); + + if (err) + cycx_down(hw); /* shutdown adapter */ + + return err; } +EXPORT_SYMBOL(cycx_down); +int cycx_down(cycxhw_t *hw) +{ + iounmap((u32 *)hw->dpmbase); + return 0; +} + /* Enable interrupt generation. */ EXPORT_SYMBOL(cycx_inten); -void cycx_inten (cycxhw_t *hw) +void cycx_inten(cycxhw_t *hw) { - cyc2x_writeb (0, hw->dpmbase); + cyc2x_writeb(0, hw->dpmbase); } /* Generate an interrupt to adapter's CPU. */ EXPORT_SYMBOL(cycx_intr); -void cycx_intr (cycxhw_t *hw) +void cycx_intr(cycxhw_t *hw) { cyc2x_writew(0, hw->dpmbase + GEN_CYCX_INTR); } @@ -207,7 +219,7 @@ * o Set exec flag. * o Busy-wait until flag is reset. */ EXPORT_SYMBOL(cycx_exec); -int cycx_exec (u32 addr) +int cycx_exec(u32 addr) { u16 i = 0; /* wait till addr content is zeroed */ @@ -223,10 +235,12 @@ /* Read absolute adapter memory. * Transfer data from adapter's memory to data buffer. */ EXPORT_SYMBOL(cycx_peek); -int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len) +int cycx_peek(cycxhw_t *hw, u32 addr, void *buf, u32 len) { - if (len == 1) *(u8*)buf = cyc2x_readb (hw->dpmbase + addr); - else cyc2x_memcpy_fromio(buf, hw->dpmbase + addr, len); + if (len == 1) + *(u8*)buf = cyc2x_readb(hw->dpmbase + addr); + else + cyc2x_memcpy_fromio(buf, hw->dpmbase + addr, len); return 0; } @@ -234,10 +248,12 @@ /* Write Absolute Adapter Memory. * Transfer data from data buffer to adapter's memory. */ EXPORT_SYMBOL(cycx_poke); -int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len) +int cycx_poke(cycxhw_t *hw, u32 addr, void *buf, u32 len) { - if (len == 1) cyc2x_writeb (*(u8*)buf, hw->dpmbase + addr); - else cyc2x_memcpy_toio(hw->dpmbase + addr, buf, len); + if (len == 1) + cyc2x_writeb(*(u8*)buf, hw->dpmbase + addr); + else + cyc2x_memcpy_toio(hw->dpmbase + addr, buf, len); return 0; } @@ -249,13 +265,13 @@ return 1 if memory exists at addr and 0 if not. */ static int memory_exists(u32 addr) { - int timeout = 0; + int tries = 0; - for (; timeout < 3 ; timeout++) { - cyc2x_writew (TEST_PATTERN, addr + 0x10); + for (; tries < 3 ; tries++) { + cyc2x_writew(TEST_PATTERN, addr + 0x10); - if (cyc2x_readw (addr + 0x10) == TEST_PATTERN) - if (cyc2x_readw (addr + 0x10) == TEST_PATTERN) return 1; + if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) + if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) return 1; delay_cycx(1); } @@ -267,10 +283,10 @@ static void reset_load(u32 addr, u8 *buffer, u32 cnt) { u32 pt_code = addr + RESET_OFFSET; - u16 i, j; + u16 i; /*, j; */ - for ( i = 0 ; i < cnt ; i++) { - for (j = 0 ; j < 50 ; j++); /* Delay - FIXME busy waiting... */ + for (i = 0 ; i < cnt ; i++) { +/* for (j = 0 ; j < 50 ; j++); Delay - FIXME busy waiting... */ cyc2x_writeb(*buffer++, pt_code++); } } @@ -286,7 +302,7 @@ } /* Set up entry point and kick start Cyclom-X CPU. */ -static void cycx_start (u32 addr) +static void cycx_start(u32 addr) { /* put in 0x30 offset the jump instruction to the code entry point */ cyc2x_writeb(0xea, addr + 0x30); @@ -326,19 +342,21 @@ cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); cyc2x_writew(GEN_DEFPAR, pt_boot_cmd); - if (wait_cyc(addr) < 0) return 2; + if (wait_cyc(addr) < 0) + return -1; cyc2x_writew(0, pt_boot_cmd + sizeof(u16)); cyc2x_writew(0x4000, pt_boot_cmd + 2 * sizeof(u16)); cyc2x_writew(GEN_SET_SEG, pt_boot_cmd); - if (wait_cyc(addr) < 0) return 2; + if (wait_cyc(addr) < 0) + return -1; for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) if (buffer_load(addr, code + i, MIN(CFM_LOAD_BUFSZ, (len - i))) < 0) { printk(KERN_ERR "%s: Error !!\n", modname); - return 4; + return -1; } return 0; @@ -355,18 +373,20 @@ cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); cyc2x_writew(GEN_DEFPAR, pt_boot_cmd); - if (wait_cyc(addr) == -1) return 2; + if (wait_cyc(addr) < 0) + return -1; cyc2x_writew(0x0000, pt_boot_cmd + sizeof(u16)); cyc2x_writew(0xc400, pt_boot_cmd + 2 * sizeof(u16)); cyc2x_writew(GEN_SET_SEG, pt_boot_cmd); - if (wait_cyc(addr) == -1) return 1; + if (wait_cyc(addr) < 0) + return -1; for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) if (buffer_load(addr, code + i,MIN(CFM_LOAD_BUFSZ,(len - i)))) { printk(KERN_ERR "%s: Error !!\n", modname); - return 4; + return -1; } return 0; @@ -375,7 +395,7 @@ /* Load adapter from the memory image of the CYCX firmware module. * o verify firmware integrity and compatibility * o start adapter up */ -static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len) +static int load_cyc2x(cycxhw_t *hw, cfm_t *cfm, u32 len) { int i, j; cycx_header_t *img_hdr; @@ -386,8 +406,8 @@ u16 cksum; /* Announce */ - printk(KERN_INFO "%s: firmware signature=\"%s\"\n", - modname, cfm->signature); + printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname, + cfm->signature); /* Verify firmware signature */ if (strcmp(cfm->signature, CFM_SIGNATURE)) { @@ -456,23 +476,24 @@ delay_cycx(1); for (j = 0 ; j < 3 ; j++) - if (!cyc2x_readw(pt_cycld)) goto reset_loaded; - else delay_cycx(1); + if (!cyc2x_readw(pt_cycld)) + goto reset_loaded; + else + delay_cycx(1); } printk(KERN_ERR "%s: reset not started.\n", modname); return -EINVAL; + reset_loaded: /* Load data.bin */ - if(cycx_data_boot(hw->dpmbase, data_image, - img_hdr->data_size)) { + if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) { printk(KERN_ERR "%s: cannot load data file.\n", modname); return -EINVAL; } /* Load code.bin */ - if(cycx_code_boot(hw->dpmbase, code_image, - img_hdr->code_size)) { + if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) { printk(KERN_ERR "%s: cannot load code file.\n", modname); return -EINVAL; } @@ -500,32 +521,20 @@ - As of now, only static buffers are available to the user. So, the bit VD_RXDIRC must be set in 'valid'. That means that user wants to use the static transmission and reception buffers. */ -static void cycx_bootcfg (cycxhw_t *hw) +static void cycx_bootcfg(cycxhw_t *hw) { /* use fixed buffers */ cyc2x_writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); } -/* Initialize CYCX_2X adapter. */ -static int init_cyc2x (cycxhw_t *hw) -{ - if (!detect_cyc2x(hw->dpmbase)) - return -ENODEV; - - return 0; -} - /* Detect Cyclom 2x adapter. * Following tests are used to detect Cyclom 2x adapter: * to be completed based on the tests done below * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */ -static int detect_cyc2x (u32 addr) +static int detect_cyc2x(u32 addr) { - printk(KERN_INFO "%s: looking for a cyclom 2x at 0x%lX...\n", - modname, (unsigned long) addr); - reset_cyc2x(addr); return memory_exists(addr); } @@ -533,35 +542,36 @@ /* Miscellaneous */ /* Get option's index into the options list. * Return option's index (1 .. N) or zero if option is invalid. */ -static int get_option_index (u32 *optlist, u32 optval) +static int get_option_index(u32 *optlist, u32 optval) { int i = 1; - for (; i <= optlist[0]; ++i) if (optlist[i] == optval) return i; + + for (; i <= optlist[0]; ++i) + if (optlist[i] == optval) + return i; + return 0; } /* Reset adapter's CPU. */ -static int reset_cyc2x (u32 addr) +static int reset_cyc2x(u32 addr) { - cyc2x_writeb (0, addr + RST_ENABLE); delay_cycx (2); - cyc2x_writeb (0, addr + RST_DISABLE); delay_cycx (2); + cyc2x_writeb(0, addr + RST_ENABLE); + delay_cycx(2); + cyc2x_writeb(0, addr + RST_DISABLE); + delay_cycx(2); return memory_exists(addr); } /* Delay */ -static void delay_cycx (int sec) +static void delay_cycx(int sec) { -/* acme - Thu dez 31 21:45:16 EDT 1998 - FIXME I'll keep this comment here just in case, as of now I don't - know it all the contexts where this routine is used are interruptible... */ - - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sec*HZ); } /* Calculate 16-bit CRC using CCITT polynomial. */ -static u16 checksum (u8 *buf, u32 len) +static u16 checksum(u8 *buf, u32 len) { u16 crc = 0; u16 mask, flag; @@ -571,7 +581,9 @@ flag = (crc & 0x8000); crc <<= 1; crc |= ((*buf & mask) ? 1 : 0); - if (flag) crc ^= 0x1021; + + if (flag) + crc ^= 0x1021; } return crc; diff -u --recursive --new-file v2.3.27/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c --- v2.3.27/linux/drivers/net/wan/cycx_main.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/net/wan/cycx_main.c Thu Nov 11 20:10:36 1999 @@ -13,6 +13,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ +* 1999/11/06 acme cycx_down back to life (it needs to be +* called to iounmap the dpmbase) * 1999/08/09 acme removed references to enable_tx_int * use spinlocks instead of cli/sti in * cyclomx_set_state @@ -248,6 +250,7 @@ } if (err) { + cycx_down(&card->hw); free_irq(irq, card); return err; } @@ -274,7 +277,8 @@ card = wandev->private; wandev->state = WAN_UNCONFIGURED; - printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,wandev->irq); + cycx_down(&card->hw); + printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name, wandev->irq); free_irq(wandev->irq, card); return 0; } diff -u --recursive --new-file v2.3.27/linux/drivers/nubus/proc.c linux/drivers/nubus/proc.c --- v2.3.27/linux/drivers/nubus/proc.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/nubus/proc.c Fri Nov 12 04:29:47 1999 @@ -17,7 +17,6 @@ icons) these files will provide "cooked" data. Otherwise they will simply provide raw access (read-only of course) to the ROM. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/pci/helper.c linux/drivers/pci/helper.c --- v2.3.27/linux/drivers/pci/helper.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/pci/helper.c Fri Nov 12 04:29:47 1999 @@ -8,7 +8,6 @@ * */ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.3.27/linux/drivers/pci/pci.ids Thu Nov 11 20:11:42 1999 +++ linux/drivers/pci/pci.ids Fri Nov 12 10:12:11 1999 @@ -543,14 +543,16 @@ 0406 85C501/2 0496 85C496 0530 530 Host + 0540 540 Host 0597 5513C 0601 85C601 0620 620 Host + 0630 630 Host 0900 SiS900 10/100 Ethernet 3602 83C602 5107 5107 5511 5511/5512 - 5513 5513 + 5513 5513 [IDE] 5517 5517 5571 5571 5591 5591/5592 Host diff -u --recursive --new-file v2.3.27/linux/drivers/pci/syscall.c linux/drivers/pci/syscall.c --- v2.3.27/linux/drivers/pci/syscall.c Tue Sep 7 12:14:06 1999 +++ linux/drivers/pci/syscall.c Fri Nov 12 04:29:47 1999 @@ -7,7 +7,6 @@ * magic northbridge registers.. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c --- v2.3.27/linux/drivers/pcmcia/cistpl.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/pcmcia/cistpl.c Fri Nov 12 04:29:47 1999 @@ -33,6 +33,7 @@ #define __NO_VERSION__ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h --- v2.3.27/linux/drivers/pcmcia/cs_internal.h Thu Nov 11 20:11:42 1999 +++ linux/drivers/pcmcia/cs_internal.h Fri Nov 12 11:29:06 1999 @@ -19,6 +19,8 @@ #ifndef _LINUX_CS_INTERNAL_H #define _LINUX_CS_INTERNAL_H +#include + typedef struct erase_busy_t { eraseq_entry_t *erase; client_handle_t client; diff -u --recursive --new-file v2.3.27/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c --- v2.3.27/linux/drivers/pcmcia/ds.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/pcmcia/ds.c Fri Nov 12 04:29:47 1999 @@ -31,6 +31,7 @@ ======================================================================*/ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c --- v2.3.27/linux/drivers/pcmcia/rsrc_mgr.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/pcmcia/rsrc_mgr.c Fri Nov 12 04:29:47 1999 @@ -33,6 +33,7 @@ #define __NO_VERSION__ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c --- v2.3.27/linux/drivers/sbus/char/uctrl.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/sbus/char/uctrl.c Fri Nov 12 04:29:47 1999 @@ -4,7 +4,6 @@ * Copyright 1999 Derrick J Brashear (shadow@dementia.org) */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/i60uscsi.h linux/drivers/scsi/i60uscsi.h --- v2.3.27/linux/drivers/scsi/i60uscsi.h Tue Sep 7 12:14:06 1999 +++ linux/drivers/scsi/i60uscsi.h Fri Nov 12 04:29:47 1999 @@ -60,6 +60,8 @@ * 12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up. **************************************************************************/ +#include + #define ULONG unsigned long #define PVOID void * #define USHORT unsigned short diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- v2.3.27/linux/drivers/scsi/ide-scsi.c Thu Nov 11 20:11:47 1999 +++ linux/drivers/scsi/ide-scsi.c Fri Nov 12 10:12:11 1999 @@ -307,7 +307,7 @@ /* * Our interrupt handler. */ -static void idescsi_pc_intr (ide_drive_t *drive) +static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; byte status, ireason; @@ -337,15 +337,14 @@ if (status & ERR_STAT) rq->errors++; idescsi_end_request (1, HWGROUP(drive)); - return; + return ide_stopped; } bcount = IN_BYTE (IDE_BCOUNTH_REG) << 8 | IN_BYTE (IDE_BCOUNTL_REG); ireason = IN_BYTE (IDE_IREASON_REG); if (ireason & IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } if (ireason & IDESCSI_IREASON_IO) { temp = pc->actually_transferred + bcount; @@ -365,7 +364,7 @@ pc->current_position += temp; idescsi_discard_data (drive,bcount - temp); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); - return; + return ide_started; } #if IDESCSI_DEBUG_LOG printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); @@ -389,32 +388,34 @@ pc->current_position+=bcount; ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ + return ide_started; } -static void idescsi_transfer_pc (ide_drive_t *drive) +static ide_startstop_t idescsi_transfer_pc (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; idescsi_pc_t *pc = scsi->pc; byte ireason; + ide_startstop_t startstop; - if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n"); - return; + return startstop; } ireason = IN_BYTE (IDE_IREASON_REG); if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); - ide_do_reset (drive); - return; + return ide_do_reset (drive); } ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ + return ide_started; } /* * Issue a packet command */ -static void idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) +static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) { idescsi_scsi_t *scsi = drive->driver_data; int bcount; @@ -443,16 +444,17 @@ if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - idescsi_transfer_pc (drive); + return idescsi_transfer_pc (drive); } } /* * idescsi_do_request is our request handling function. */ -static void idescsi_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { #if IDESCSI_DEBUG_LOG printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); @@ -460,11 +462,11 @@ #endif /* IDESCSI_DEBUG_LOG */ if (rq->cmd == IDESCSI_PC_RQ) { - idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer); - return; + return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer); } printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd); idescsi_end_request (0,HWGROUP (drive)); + return ide_stopped; } static int idescsi_open (struct inode *inode, struct file *filp, ide_drive_t *drive) diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h --- v2.3.27/linux/drivers/scsi/ini9100u.h Thu Nov 11 20:11:47 1999 +++ linux/drivers/scsi/ini9100u.h Fri Nov 12 11:30:07 1999 @@ -82,10 +82,7 @@ extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); extern int i91u_reset(Scsi_Cmnd *, unsigned int); - extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ -extern struct proc_dir_entry proc_scsi_ini9100u; -#endif #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g" diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c --- v2.3.27/linux/drivers/scsi/inia100.c Thu Nov 11 20:11:47 1999 +++ linux/drivers/scsi/inia100.c Fri Nov 12 04:29:47 1999 @@ -80,7 +80,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/qlogicfc.h linux/drivers/scsi/qlogicfc.h --- v2.3.27/linux/drivers/scsi/qlogicfc.h Thu Aug 26 13:05:39 1999 +++ linux/drivers/scsi/qlogicfc.h Fri Nov 12 04:40:46 1999 @@ -86,8 +86,6 @@ #define NULL (0) #endif -extern struct proc_dir_entry proc_scsi_isp2x00; - #define QLOGICFC { \ detect: isp2x00_detect, \ release: isp2x00_release, \ diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/qlogicisp.h linux/drivers/scsi/qlogicisp.h --- v2.3.27/linux/drivers/scsi/qlogicisp.h Sun Dec 21 17:04:49 1997 +++ linux/drivers/scsi/qlogicisp.h Fri Nov 12 04:40:46 1999 @@ -70,8 +70,6 @@ #define NULL (0) #endif -extern struct proc_dir_entry proc_scsi_isp1020; - #define QLOGICISP { \ detect: isp1020_detect, \ release: isp1020_release, \ diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/qlogicpti.h linux/drivers/scsi/qlogicpti.h --- v2.3.27/linux/drivers/scsi/qlogicpti.h Mon Mar 15 16:11:31 1999 +++ linux/drivers/scsi/qlogicpti.h Fri Nov 12 04:40:46 1999 @@ -163,8 +163,6 @@ int qlogicpti_abort(Scsi_Cmnd *); int qlogicpti_reset(Scsi_Cmnd *, unsigned int); -extern struct proc_dir_entry proc_scsi_qlogicpti; - /* mailbox command complete status codes */ #define MBOX_COMMAND_COMPLETE 0x4000 #define INVALID_COMMAND 0x4001 diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/sim710.c linux/drivers/scsi/sim710.c --- v2.3.27/linux/drivers/scsi/sim710.c Thu Nov 11 20:11:48 1999 +++ linux/drivers/scsi/sim710.c Fri Nov 12 04:29:47 1999 @@ -60,6 +60,7 @@ #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/scsi/wd33c93.h linux/drivers/scsi/wd33c93.h --- v2.3.27/linux/drivers/scsi/wd33c93.h Mon Oct 4 15:49:30 1999 +++ linux/drivers/scsi/wd33c93.h Fri Nov 12 04:29:47 1999 @@ -23,6 +23,7 @@ #ifndef WD33C93_H #define WD33C93_H +#include #define PROC_INTERFACE /* add code for /proc/scsi/wd33c93/xxx interface */ #ifdef PROC_INTERFACE diff -u --recursive --new-file v2.3.27/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c --- v2.3.27/linux/drivers/sound/adlib_card.c Mon Oct 4 15:49:30 1999 +++ linux/drivers/sound/adlib_card.c Fri Nov 12 04:29:47 1999 @@ -10,8 +10,6 @@ * for more info. */ - -#include #include #include "sound_config.h" #include "soundmodule.h" diff -u --recursive --new-file v2.3.27/linux/drivers/sound/lowlevel/miroaci.h linux/drivers/sound/lowlevel/miroaci.h --- v2.3.27/linux/drivers/sound/lowlevel/miroaci.h Mon Oct 4 15:49:30 1999 +++ linux/drivers/sound/lowlevel/miroaci.h Fri Nov 12 04:29:47 1999 @@ -1,3 +1,4 @@ +#include #if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE) extern int aci_implied_cmd(unsigned char opcode); extern int aci_write_cmd(unsigned char opcode, unsigned char parameter); diff -u --recursive --new-file v2.3.27/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.3.27/linux/drivers/sound/maestro.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/sound/maestro.c Fri Nov 12 04:29:47 1999 @@ -177,6 +177,7 @@ /*****************************************************************************/ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c --- v2.3.27/linux/drivers/sound/opl3.c Mon Oct 4 15:49:30 1999 +++ linux/drivers/sound/opl3.c Fri Nov 12 04:29:47 1999 @@ -20,7 +20,6 @@ * OPL3 devices. */ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c --- v2.3.27/linux/drivers/usb/ezusb.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/usb/ezusb.c Fri Nov 12 04:29:47 1999 @@ -34,7 +34,6 @@ /*****************************************************************************/ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.27/linux/drivers/usb/printer.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/usb/printer.c Fri Nov 12 04:26:37 1999 @@ -165,7 +165,7 @@ unsigned long partial; int result = USB_ST_NOERROR; int maxretry; - + do { char *obuf = p->obuf; unsigned long thistime; @@ -180,7 +180,7 @@ if (signal_pending(current)) { return bytes_written ? bytes_written : -EINTR; } - result = p->pusb_dev->bus->op->bulk_msg(p->pusb_dev, + result = usb_bulk_msg(p->pusb_dev, usb_sndbulkpipe(p->pusb_dev, p->bulk_out_ep), obuf, thistime, &partial, HZ*20); if (partial) { @@ -233,7 +233,7 @@ return -ENODEV; this_read = (count > sizeof(buf)) ? sizeof(buf) : count; - result = p->pusb_dev->bus->op->bulk_msg(p->pusb_dev, + result = usb_bulk_msg(p->pusb_dev, usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep), buf, this_read, &partial, HZ*20); diff -u --recursive --new-file v2.3.27/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.27/linux/drivers/usb/usb.c Thu Nov 11 20:11:49 1999 +++ linux/drivers/usb/usb.c Fri Nov 12 13:22:56 1999 @@ -1304,6 +1304,11 @@ return ret; } +int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, unsigned long *rval, int timeout) +{ + return dev->bus->op->bulk_msg(dev, pipe, data, len, rval, timeout); +} + void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id) { return dev->bus->op->request_bulk(dev, pipe, handler, data, len, dev_id); @@ -1517,7 +1522,7 @@ EXPORT_SYMBOL(usb_control_msg); EXPORT_SYMBOL(usb_request_irq); EXPORT_SYMBOL(usb_release_irq); -/* EXPORT_SYMBOL(usb_bulk_msg); */ +EXPORT_SYMBOL(usb_bulk_msg); EXPORT_SYMBOL(usb_request_bulk); EXPORT_SYMBOL(usb_terminate_bulk); diff -u --recursive --new-file v2.3.27/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.27/linux/drivers/usb/usb.h Sun Nov 7 16:37:34 1999 +++ linux/drivers/usb/usb.h Fri Nov 12 13:22:56 1999 @@ -579,6 +579,7 @@ extern int usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *, void **); extern int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe); +extern int usb_bulk_msg(struct usb_device *, unsigned int, void *, int, unsigned long *, int); extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *); extern int usb_terminate_bulk(struct usb_device *, void *); @@ -694,6 +695,8 @@ #define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) #define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint)) #define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) #define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev)) #define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN) diff -u --recursive --new-file v2.3.27/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c --- v2.3.27/linux/drivers/usb/usb_scsi.c Thu Nov 11 20:11:49 1999 +++ linux/drivers/usb/usb_scsi.c Fri Nov 12 13:22:56 1999 @@ -1,14 +1,14 @@ -/* Driver for USB scsi like devices - * +/* Driver for USB SCSI-like devices + * * (C) Michael Gee (michael@linuxspecific.com) 1999 * * This driver is schizoid - it makes a USB device appear as both a SCSI device * and a character device. The latter is only available if the device has an * interrupt endpoint, and is used specifically to receive interrupt events. * - * In order to support various 'strange' devices, this module supports plug in - * device specific filter modules, which can do their own thing when required. + * In order to support various 'strange' devices, this module supports plug-in + * device-specific filter modules, which can do their own thing when required. * * Further reference. * This driver is based on the 'USB Mass Storage Class' document. This @@ -55,6 +55,12 @@ }; +#ifdef REWRITE_PROJECT +#define IRQ_PERIOD 255 +#else +#define IRQ_PERIOD 0 /* single IRQ transfer then remove it */ +#endif + /* * Per device data */ @@ -68,7 +74,7 @@ struct usb_device *pusb_dev; struct usb_scsi_filter *filter; /* filter driver */ void *fdata; /* filter data */ - unsigned int flags; /* from filter initially*/ + unsigned int flags; /* from filter initially */ __u8 ifnum; /* interface number */ __u8 ep_in; /* in endpoint */ __u8 ep_out; /* out ....... */ @@ -91,9 +97,11 @@ __u16 ip_data; /* interrupt data */ int ip_wanted; /* needed */ int pid; /* control thread */ - struct semaphore *notify; /* wait for thread to begin */ + struct semaphore *notify; /* wait for thread to begin */ void *irq_handle; /* for USB interrupt requests */ unsigned int irqpipe; /* remember pipe for release_irq */ + int mode_xlate; /* if current SCSI command is MODE_6 */ + /* but is translated to MODE_10 for UFI */ }; /* @@ -142,8 +150,8 @@ length -= this_xfer; do { /* US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer); */ - result = us->pusb_dev->bus->op->bulk_msg(us->pusb_dev, pipe, buf, - this_xfer, &partial, HZ*5); + result = usb_bulk_msg(us->pusb_dev, pipe, buf, + this_xfer, &partial, HZ*5); if (result != 0 || partial != this_xfer) US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n", @@ -152,7 +160,7 @@ if (result == USB_ST_STALL) { US_DEBUGP("clearing endpoint halt for pipe %x\n", pipe); usb_clear_halt(us->pusb_dev, - usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN)); + usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN)); } /* we want to retry if the device reported NAK */ @@ -313,6 +321,7 @@ case MODE_SENSE: case MODE_SELECT: + us->mode_xlate = (srb->cmnd[0] == MODE_SENSE); cmd[0] = srb->cmnd[0] | 0x40; cmd[1] = srb->cmnd[1]; cmd[2] = srb->cmnd[2]; @@ -320,6 +329,7 @@ break; default: + us->mode_xlate = 0; memcpy(cmd, srb->cmnd, srb->cmd_len); break; } @@ -385,7 +395,7 @@ return DID_ABORT << 16; } US_DEBUGP("Got AP status %x %x\n", status[0], status[1]); - if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && + if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && ( (status[0] & ~3) || status[1])) return (DID_OK << 16) | 2; else @@ -397,9 +407,9 @@ /* add interrupt transfer, marked for removal */ us->ip_wanted = 1; - us->irqpipe = usb_rcvctrlpipe(us->pusb_dev, us->ep_int); + us->irqpipe = usb_rcvintpipe(us->pusb_dev, us->ep_int); result = usb_request_irq(us->pusb_dev, us->irqpipe, pop_CBI_irq, - 0, (void *)us, &us->irq_handle); + IRQ_PERIOD, (void *)us, &us->irq_handle); if (result) { US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n", result); @@ -407,6 +417,11 @@ } sleep_on(&us->ip_waitq); +#ifdef REWRITE_PROJECT + usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); + us->irq_handle = NULL; +#endif + if (us->ip_wanted) { US_DEBUGP("Did not get interrupt on CBI\n"); us->ip_wanted = 0; @@ -527,9 +542,9 @@ US_DEBUGP("Bulk command S %x T %x L %d F %d CL %d\n", bcb.Signature, bcb.Tag, bcb.DataTransferLength, bcb.Flags, bcb.Length); - result = us->pusb_dev->bus->op->bulk_msg(us->pusb_dev, - usb_sndbulkpipe(us->pusb_dev, us->ep_out), &bcb, - US_BULK_CB_WRAP_LEN, &partial, HZ*5); + result = usb_bulk_msg(us->pusb_dev, + usb_sndbulkpipe(us->pusb_dev, us->ep_out), &bcb, + US_BULK_CB_WRAP_LEN, &partial, HZ*5); if (result) { US_DEBUGP("Bulk command result %x\n", result); return DID_ABORT << 16; @@ -550,9 +565,9 @@ stall = 0; do { - result = us->pusb_dev->bus->op->bulk_msg(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*5); + result = usb_bulk_msg(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs, + US_BULK_CS_WRAP_LEN, &partial, HZ*5); if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) stall++; else @@ -635,7 +650,6 @@ if (us->irq_handle) { usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); us->irq_handle = NULL; - us->irqpipe = 0; } if (us->filter) us->filter->release(us->fdata); @@ -831,7 +845,7 @@ //exit_fs(current); sprintf(current->comm, "usbscsi%d", us->host_number); - + unlock_kernel(); up(us->notify); @@ -868,7 +882,7 @@ /* check for variable length - do properly if so */ if (us->filter && us->filter->command) - us->srb->result = us->filter->command(us->fdata, us->srb); + us->srb->result = us->filter->command(us->fdata, us->srb); else if (us->srb->cmnd[0] == START_STOP && us->pusb_dev->descriptor.idProduct == 0x0001 && us->pusb_dev->descriptor.idVendor == 0x04e6) @@ -884,7 +898,7 @@ else break; saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 18; + us->srb->cmnd[4] = 18; break; case INQUIRY: @@ -893,7 +907,7 @@ else break; saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 36; + us->srb->cmnd[4] = 36; break; case MODE_SENSE: @@ -902,7 +916,7 @@ else break; saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 4; + us->srb->cmnd[4] = 4; break; case LOG_SENSE: @@ -912,14 +926,14 @@ else break; saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8]; - us->srb->cmnd[7] = 0; - us->srb->cmnd[8] = 8; + us->srb->cmnd[7] = 0; + us->srb->cmnd[8] = 8; break; default: break; } /* end switch on cmnd[0] */ - us->srb->result = us->pop(us->srb); + us->srb->result = us->pop(us->srb); if (savelen != us->srb->request_bufflen && us->srb->result == (DID_OK << 16)) { @@ -961,7 +975,7 @@ savelen, length); if (us->srb->request_bufflen != length) { - US_DEBUGP("redoing cmd with len=%d\n", length); + US_DEBUGP("redoing cmd with len=%d\n", length); us->srb->request_bufflen = length; us->srb->result = us->pop(us->srb); } @@ -982,6 +996,17 @@ printk("\n"); } us->srb->cmnd[4] = saveallocation; + if (us->mode_xlate) { + /* convert MODE_SENSE_10 return data + * format to MODE_SENSE_6 format */ + unsigned char *dta = (unsigned char *)us->srb->request_buffer; + dta[0] = dta[1]; /* data len */ + dta[1] = dta[2]; /* med type */ + dta[2] = dta[3]; /* dev-spec prm */ + dta[3] = dta[7]; /* block desc len */ + printk (KERN_DEBUG USB_SCSI "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", + dta[0], dta[1], dta[2], dta[3]); + } break; case LOG_SENSE: @@ -1006,7 +1031,7 @@ } } } else if (us->srb->cmnd[0] != INQUIRY && - us->srb->result == (DID_OK << 16)) { + us->srb->result == (DID_OK << 16)) { us->srb->result |= 2; /* force check condition */ } } @@ -1108,13 +1133,13 @@ /* now check if we have seen it before */ - if (dev->descriptor.iSerialNumber && + if (dev->descriptor.iSerialNumber && usb_string(dev, dev->descriptor.iSerialNumber) ) { make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, - usb_string(dev, dev->descriptor.iSerialNumber)); + usb_string(dev, dev->descriptor.iSerialNumber)); } else { make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, - "0"); + "0"); } for (ss = us_list; ss; ss = ss->next) { if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) { @@ -1172,13 +1197,13 @@ break; } - /* - * we are expecting a minimum of 2 endpoints - in and out (bulk) - * an optional interrupt is OK (necessary for CBI protocol) - * we will ignore any others + /* + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt is OK (necessary for CBI protocol). + * We will ignore any others. */ - for (i = 0; i < interface->bNumEndpoints; i++) { + for (i = 0; i < interface->bNumEndpoints; i++) { if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN) @@ -1276,7 +1301,6 @@ memcpy(htmplt, &my_host_template, sizeof(my_host_template)); ss->host_number = my_host_number++; - (struct us_data *)htmplt->proc_dir = ss; if (dev->descriptor.idVendor == 0x04e6 && @@ -1291,12 +1315,19 @@ qstat, 2, HZ*5); US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]); init_waitqueue_head(&ss->ip_waitq); - ss->irqpipe = usb_rcvctrlpipe(ss->pusb_dev, ss->ep_int); + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq, - 0, (void *)ss, &ss->irq_handle); + IRQ_PERIOD, (void *)ss, &ss->irq_handle); if (result) return NULL; + interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6); +#ifdef REWRITE_PROJECT + /* FIXME: Don't know if this release_irq() call is at the + right place/time. */ + usb_release_irq(ss->pusb_dev, ss->irq_handle, ss->irqpipe); + ss->irq_handle = NULL; +#endif } else if (ss->protocol == US_PR_CBI) init_waitqueue_head(&ss->ip_waitq); @@ -1307,7 +1338,7 @@ DECLARE_MUTEX_LOCKED(sem); init_waitqueue_head(&ss->waitq); - + ss->notify = &sem; ss->pid = kernel_thread(usbscsi_control_thread, ss, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); @@ -1337,6 +1368,7 @@ prev->next = ss; } + printk(KERN_WARNING "DANGEROUS: USB SCSI driver data integrity not assured !!!\n"); printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum); return ss; diff -u --recursive --new-file v2.3.27/linux/drivers/usb/usb_scsi.h linux/drivers/usb/usb_scsi.h --- v2.3.27/linux/drivers/usb/usb_scsi.h Wed Jun 30 11:24:55 1999 +++ linux/drivers/usb/usb_scsi.h Fri Nov 12 13:22:56 1999 @@ -1,13 +1,13 @@ -/* Driver for USB scsi - include file - * +/* Driver for USB SCSI - include file + * * (C) Michael Gee (michael@linuxspecific.com) 1999 * - * This driver is scitzoid - it make a USB scanner appear as both a SCSI device + * This driver is schizoid - it makes a USB scanner appear as both a SCSI device * and a character device. The latter is only available if the device has an * interrupt endpoint, and is used specifically to receive interrupt events. * - * In order to support various 'strange' scanners, this module supports plug in - * device specific filter modules, which can do their own thing when required. + * In order to support various 'strange' scanners, this module supports plug-in + * device-specific filter modules, which can do their own thing when required. * */ @@ -58,7 +58,7 @@ __u32 Signature; /* contains 'USBC' */ __u32 Tag; /* unique per command id */ __u32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ + __u8 Flags; /* direction in bit 0 */ __u8 Lun; /* LUN normally 0 */ __u8 Length; /* of of the CDB */ __u8 CDB[16]; /* max command */ @@ -101,10 +101,10 @@ struct usb_scsi_filter * next; /* usb_scsi driver only */ char *name; /* not really required */ - unsigned int flags; /* Filter flags */ - void * (* probe) (struct usb_device *, char *, char *, char *); /* probe device */ - void (* release)(void *); /* device gone */ - int (* command)(void *, Scsi_Cmnd *); /* all commands */ + unsigned int flags; /* Filter flags */ + void * (* probe) (struct usb_device *, char *, char *, char *); /* probe device */ + void (* release)(void *); /* device gone */ + int (* command)(void *, Scsi_Cmnd *); /* all commands */ }; #define GUID(x) __u32 x[3] diff -u --recursive --new-file v2.3.27/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.3.27/linux/drivers/video/aty128fb.c Fri Oct 22 13:21:51 1999 +++ linux/drivers/video/aty128fb.c Fri Nov 12 04:29:47 1999 @@ -24,7 +24,7 @@ * example code and hardware. Thanks Nitya. -atong */ - +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c --- v2.3.27/linux/drivers/video/cyber2000fb.c Mon Nov 1 13:56:27 1999 +++ linux/drivers/video/cyber2000fb.c Fri Nov 12 04:29:47 1999 @@ -5,6 +5,7 @@ * * Based on cyberfb.c */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/drivers/video/rivafb.c linux/drivers/video/rivafb.c --- v2.3.27/linux/drivers/video/rivafb.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/video/rivafb.c Fri Nov 12 04:29:47 1999 @@ -20,6 +20,7 @@ /* version number of this driver */ #define RIVAFB_VERSION "0.6.5" +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/fs/dquot.c linux/fs/dquot.c --- v2.3.27/linux/fs/dquot.c Sat Oct 9 11:47:50 1999 +++ linux/fs/dquot.c Fri Nov 12 04:36:13 1999 @@ -21,6 +21,19 @@ * Revised list management to avoid races * -- Bill Hawes, , 9/98 * + * Fixed races in dquot_transfer(), dqget() and dquot_alloc_...(). + * As the consequence the locking was moved from dquot_decr_...(), + * dquot_incr_...() to calling functions. + * invalidate_dquots() now writes modified dquots. + * Serialized quota_off() and quota_on() for mount point. + * Fixed a few bugs in grow_dquots. + * Fixed deadlock in write_dquot() - we no longer account quotas on + * quota files + * remove_dquot_ref() moved to inode.c - it now traverses through inodes + * add_dquot_ref() restarts after blocking + * Added check for bogus uid and fixed check for group in quotactl. + * Jan Kara, , sponsored by SuSE CR, 10-11/99 + * * (C) Copyright 1994 - 1997 Marco van Wieringen */ @@ -74,7 +87,7 @@ */ static struct dquot *inuse_list = NULL; -LIST_HEAD(free_dquots); +static LIST_HEAD(free_dquots); static struct dquot *dquot_hash[NR_DQHASH]; static int dquot_updating[NR_DQHASH]; @@ -82,6 +95,9 @@ static DECLARE_WAIT_QUEUE_HEAD(dquot_wait); static DECLARE_WAIT_QUEUE_HEAD(update_wait); +static void dqput(struct dquot *); +static struct dquot *dqduplicate(struct dquot *); + static inline char is_enabled(struct vfsmount *vfsmnt, short type) { switch (type) { @@ -166,7 +182,8 @@ { /* sanity check */ if (list_empty(&dquot->dq_free)) { - printk("remove_free_dquot: dquot not on free list??\n"); + printk("remove_free_dquot: dquot not on the free list??\n"); + return; /* J.K. Just don't do anything */ } list_del(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_free); @@ -226,16 +243,25 @@ wake_up(&dquot->dq_wait); } +/* + * We don't have to be afraid of deadlocks as we never have quotas on quota files... + */ static void write_dquot(struct dquot *dquot) { short type = dquot->dq_type; - struct file *filp = dquot->dq_mnt->mnt_dquot.files[type]; + struct file *filp; mm_segment_t fs; loff_t offset; ssize_t ret; + struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem; lock_dquot(dquot); - down(&dquot->dq_mnt->mnt_dquot.semaphore); + if (!dquot->dq_mnt) { /* Invalidated quota? */ + unlock_dquot(dquot); + return; + } + down(sem); + filp = dquot->dq_mnt->mnt_dquot.files[type]; offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); @@ -253,40 +279,42 @@ printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", kdevname(dquot->dq_dev)); - up(&dquot->dq_mnt->mnt_dquot.semaphore); set_fs(fs); - + up(sem); unlock_dquot(dquot); + dqstats.writes++; } static void read_dquot(struct dquot *dquot) { - short type; + short type = dquot->dq_type; struct file *filp; mm_segment_t fs; loff_t offset; - type = dquot->dq_type; filp = dquot->dq_mnt->mnt_dquot.files[type]; - if (filp == (struct file *)NULL) return; lock_dquot(dquot); - down(&dquot->dq_mnt->mnt_dquot.semaphore); + if (!dquot->dq_mnt) /* Invalidated quota? */ + goto out_lock; + /* Now we are sure filp is valid - the dquot isn't invalidated */ + down(&dquot->dq_mnt->mnt_dquot.dqio_sem); offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset); - up(&dquot->dq_mnt->mnt_dquot.semaphore); + up(&dquot->dq_mnt->mnt_dquot.dqio_sem); set_fs(fs); if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 && dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0) dquot->dq_flags |= DQ_FAKE; - unlock_dquot(dquot); dqstats.reads++; +out_lock: + unlock_dquot(dquot); } /* @@ -306,10 +334,11 @@ void invalidate_dquots(kdev_t dev, short type) { - struct dquot *dquot, *next = inuse_list; + struct dquot *dquot, *next; int need_restart; restart: + next = inuse_list; /* Here it is better. Otherwise the restart doesn't have any sense ;-) */ need_restart = 0; while ((dquot = next) != NULL) { next = dquot->dq_next; @@ -317,6 +346,8 @@ continue; if (dquot->dq_type != type) continue; + if (!dquot->dq_mnt) /* Already invalidated entry? */ + continue; if (dquot->dq_flags & DQ_LOCKED) { __wait_on_dquot(dquot); @@ -329,6 +360,18 @@ continue; if (dquot->dq_type != type) continue; + if (!dquot->dq_mnt) + continue; + } + /* + * Because inodes needn't to be the only holders of dquot + * the quota needn't to be written to disk. So we write it + * ourselves before discarding the data just for sure... + */ + if (dquot->dq_flags & DQ_MOD && dquot->dq_mnt) + { + write_dquot(dquot); + need_restart = 1; /* We slept on IO */ } clear_dquot(dquot); } @@ -342,10 +385,11 @@ int sync_dquots(kdev_t dev, short type) { - struct dquot *dquot, *next = inuse_list; + struct dquot *dquot, *next, *ddquot; int need_restart; restart: + next = inuse_list; need_restart = 0; while ((dquot = next) != NULL) { next = dquot->dq_next; @@ -353,12 +397,16 @@ continue; if (type != -1 && dquot->dq_type != type) continue; + if (!dquot->dq_mnt) /* Invalidated? */ + continue; if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD))) continue; - wait_on_dquot(dquot); - if (dquot->dq_flags & DQ_MOD) - write_dquot(dquot); + if ((ddquot = dqduplicate(dquot)) == NODQUOT) + continue; + if (ddquot->dq_flags & DQ_MOD) + write_dquot(ddquot); + dqput(ddquot); /* Set the flag for another pass. */ need_restart = 1; } @@ -373,7 +421,8 @@ return(0); } -void dqput(struct dquot *dquot) +/* NOTE: If you change this function please check whether dqput_blocks() works right... */ +static void dqput(struct dquot *dquot) { if (!dquot) return; @@ -390,42 +439,45 @@ * checking and doesn't need to be written. It's just an empty * dquot that is put back on to the freelist. */ - if (dquot->dq_mnt != (struct vfsmount *)NULL) { + if (dquot->dq_mnt) dqstats.drops++; we_slept: - wait_on_dquot(dquot); - if (dquot->dq_count > 1) { - dquot->dq_count--; - return; - } - if (dquot->dq_flags & DQ_MOD) { - write_dquot(dquot); - goto we_slept; - } + if (dquot->dq_count > 1) { + /* We have more than one user... We can simply decrement use count */ + dquot->dq_count--; + return; + } + if (dquot->dq_flags & DQ_LOCKED) { + printk(KERN_ERR "VFS: Locked quota to be put on the free list.\n"); + dquot->dq_flags &= ~DQ_LOCKED; + } + if (dquot->dq_mnt && dquot->dq_flags & DQ_MOD) { + write_dquot(dquot); + goto we_slept; } /* sanity check */ if (!list_empty(&dquot->dq_free)) { - printk("dqput: dquot already on free list??\n"); - } - if (--dquot->dq_count == 0) { - /* Place at end of LRU free queue */ - put_dquot_last(dquot); - wake_up(&dquot_wait); + printk(KERN_ERR "dqput: dquot already on free list??\n"); + dquot->dq_count--; /* J.K. Just decrementing use count seems safer... */ + return; } - - return; + dquot->dq_count--; + dquot->dq_flags &= ~DQ_MOD; /* Modified flag has no sense on free list */ + /* Place at end of LRU free queue */ + put_dquot_last(dquot); + wake_up(&dquot_wait); } -static void grow_dquots(void) +static int grow_dquots(void) { struct dquot *dquot; - int cnt = 32; + int cnt = 0; - while (cnt > 0) { + while (cnt < 32) { dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL); if(!dquot) - return; + return cnt; nr_dquots++; memset((caddr_t)dquot, 0, sizeof(struct dquot)); @@ -433,8 +485,9 @@ /* all dquots go on the inuse_list */ put_inuse(dquot); put_dquot_head(dquot); - cnt--; + cnt++; } + return cnt; } static struct dquot *find_best_candidate_weighted(void) @@ -446,6 +499,7 @@ while ((tmp = tmp->next) != &free_dquots && --limit) { dquot = list_entry(tmp, struct dquot, dq_free); + /* This should never happen... */ if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) continue; myscore = dquot->dq_referenced; @@ -474,27 +528,16 @@ struct dquot *get_empty_dquot(void) { struct dquot *dquot; - int count; + int shrink = 1; /* Number of times we should try to shrink dcache and icache */ repeat: dquot = find_best_free(); if (!dquot) goto pressure; got_it: - if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) { - wait_on_dquot(dquot); - if (dquot->dq_flags & DQ_MOD) - { - if(dquot->dq_mnt != (struct vfsmount *)NULL) - write_dquot(dquot); - } - /* - * The dquot may be back in use now, so we - * must recheck the free list. - */ - goto repeat; - } - /* sanity check ... */ + /* Sanity checks */ + if (dquot->dq_flags & DQ_LOCKED) + printk(KERN_ERR "VFS: Locked dquot on the free list\n"); if (dquot->dq_count != 0) printk(KERN_ERR "VFS: free dquot count=%d\n", dquot->dq_count); @@ -505,10 +548,9 @@ return dquot; pressure: - if (nr_dquots < max_dquots) { - grow_dquots(); - goto repeat; - } + if (nr_dquots < max_dquots) + if (grow_dquots()) + goto repeat; dquot = find_best_candidate_weighted(); if (dquot) @@ -516,10 +558,11 @@ /* * Try pruning the dcache to free up some dquots ... */ - if (count) { - printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count); - prune_dcache(count); - prune_icache(count); + if (shrink) { + printk(KERN_DEBUG "get_empty_dquot: pruning dcache and icache\n"); + prune_dcache(128); + prune_icache(128); + shrink--; goto repeat; } @@ -534,7 +577,7 @@ struct dquot *dquot, *empty = NULL; struct vfsmount *vfsmnt; - if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0) + if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || !is_enabled(vfsmnt, type)) return(NODQUOT); we_slept: @@ -567,12 +610,67 @@ while (dquot_updating[hashent]) sleep_on(&update_wait); + if (!dquot->dq_mnt) { /* Has somebody invalidated entry under us? */ + /* + * Do it as if the quota was invalidated before we started + */ + dqput(dquot); + return NODQUOT; + } dquot->dq_referenced++; dqstats.lookups++; return dquot; } +static struct dquot *dqduplicate(struct dquot *dquot) +{ + if (dquot == NODQUOT || !dquot->dq_mnt) + return NODQUOT; + dquot->dq_count++; + wait_on_dquot(dquot); + if (!dquot->dq_mnt) { + dquot->dq_count--; + return NODQUOT; + } + dquot->dq_referenced++; + dqstats.lookups++; + return dquot; +} + +/* Check whether this inode is quota file */ +static inline int is_quotafile(struct inode *inode) +{ + int cnt; + struct vfsmount *vfsmnt; + struct file **files; + + vfsmnt = lookup_vfsmnt(inode->i_dev); + if (!vfsmnt) + return 0; + files = vfsmnt->mnt_dquot.files; + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (files[cnt] && files[cnt]->f_dentry->d_inode == inode) + return 1; + return 0; +} + +static int dqinit_needed(struct inode *inode, short type) +{ + int cnt; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) + return 0; + if (is_quotafile(inode)) + return 0; + if (type != -1) + return inode->i_dquot[type] == NODQUOT; + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt] == NODQUOT) + return 1; + return 0; +} + static void add_dquot_ref(kdev_t dev, short type) { struct super_block *sb = get_super(dev); @@ -582,6 +680,7 @@ if (!sb || !sb->dq_op) return; /* nothing to do */ +restart: file_list_lock(); for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { struct file *filp = list_entry(p, struct file, f_list); @@ -590,84 +689,81 @@ inode = filp->f_dentry->d_inode; if (!inode) continue; - /* N.B. race problem -- filp could become unused */ - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { file_list_unlock(); sb->dq_op->initialize(inode, type); inode->i_flags |= S_QUOTA; - file_list_lock(); + /* As we may have blocked we had better restart... */ + goto restart; } } file_list_unlock(); } -static void reset_dquot_ptrs(kdev_t dev, short type) +/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ +static inline int dqput_blocks(struct dquot *dquot) { - struct super_block *sb = get_super(dev); - struct list_head *p; - struct inode *inode; - struct dquot *dquot; + if (dquot->dq_count == 1) + return 1; + return 0; +} + +/* Remove references to dquots from inode - add dquot to list for freeing if needed */ +int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *tofree_head) +{ + struct dquot *dquot = inode->i_dquot[type]; int cnt; - if (!sb || !sb->dq_op) - return; /* nothing to do */ + inode->i_dquot[type] = NODQUOT; + /* any other quota in use? */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + if (inode->i_dquot[cnt] != NODQUOT) + goto put_it; + } + inode->i_flags &= ~S_QUOTA; +put_it: + if (dquot != NODQUOT) + if (dqput_blocks(dquot)) { + if (dquot->dq_count != 1) + printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count); + list_add(&dquot->dq_free, tofree_head); /* As dquot must have currently users it can't be on the free list... */ + return 1; + } + else + dqput(dquot); /* We have guaranteed we won't block */ + return 0; +} -restart: - /* free any quota for unused dentries */ - shrink_dcache_sb(sb); +/* Free list of dquots - called from inode.c */ +void put_dquot_list(struct list_head *tofree_head) +{ + struct list_head *act_head = tofree_head; + struct dquot *dquot; - file_list_lock(); - for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { - struct file *filp = list_entry(p, struct file, f_list); - if (!filp->f_dentry) - continue; - inode = filp->f_dentry->d_inode; - if (!inode) - continue; - /* - * Note: we restart after each blocking operation, - * as the inuse_filps list may have changed. - */ - if (IS_QUOTAINIT(inode)) { - dquot = inode->i_dquot[type]; - inode->i_dquot[type] = NODQUOT; - /* any other quota in use? */ - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] != NODQUOT) - goto put_it; - } - inode->i_flags &= ~S_QUOTA; - put_it: - if (dquot != NODQUOT) { - file_list_unlock(); - dqput(dquot); - /* we may have blocked ... */ - goto restart; - } - } + /* So now we have dquots on the list... Just free them */ + while (act_head != tofree_head) { + dquot = list_entry(act_head, struct dquot, dq_free); + act_head = act_head->next; + list_del(&dquot->dq_free); /* Remove dquot from the list so we won't have problems... */ + INIT_LIST_HEAD(&dquot->dq_free); + dqput(dquot); } - file_list_unlock(); } static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) { - lock_dquot(dquot); dquot->dq_curinodes += number; dquot->dq_flags |= DQ_MOD; - unlock_dquot(dquot); } static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number) { - lock_dquot(dquot); dquot->dq_curblocks += number; dquot->dq_flags |= DQ_MOD; - unlock_dquot(dquot); } static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number) { - lock_dquot(dquot); if (dquot->dq_curinodes > number) dquot->dq_curinodes -= number; else @@ -676,12 +772,10 @@ dquot->dq_itime = (time_t) 0; dquot->dq_flags &= ~DQ_INODES; dquot->dq_flags |= DQ_MOD; - unlock_dquot(dquot); } static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number) { - lock_dquot(dquot); if (dquot->dq_curblocks > number) dquot->dq_curblocks -= number; else @@ -690,7 +784,6 @@ dquot->dq_btime = (time_t) 0; dquot->dq_flags &= ~DQ_BLKS; dquot->dq_flags |= DQ_MOD; - unlock_dquot(dquot); } static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot) @@ -709,7 +802,7 @@ return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0); } -static int check_idq(struct dquot *dquot, short type, u_long short inodes, uid_t initiator, +static int check_idq(struct dquot *dquot, short type, u_long inodes, uid_t initiator, struct tty_struct *tty) { if (inodes <= 0 || dquot->dq_flags & DQ_FAKE) @@ -874,9 +967,11 @@ if (dquot == NODQUOT) goto out; + lock_dquot(dquot); /* We must protect against invalidating the quota */ error = -EFAULT; if (dqblk && !copy_to_user(dqblk, &dquot->dq_dqb, sizeof(struct dqblk))) error = 0; + unlock_dquot(dquot); dqput(dquot); out: return error; @@ -917,14 +1012,14 @@ * This is a simple algorithm that calculates the size of a file in blocks. * This is only used on filesystems that do not have an i_blocks count. */ -static u_long isize_to_blocks(size_t isize, size_t blksize) +static u_long isize_to_blocks(loff_t isize, size_t blksize_bits) { u_long blocks; u_long indirect; - if (!blksize) - blksize = BLOCK_SIZE; - blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0); + if (!blksize_bits) + blksize_bits = BLOCK_SIZE_BITS; + blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0); if (blocks > 10) { indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */ if (blocks > (10 + 256)) { @@ -934,7 +1029,7 @@ } blocks += indirect; } - return(blocks); + return blocks; } /* @@ -951,6 +1046,9 @@ if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { + /* We don't want to have quotas on quota files - nasty deadlocks possible */ + if (is_quotafile(inode)) + return; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; @@ -968,6 +1066,8 @@ break; } dquot = dqget(inode->i_dev, id, cnt); + if (dquot == NODQUOT) + continue; if (inode->i_dquot[cnt] != NODQUOT) { dqput(dquot); continue; @@ -1005,23 +1105,36 @@ int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator, char warn) { - unsigned short cnt; + int cnt; struct tty_struct *tty = current->tty; + struct dquot *dquot[MAXQUOTAS]; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + dquot[cnt] = dqduplicate(inode->i_dquot[cnt]); + if (dquot[cnt] == NODQUOT) continue; - if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn)) - return(NO_QUOTA); + lock_dquot(dquot[cnt]); + if (check_bdq(dquot[cnt], cnt, number, initiator, tty, warn)) + goto put_all; } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (dquot[cnt] == NODQUOT) continue; - dquot_incr_blocks(inode->i_dquot[cnt], number); + dquot_incr_blocks(dquot[cnt], number); + unlock_dquot(dquot[cnt]); + dqput(dquot[cnt]); } - return(QUOTA_OK); + return QUOTA_OK; +put_all: + for (; cnt >= 0; cnt--) { + if (dquot[cnt] == NODQUOT) + continue; + unlock_dquot(dquot[cnt]); + dqput(dquot[cnt]); + } + return NO_QUOTA; } /* @@ -1029,23 +1142,36 @@ */ int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator) { - unsigned short cnt; + int cnt; struct tty_struct *tty = current->tty; + struct dquot *dquot[MAXQUOTAS]; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]); + if (dquot[cnt] == NODQUOT) continue; - if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty)) - return(NO_QUOTA); + lock_dquot(dquot[cnt]); + if (check_idq(dquot[cnt], cnt, number, initiator, tty)) + goto put_all; } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (dquot[cnt] == NODQUOT) continue; - dquot_incr_inodes(inode->i_dquot[cnt], number); + dquot_incr_inodes(dquot[cnt], number); + unlock_dquot(dquot[cnt]); + dqput(dquot[cnt]); } - return(QUOTA_OK); + return QUOTA_OK; +put_all: + for (; cnt >= 0; cnt--) { + if (dquot[cnt] == NODQUOT) + continue; + unlock_dquot(dquot[cnt]); + dqput(dquot[cnt]); + } + return NO_QUOTA; } /* @@ -1054,11 +1180,14 @@ void dquot_free_block(const struct inode *inode, unsigned long number) { unsigned short cnt; + struct dquot *dquot; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + dquot = inode->i_dquot[cnt]; + if (dquot == NODQUOT) continue; - dquot_decr_blocks(inode->i_dquot[cnt], number); + wait_on_dquot(dquot); + dquot_decr_blocks(dquot, number); } } @@ -1068,11 +1197,14 @@ void dquot_free_inode(const struct inode *inode, unsigned long number) { unsigned short cnt; + struct dquot *dquot; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + dquot = inode->i_dquot[cnt]; + if (dquot == NODQUOT) continue; - dquot_decr_inodes(inode->i_dquot[cnt], number); + wait_on_dquot(dquot); + dquot_decr_inodes(dquot, number); } } @@ -1081,21 +1213,25 @@ * * Note: this is a blocking operation. */ -int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator) +int dquot_transfer(struct dentry *dentry, struct iattr *iattr, uid_t initiator) { + struct inode *inode = dentry -> d_inode; unsigned long blocks; struct dquot *transfer_from[MAXQUOTAS]; struct dquot *transfer_to[MAXQUOTAS]; struct tty_struct *tty = current->tty; short cnt, disc; + int error = -EDQUOT; + if (!inode) + return -ENOENT; /* * Find out if this filesystem uses i_blocks. */ - if (inode->i_blksize == 0) - blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE); + if (!inode->i_sb || !inode->i_sb->s_blocksize) + blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS); else - blocks = (inode->i_blocks / 2); + blocks = (inode->i_blocks >> 1); /* * Build the transfer_from and transfer_to lists and check quotas to see @@ -1112,27 +1248,60 @@ case USRQUOTA: if (inode->i_uid == iattr->ia_uid) continue; - transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt); - transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt); + /* We can get transfer_from from inode, can't we? */ + transfer_from[cnt] = dqget(inode->i_dev, inode->i_uid, cnt); + transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_uid, cnt); break; case GRPQUOTA: if (inode->i_gid == iattr->ia_gid) continue; - transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt); - transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt); + transfer_from[cnt] = dqget(inode->i_dev, inode->i_gid, cnt); + transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_gid, cnt); break; } - if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA || - check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) { - for (disc = 0; disc <= cnt; disc++) { - dqput(transfer_from[disc]); - dqput(transfer_to[disc]); + /* Something bad (eg. quotaoff) happened while we were sleeping? */ + if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT) + { + if (transfer_from[cnt] != NODQUOT) { + dqput(transfer_from[cnt]); + transfer_from[cnt] = NODQUOT; } - return(NO_QUOTA); + if (transfer_to[cnt] != NODQUOT) { + dqput(transfer_to[cnt]); + transfer_to[cnt] = NODQUOT; + } + continue; + } + /* + * We have to lock the quotas to prevent races... + */ + if (transfer_from[cnt] < transfer_to[cnt]) + { + lock_dquot(transfer_from[cnt]); + lock_dquot(transfer_to[cnt]); + } + else + { + lock_dquot(transfer_to[cnt]); + lock_dquot(transfer_from[cnt]); + } + + /* + * The entries might got invalidated while locking. The second + * dqget() could block and so the first structure might got + * invalidated or locked... + */ + if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt || + check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA || + check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) { + cnt++; + goto put_all; } } + if ((error = notify_change(dentry, iattr))) + goto put_all; /* * Finally perform the needed transfer from transfer_from to transfer_to, * and release any pointers to dquots not needed anymore. @@ -1144,28 +1313,39 @@ if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT) continue; - if (transfer_from[cnt] != NODQUOT) { - dquot_decr_inodes(transfer_from[cnt], 1); - dquot_decr_blocks(transfer_from[cnt], blocks); - } + dquot_decr_inodes(transfer_from[cnt], 1); + dquot_decr_blocks(transfer_from[cnt], blocks); - if (transfer_to[cnt] != NODQUOT) { - dquot_incr_inodes(transfer_to[cnt], 1); - dquot_incr_blocks(transfer_to[cnt], blocks); - } + dquot_incr_inodes(transfer_to[cnt], 1); + dquot_incr_blocks(transfer_to[cnt], blocks); + unlock_dquot(transfer_from[cnt]); + dqput(transfer_from[cnt]); if (inode->i_dquot[cnt] != NODQUOT) { struct dquot *temp = inode->i_dquot[cnt]; inode->i_dquot[cnt] = transfer_to[cnt]; + unlock_dquot(transfer_to[cnt]); dqput(temp); - dqput(transfer_from[cnt]); } else { - dqput(transfer_from[cnt]); + unlock_dquot(transfer_to[cnt]); dqput(transfer_to[cnt]); } } - return(QUOTA_OK); + return 0; +put_all: + for (disc = 0; disc < cnt; disc++) { + /* There should be none or both pointers set but... */ + if (transfer_to[disc] != NODQUOT) { + unlock_dquot(transfer_to[disc]); + dqput(transfer_to[disc]); + } + if (transfer_from[disc] != NODQUOT) { + unlock_dquot(transfer_from[disc]); + dqput(transfer_from[disc]); + } + } + return error; } @@ -1221,6 +1401,9 @@ } } +/* Function in inode.c - remove pointers to dquots in icache */ +extern void remove_dquot_ref(kdev_t, short); + /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) */ @@ -1229,48 +1412,57 @@ struct vfsmount *vfsmnt; struct file *filp; short cnt; + int enabled = 0; + + /* We don't need to search for vfsmnt each time - umount has to wait for us */ + vfsmnt = lookup_vfsmnt(dev); + if (!vfsmnt || !vfsmnt->mnt_sb) + goto out; + /* We need to serialize quota_off() for device */ + down(&vfsmnt->mnt_dquot.dqoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; - - vfsmnt = lookup_vfsmnt(dev); - if (!vfsmnt) - goto out; - if (!vfsmnt->mnt_sb) - goto out; if (!is_enabled(vfsmnt, cnt)) continue; reset_enable_flags(vfsmnt, cnt); /* Note: these are blocking operations */ - reset_dquot_ptrs(dev, cnt); + remove_dquot_ref(dev, cnt); invalidate_dquots(dev, cnt); + /* Wait for any pending IO - remove me as soon as invalidate is more polite */ + down(&vfsmnt->mnt_dquot.dqio_sem); filp = vfsmnt->mnt_dquot.files[cnt]; vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL; vfsmnt->mnt_dquot.inode_expire[cnt] = 0; vfsmnt->mnt_dquot.block_expire[cnt] = 0; + up(&vfsmnt->mnt_dquot.dqio_sem); fput(filp); - } + } /* * Check whether any quota is still enabled, * and if not clear the dq_op pointer. */ - vfsmnt = lookup_vfsmnt(dev); - if (vfsmnt && vfsmnt->mnt_sb) { - int enabled = 0; - for (cnt = 0; cnt < MAXQUOTAS; cnt++) - enabled |= is_enabled(vfsmnt, cnt); - if (!enabled) - vfsmnt->mnt_sb->dq_op = NULL; - } - + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + enabled |= is_enabled(vfsmnt, cnt); + if (!enabled) + vfsmnt->mnt_sb->dq_op = NULL; + up(&vfsmnt->mnt_dquot.dqoff_sem); out: return(0); } +static inline int check_quotafile_size(loff_t size) +{ + ulong blocks = size >> BLOCK_SIZE_BITS; + size_t off = size & ~(BLOCK_SIZE - 1); + + return !((blocks % sizeof(struct dqblk) + off % sizeof(struct dqblk)) % sizeof(struct dqblk)); +} + int quota_on(kdev_t dev, short type, char *path) { struct file *f; @@ -1287,47 +1479,52 @@ if (is_enabled(vfsmnt, type)) return -EBUSY; - mnt_dquot = &vfsmnt->mnt_dquot; + mnt_dquot = &vfsmnt->mnt_dquot; + down(&mnt_dquot->dqoff_sem); tmp = getname(path); error = PTR_ERR(tmp); if (IS_ERR(tmp)) - return error; + goto out_lock; f = filp_open(tmp, O_RDWR, 0600); putname(tmp); - if (IS_ERR(f)) - return PTR_ERR(f); - /* sanity checks */ + error = PTR_ERR(f); + if (IS_ERR(f)) + goto out_lock; error = -EIO; if (!f->f_op->read && !f->f_op->write) - goto cleanup; + goto out_f; inode = f->f_dentry->d_inode; error = -EACCES; if (!S_ISREG(inode->i_mode)) - goto cleanup; + goto out_f; error = -EINVAL; - if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) - goto cleanup; + if (inode->i_size == 0 || !check_quotafile_size(inode->i_size)) + goto out_f; + dquot_drop(inode); /* We don't want quota on quota files */ - /* OK, there we go */ set_enable_flags(vfsmnt, type); mnt_dquot->files[type] = f; dquot = dqget(dev, 0, type); - mnt_dquot->inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME; - mnt_dquot->block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME; + mnt_dquot->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME; + mnt_dquot->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME; dqput(dquot); vfsmnt->mnt_sb->dq_op = &dquot_operations; add_dquot_ref(dev, type); - return(0); + up(&mnt_dquot->dqoff_sem); + return 0; -cleanup: - fput(f); - return error; +out_f: + filp_close(f, NULL); +out_lock: + up(&mnt_dquot->dqoff_sem); + + return error; } /* @@ -1348,6 +1545,9 @@ if ((u_int) type >= MAXQUOTAS) goto out; + if (id & ~0xFFFF) + goto out; + ret = -EPERM; switch (cmds) { case Q_SYNC: @@ -1355,7 +1555,7 @@ break; case Q_GETQUOTA: if (((type == USRQUOTA && current->euid != id) || - (type == GRPQUOTA && current->egid != id)) && + (type == GRPQUOTA && in_group_p(id))) && !capable(CAP_SYS_RESOURCE)) goto out; break; @@ -1365,7 +1565,7 @@ } ret = -EINVAL; - dev = 0; + dev = NODEV; if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) { mode_t mode; struct dentry * dentry; diff -u --recursive --new-file v2.3.27/linux/fs/inode.c linux/fs/inode.c --- v2.3.27/linux/fs/inode.c Mon Nov 1 13:56:27 1999 +++ linux/fs/inode.c Fri Nov 12 11:06:18 1999 @@ -756,3 +756,51 @@ inode->i_atime = CURRENT_TIME; mark_inode_dirty (inode); } /* End Function update_atime */ + + +/* + * Quota functions that want to walk the inode lists.. + */ +#ifdef CONFIG_QUOTA + +/* Functions back in dquot.c */ +void put_dquot_list(struct list_head *); +int remove_inode_dquot_ref(struct inode *, short, struct list_head *); + +void remove_dquot_ref(kdev_t dev, short type) +{ + struct super_block *sb = get_super(dev); + struct inode *inode; + struct list_head *act_head; + LIST_HEAD(tofree_head); + + if (!sb || !sb->dq_op) + return; /* nothing to do */ + + /* We have to be protected against other CPUs */ + spin_lock(&inode_lock); + + for (act_head = inode_in_use.next; act_head != &inode_in_use; act_head = act_head->next) { + inode = list_entry(act_head, struct inode, i_list); + if (inode->i_sb != sb || !IS_QUOTAINIT(inode)) + continue; + remove_inode_dquot_ref(inode, type, &tofree_head); + } + for (act_head = inode_unused.next; act_head != &inode_unused; act_head = act_head->next) { + inode = list_entry(act_head, struct inode, i_list); + if (inode->i_sb != sb || !IS_QUOTAINIT(inode)) + continue; + remove_inode_dquot_ref(inode, type, &tofree_head); + } + for (act_head = sb->s_dirty.next; act_head != &sb->s_dirty; act_head = act_head->next) { + inode = list_entry(act_head, struct inode, i_list); + if (!IS_QUOTAINIT(inode)) + continue; + remove_inode_dquot_ref(inode, type, &tofree_head); + } + spin_unlock(&inode_lock); + + put_dquot_list(&tofree_head); +} + +#endif diff -u --recursive --new-file v2.3.27/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.3.27/linux/fs/isofs/inode.c Sun Nov 7 16:37:34 1999 +++ linux/fs/isofs/inode.c Fri Nov 12 13:21:09 1999 @@ -990,8 +990,8 @@ } bh_result->b_dev = inode->i_dev; - bh_result->b_blocknr = - (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode); + bh_result->b_blocknr = firstext + + ((b_off - offset) >> ISOFS_BUFFER_BITS(inode)); bh_result->b_state |= (1UL << BH_Mapped); err = 0; @@ -1236,8 +1236,7 @@ iso_date(raw_inode->date, high_sierra); inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + - isonum_711 (raw_inode->ext_attr_length)) - << inode -> i_sb -> u.isofs_sb.s_log_zone_size; + isonum_711 (raw_inode->ext_attr_length)); /* Now test for possible Rock Ridge extensions which will override some of these numbers in the inode structure. */ diff -u --recursive --new-file v2.3.27/linux/fs/isofs/rock.c linux/fs/isofs/rock.c --- v2.3.27/linux/fs/isofs/rock.c Fri Sep 25 16:27:13 1998 +++ linux/fs/isofs/rock.c Fri Nov 12 13:21:09 1999 @@ -358,9 +358,10 @@ #ifdef DEBUG printk("RR CL (%x)\n",inode->i_ino); #endif - inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) << - inode -> i_sb -> u.isofs_sb.s_log_zone_size; - reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent); + inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); + reloc = iget(inode->i_sb, + (inode->u.isofs_i.i_first_extent << + inode -> i_sb -> u.isofs_sb.s_log_zone_size)); if (!reloc) goto out; inode->i_mode = reloc->i_mode; diff -u --recursive --new-file v2.3.27/linux/fs/nfsd/stats.c linux/fs/nfsd/stats.c --- v2.3.27/linux/fs/nfsd/stats.c Thu Nov 11 20:11:50 1999 +++ linux/fs/nfsd/stats.c Fri Nov 12 04:40:46 1999 @@ -17,6 +17,7 @@ #include #include #include +#define __NO_VERSION__ #include #include diff -u --recursive --new-file v2.3.27/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.3.27/linux/fs/proc/array.c Thu Nov 11 20:11:50 1999 +++ linux/fs/proc/array.c Fri Nov 12 04:29:47 1999 @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/fs/proc/base.c linux/fs/proc/base.c --- v2.3.27/linux/fs/proc/base.c Thu Nov 11 20:11:50 1999 +++ linux/fs/proc/base.c Fri Nov 12 11:02:34 1999 @@ -104,9 +104,12 @@ { struct mm_struct *mm = task->mm; int res = 0; - if (mm) - res = access_process_vm(task, mm->env_start, buffer, - mm->env_end - mm->env_start, 0); + if (mm) { + int len = mm->env_end - mm->env_start; + if (len > PAGE_SIZE) + len = PAGE_SIZE; + res = access_process_vm(task, mm->env_start, buffer, len, 0); + } return res; } @@ -116,9 +119,12 @@ { struct mm_struct *mm = task->mm; int res = 0; - if (mm) - res = access_process_vm(task, mm->arg_start, buffer, - mm->arg_end - mm->arg_start, 0); + if (mm) { + int len = mm->arg_end - mm->arg_start; + if (len > PAGE_SIZE) + len = PAGE_SIZE; + res = access_process_vm(task, mm->arg_start, buffer, len, 0); + } return res; } diff -u --recursive --new-file v2.3.27/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.3.27/linux/fs/proc/inode.c Thu Nov 11 20:11:50 1999 +++ linux/fs/proc/inode.c Fri Nov 12 04:40:46 1999 @@ -14,6 +14,7 @@ #include #include #include +#define __NO_VERSION__ #include #include diff -u --recursive --new-file v2.3.27/linux/fs/proc/kcore.c linux/fs/proc/kcore.c --- v2.3.27/linux/fs/proc/kcore.c Thu Nov 11 20:11:50 1999 +++ linux/fs/proc/kcore.c Fri Nov 12 10:37:24 1999 @@ -16,7 +16,6 @@ #include #include #include -#include #include @@ -189,7 +188,7 @@ * store an ELF coredump header in the supplied buffer * num_vma is the number of elements in vmlist */ -static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen) +static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff) { struct elf_prstatus prstatus; /* NT_PRSTATUS */ struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */ @@ -235,18 +234,20 @@ nhdr->p_flags = 0; nhdr->p_align = 0; - /* setup ELF PT_LOAD program header */ + /* setup ELF PT_LOAD program header for the + * virtual range 0xc0000000 -> high_memory */ phdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr); phdr->p_type = PT_LOAD; phdr->p_flags = PF_R|PF_W|PF_X; - phdr->p_offset = elf_buflen; + phdr->p_offset = dataoff; phdr->p_vaddr = PAGE_OFFSET; phdr->p_paddr = __pa(PAGE_OFFSET); phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET); phdr->p_align = PAGE_SIZE; + /* setup ELF PT_LOAD program headers, one for every kvma range */ for (m=vmlist; m; m=m->next) { phdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); @@ -254,9 +255,9 @@ phdr->p_type = PT_LOAD; phdr->p_flags = PF_R|PF_W|PF_X; - phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + elf_buflen; + phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + dataoff; phdr->p_vaddr = (size_t)m->addr; - phdr->p_paddr = __pa(m); + phdr->p_paddr = __pa(m->addr); phdr->p_filesz = phdr->p_memsz = m->size; phdr->p_align = PAGE_SIZE; } @@ -310,13 +311,16 @@ /* * read from the ELF header and then kernel memory */ -static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, - loff_t *fpos) +static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos) { ssize_t acc = 0; size_t size, tsz; char * elf_buffer; - int elf_buflen = 0, num_vma = 0; + size_t elf_buflen = 0; + int num_vma = 0; + + if (verify_area(VERIFY_WRITE, buffer, buflen)) + return -EFAULT; /* XXX we need to somehow lock vmlist between here * and after elf_kcore_store_hdr() returns. @@ -340,7 +344,7 @@ return -ENOMEM; memset(elf_buffer, 0, elf_buflen); elf_kcore_store_hdr(elf_buffer, num_vma, elf_buflen); - copy_to_user(buffer, elf_buffer, tsz); + copy_to_user(buffer, elf_buffer + *fpos, tsz); kfree(elf_buffer); buflen -= tsz; *fpos += tsz; @@ -349,7 +353,7 @@ /* leave now if filled buffer already */ if (buflen == 0) - return tsz; + return acc; } /* where page 0 not mapped, write zeros into buffer */ @@ -374,14 +378,10 @@ #endif /* fill the remainder of the buffer from kernel VM space */ -#if defined (__i386__) || defined (__mc68000__) - copy_to_user(buffer, __va(*fpos - PAGE_SIZE), buflen); -#else - copy_to_user(buffer, __va(*fpos), buflen); -#endif + copy_to_user(buffer, __va(*fpos - elf_buflen), buflen); + acc += buflen; *fpos += buflen; - return acc; } diff -u --recursive --new-file v2.3.27/linux/fs/super.c linux/fs/super.c --- v2.3.27/linux/fs/super.c Mon Nov 1 13:56:27 1999 +++ linux/fs/super.c Fri Nov 12 04:36:13 1999 @@ -104,7 +104,8 @@ lptr->mnt_dev = sb->s_dev; lptr->mnt_flags = sb->s_flags; - sema_init(&lptr->mnt_dquot.semaphore, 1); + sema_init(&lptr->mnt_dquot.dqio_sem, 1); + sema_init(&lptr->mnt_dquot.dqoff_sem, 1); lptr->mnt_dquot.flags = 0; /* N.B. Is it really OK to have a vfsmount without names? */ diff -u --recursive --new-file v2.3.27/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v2.3.27/linux/fs/sysv/inode.c Sat Oct 9 11:47:50 1999 +++ linux/fs/sysv/inode.c Fri Nov 12 04:29:47 1999 @@ -21,6 +21,7 @@ * the superblock. */ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/fs/udf/dir.c linux/fs/udf/dir.c --- v2.3.27/linux/fs/udf/dir.c Mon Nov 1 13:56:27 1999 +++ linux/fs/udf/dir.c Fri Nov 12 04:29:47 1999 @@ -32,6 +32,7 @@ #include "udfdecl.h" #if defined(__linux__) && defined(__KERNEL__) +#include #include #include "udf_i.h" #include "udf_sb.h" diff -u --recursive --new-file v2.3.27/linux/fs/udf/file.c linux/fs/udf/file.c --- v2.3.27/linux/fs/udf/file.c Mon Nov 1 13:56:27 1999 +++ linux/fs/udf/file.c Fri Nov 12 04:29:47 1999 @@ -31,6 +31,7 @@ */ #include "udfdecl.h" +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/fs/udf/super.c linux/fs/udf/super.c --- v2.3.27/linux/fs/udf/super.c Sun Nov 7 16:37:34 1999 +++ linux/fs/udf/super.c Fri Nov 12 04:29:47 1999 @@ -48,6 +48,7 @@ #include "udfdecl.h" +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h --- v2.3.27/linux/include/asm-arm/arch-ebsa285/irq.h Fri Oct 22 13:21:53 1999 +++ linux/include/asm-arm/arch-ebsa285/irq.h Fri Nov 12 04:29:47 1999 @@ -11,6 +11,7 @@ * 16-Mar-1999 RMK Added autodetect of ISA PICs */ /* no need for config.h - arch/arm/kernel/irq.c does this for us */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-arm/arch-sa1100/irq.h linux/include/asm-arm/arch-sa1100/irq.h --- v2.3.27/linux/include/asm-arm/arch-sa1100/irq.h Fri Oct 22 13:21:53 1999 +++ linux/include/asm-arm/arch-sa1100/irq.h Fri Nov 12 04:29:47 1999 @@ -12,6 +12,8 @@ * 11-08-1999 PD SA1101 support added * 25-09-1999 RMK Merged into main ARM tree, cleaned up */ +#include + static inline unsigned int fixup_irq(unsigned int irq) { #ifdef CONFIG_SA1101 diff -u --recursive --new-file v2.3.27/linux/include/asm-arm/arch-sa1100/irqs.h linux/include/asm-arm/arch-sa1100/irqs.h --- v2.3.27/linux/include/asm-arm/arch-sa1100/irqs.h Fri Oct 22 13:21:53 1999 +++ linux/include/asm-arm/arch-sa1100/irqs.h Fri Nov 12 04:29:47 1999 @@ -4,6 +4,7 @@ * Copyright (C) 1996 Russell King * Copyright (C) 1998 Deborah Wallach (updates for SA1100/Brutus). */ +#include #ifdef CONFIG_SA1101 #define NR_IRQS 95 diff -u --recursive --new-file v2.3.27/linux/include/asm-arm/arch-sa1100/system.h linux/include/asm-arm/arch-sa1100/system.h --- v2.3.27/linux/include/asm-arm/arch-sa1100/system.h Fri Oct 22 13:21:53 1999 +++ linux/include/asm-arm/arch-sa1100/system.h Fri Nov 12 04:29:47 1999 @@ -3,6 +3,8 @@ * * Copyright (c) 1999 Nicolas Pitre */ +#include + #ifdef CONFIG_SA1100_VICTOR #define arch_reset( x ) { \ diff -u --recursive --new-file v2.3.27/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h --- v2.3.27/linux/include/asm-arm/processor.h Thu Nov 11 20:11:51 1999 +++ linux/include/asm-arm/processor.h Fri Nov 12 04:29:47 1999 @@ -7,6 +7,7 @@ #ifndef __ASM_ARM_PROCESSOR_H #define __ASM_ARM_PROCESSOR_H +#include /* * Default implementation of macro that returns current * instruction pointer ("program counter"). diff -u --recursive --new-file v2.3.27/linux/include/asm-i386/setup.h linux/include/asm-i386/setup.h --- v2.3.27/linux/include/asm-i386/setup.h Mon Jul 5 19:59:55 1999 +++ linux/include/asm-i386/setup.h Fri Nov 12 10:12:11 1999 @@ -2,3 +2,9 @@ * Just a place holder. We don't want to have to test x86 before * we include stuff */ + +#ifndef _i386_SETUP_H +#define _i386_SETUP_H + + +#endif /* _i386_SETUP_H */ diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/dvma.h linux/include/asm-m68k/dvma.h --- v2.3.27/linux/include/asm-m68k/dvma.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/dvma.h Fri Nov 12 04:29:47 1999 @@ -9,6 +9,8 @@ #ifndef __M68K_DVMA_H #define __M68K_DVMA_H +#include + #ifdef CONFIG_SUN3 /* sun3 dvma page support */ diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/elf.h linux/include/asm-m68k/elf.h --- v2.3.27/linux/include/asm-m68k/elf.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/elf.h Fri Nov 12 04:29:47 1999 @@ -5,6 +5,7 @@ * ELF register definitions.. */ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/mmu_context.h linux/include/asm-m68k/mmu_context.h --- v2.3.27/linux/include/asm-m68k/mmu_context.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/mmu_context.h Fri Nov 12 04:29:47 1999 @@ -1,6 +1,8 @@ #ifndef __M68K_MMU_CONTEXT_H #define __M68K_MMU_CONTEXT_H +#include + #ifndef CONFIG_SUN3 #include diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/openprom.h linux/include/asm-m68k/openprom.h --- v2.3.27/linux/include/asm-m68k/openprom.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/openprom.h Fri Nov 12 04:29:47 1999 @@ -8,6 +8,8 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#include + /* Empirical constants... */ #ifdef CONFIG_SUN3 #define KADB_DEBUGGER_BEGVM 0x0fee0000 /* There is no kadb yet but...*/ diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/param.h linux/include/asm-m68k/param.h --- v2.3.27/linux/include/asm-m68k/param.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/param.h Fri Nov 12 04:29:47 1999 @@ -1,6 +1,8 @@ #ifndef _M68K_PARAM_H #define _M68K_PARAM_H +#include + #ifndef HZ #define HZ 100 #endif diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h --- v2.3.27/linux/include/asm-m68k/processor.h Thu Nov 11 20:11:52 1999 +++ linux/include/asm-m68k/processor.h Fri Nov 12 04:29:47 1999 @@ -13,6 +13,7 @@ */ #define current_text_addr() ({ __label__ _l; _l: &&_l;}) +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/shm.h linux/include/asm-m68k/shm.h --- v2.3.27/linux/include/asm-m68k/shm.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/shm.h Fri Nov 12 04:29:47 1999 @@ -1,6 +1,8 @@ #ifndef _M68K_SHM_H #define _M68K_SHM_H +#include + /* format of page table entries that correspond to shared memory pages currently out in swap space (see also mm/swap.c): bits 0-1 (PAGE_PRESENT) is = 0 diff -u --recursive --new-file v2.3.27/linux/include/asm-m68k/sun3ints.h linux/include/asm-m68k/sun3ints.h --- v2.3.27/linux/include/asm-m68k/sun3ints.h Tue Sep 7 12:14:07 1999 +++ linux/include/asm-m68k/sun3ints.h Fri Nov 12 04:29:47 1999 @@ -11,7 +11,6 @@ #ifndef SUN3INTS_H #define SUN3INTS_H -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-ppc/irq_control.h linux/include/asm-ppc/irq_control.h --- v2.3.27/linux/include/asm-ppc/irq_control.h Sat Oct 9 11:47:50 1999 +++ linux/include/asm-ppc/irq_control.h Fri Nov 12 04:29:47 1999 @@ -6,8 +6,6 @@ #ifndef _PPC_IRQ_CONTROL_H #define _PPC_IRQ_CONTROL_H -#include - #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h --- v2.3.27/linux/include/asm-ppc/keyboard.h Fri Oct 15 15:25:14 1999 +++ linux/include/asm-ppc/keyboard.h Fri Nov 12 04:29:47 1999 @@ -15,7 +15,6 @@ #ifdef __KERNEL__ -#include #include #include diff -u --recursive --new-file v2.3.27/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h --- v2.3.27/linux/include/asm-ppc/linux_logo.h Sat Oct 9 11:47:50 1999 +++ linux/include/asm-ppc/linux_logo.h Fri Nov 12 04:29:47 1999 @@ -11,7 +11,6 @@ * (i.e. linux_logo_{red,green,blue}[0] is color 0x20) */ -#include #include #define linux_logo_banner "Linux/PPC version " UTS_RELEASE diff -u --recursive --new-file v2.3.27/linux/include/asm-ppc/mpc8xx.h linux/include/asm-ppc/mpc8xx.h --- v2.3.27/linux/include/asm-ppc/mpc8xx.h Sat Oct 9 11:47:50 1999 +++ linux/include/asm-ppc/mpc8xx.h Fri Nov 12 04:29:47 1999 @@ -8,6 +8,8 @@ #ifndef __CONFIG_8xx_DEFS #define __CONFIG_8xx_DEFS +#include + #ifdef CONFIG_8xx #ifdef CONFIG_MBX diff -u --recursive --new-file v2.3.27/linux/include/linux/acpi.h linux/include/linux/acpi.h --- v2.3.27/linux/include/linux/acpi.h Thu Nov 11 20:11:52 1999 +++ linux/include/linux/acpi.h Fri Nov 12 11:29:52 1999 @@ -26,6 +26,7 @@ #ifdef __KERNEL__ +#include #include #include diff -u --recursive --new-file v2.3.27/linux/include/linux/cycx_drv.h linux/include/linux/cycx_drv.h --- v2.3.27/linux/include/linux/cycx_drv.h Mon Nov 1 13:56:27 1999 +++ linux/include/linux/cycx_drv.h Thu Nov 11 20:10:36 1999 @@ -53,6 +53,7 @@ /* Function Prototypes */ extern int cycx_setup (cycxhw_t *hw, void *sfm, u32 len); +extern int cycx_down (cycxhw_t *hw); extern int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len); extern int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len); extern int cycx_exec (u32 addr); diff -u --recursive --new-file v2.3.27/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.3.27/linux/include/linux/fs.h Thu Nov 11 20:11:53 1999 +++ linux/include/linux/fs.h Fri Nov 12 11:28:05 1999 @@ -682,7 +682,7 @@ int (*alloc_inode) (const struct inode *, unsigned long, uid_t); void (*free_block) (const struct inode *, unsigned long); void (*free_inode) (const struct inode *, unsigned long); - int (*transfer) (struct inode *, struct iattr *, char, uid_t); + int (*transfer) (struct dentry *, struct iattr *, uid_t); }; struct file_system_type { diff -u --recursive --new-file v2.3.27/linux/include/linux/ide.h linux/include/linux/ide.h --- v2.3.27/linux/include/linux/ide.h Sun Nov 7 16:37:34 1999 +++ linux/include/linux/ide.h Fri Nov 12 11:28:10 1999 @@ -227,8 +227,8 @@ unsigned set_multmode : 1; /* set multmode count */ unsigned set_tune : 1; /* tune interface for drive */ unsigned reserved : 4; /* unused */ - } b; - } special_t; + } b; +} special_t; typedef struct ide_drive_s { struct request *queue; /* request queue */ @@ -299,7 +299,7 @@ thresholds_t smart_thresholds; values_t smart_values; #endif - } ide_drive_t; +} ide_drive_t; /* * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive. @@ -317,11 +317,10 @@ ide_dma_off, ide_dma_off_quietly, ide_dma_test_irq, ide_dma_bad_drive, ide_dma_good_drive, ide_dma_lostirq, ide_dma_timeout - } ide_dma_action_t; +} ide_dma_action_t; typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *); - /* * An ide_tuneproc_t() is used to set the speed of an IDE interface * to a particular PIO mode. The "byte" parameter is used @@ -350,7 +349,7 @@ ide_qd6580, ide_umc8672, ide_ht6560b, ide_pdc4030, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives - } hwif_chipset_t; +} hwif_chipset_t; typedef struct ide_pci_devid_s { unsigned short vid; @@ -396,12 +395,20 @@ #if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */ #endif - } ide_hwif_t; +} ide_hwif_t; + + /* + * Status returned from various ide_ functions + */ +typedef enum { + ide_stopped, /* no drive operation was started */ + ide_started /* a drive operation was started, and a handler was set */ +} ide_startstop_t; /* * internal ide interrupt handler type */ -typedef void (ide_handler_t)(ide_drive_t *); +typedef ide_startstop_t (ide_handler_t)(ide_drive_t *); /* * when ide_timer_expiry fires, invoke a handler of this type @@ -410,9 +417,9 @@ typedef int (ide_expiry_t)(ide_drive_t *); typedef struct hwgroup_s { - spinlock_t spinlock; /* protects "busy" and "handler" */ ide_handler_t *handler;/* irq handler, if active */ - int busy; /* BOOL: protects all fields below */ + volatile int busy; /* BOOL: protects all fields below */ + int sleeping; /* BOOL: wake us up on timer expiry */ ide_drive_t *drive; /* current drive */ ide_hwif_t *hwif; /* ptr to current hwif in linked-list */ struct request *rq; /* current request */ @@ -420,7 +427,7 @@ struct request wrq; /* local copy of current write rq */ unsigned long poll_timeout; /* timeout value during long polls */ ide_expiry_t *expiry; /* queried upon timeouts */ - } ide_hwgroup_t; +} ide_hwgroup_t; /* * configurable drive settings @@ -504,7 +511,7 @@ #define IDE_SUBDRIVER_VERSION 1 typedef int (ide_cleanup_proc)(ide_drive_t *); -typedef void (ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long); +typedef ide_startstop_t (ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long); typedef void (ide_end_request_proc)(byte, ide_hwgroup_t *); typedef int (ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); typedef int (ide_open_proc)(struct inode *, struct file *, ide_drive_t *); @@ -512,7 +519,7 @@ typedef int (ide_check_media_change_proc)(ide_drive_t *); typedef void (ide_pre_reset_proc)(ide_drive_t *); typedef unsigned long (ide_capacity_proc)(ide_drive_t *); -typedef void (ide_special_proc)(ide_drive_t *); +typedef ide_startstop_t (ide_special_proc)(ide_drive_t *); typedef void (ide_setting_proc)(ide_drive_t *); typedef struct ide_driver_s { @@ -533,7 +540,7 @@ ide_capacity_proc *capacity; ide_special_proc *special; ide_proc_entry_t *proc; - } ide_driver_t; +} ide_driver_t; #define DRIVER(drive) ((ide_driver_t *)((drive)->driver)) @@ -600,9 +607,9 @@ /* * ide_error() takes action based on the error returned by the controller. - * The calling function must return afterwards, to restart the request. + * The caller should return immediately after invoking this. */ -void ide_error (ide_drive_t *drive, const char *msg, byte stat); +ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); /* * Issue a simple drive command @@ -622,10 +629,13 @@ * This routine busy-waits for the drive status to be not "busy". * It then checks the status for all of the "good" bits and none * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should return. - * + * cases return 1 after doing "*startstop = ide_error()", and the + * caller should return the updated value of "startstop" in this case. + * "startstop" is unchanged when the function returns 0; */ -int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout); +int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout); + +int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout); /* * This routine is called from the partition-table code in genhd.c @@ -647,7 +657,7 @@ * Start a reset operation for an IDE interface. * The caller should return immediately after invoking this. */ -void ide_do_reset (ide_drive_t *); +ide_startstop_t ide_do_reset (ide_drive_t *); /* * This function is intended to be used prior to invoking ide_do_drive_cmd(). @@ -657,12 +667,12 @@ /* * "action" parameter type for ide_do_drive_cmd() below. */ -typedef enum - {ide_wait, /* insert rq at end of list, and wait for it */ - ide_next, /* insert rq immediately after current request */ - ide_preempt, /* insert rq in front of current request */ - ide_end} /* insert rq at end of list, but don't wait for it */ - ide_action_t; +typedef enum { + ide_wait, /* insert rq at end of list, and wait for it */ + ide_next, /* insert rq immediately after current request */ + ide_preempt, /* insert rq in front of current request */ + ide_end /* insert rq at end of list, but don't wait for it */ +} ide_action_t; /* * This function issues a special IDE device request @@ -703,7 +713,11 @@ int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf); void ide_delay_50ms (void); + +int ide_driveid_update (ide_drive_t *drive); +int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature); int ide_config_drive_speed (ide_drive_t *drive, byte speed); +int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature); /* * ide_system_bus_speed() returns what we think is the system VESA/PCI @@ -717,7 +731,7 @@ * ide_multwrite() transfers a block of up to mcount sectors of data * to a drive as part of a disk multwrite operation. */ -void ide_multwrite (ide_drive_t *drive, unsigned int mcount); +int ide_multwrite (ide_drive_t *drive, unsigned int mcount); /* * ide_stall_queue() can be used by a drive to give excess bandwidth back @@ -812,6 +826,7 @@ #else /* CONFIG_BLK_DEV_OFFBOARD */ # define OFF_BOARD NEVER_BOARD #endif /* CONFIG_BLK_DEV_OFFBOARD */ + unsigned long ide_find_free_region (unsigned short size) __init; void ide_scan_pcibus (void) __init; #endif @@ -819,7 +834,7 @@ #define BAD_DMA_DRIVE 0 #define GOOD_DMA_DRIVE 1 int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func); -void ide_dma_intr (ide_drive_t *drive); +ide_startstop_t ide_dma_intr (ide_drive_t *drive); int check_drive_lists (ide_drive_t *drive, int good_bad); int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive); int ide_release_dma (ide_hwif_t *hwif); diff -u --recursive --new-file v2.3.27/linux/include/linux/isapnp.h linux/include/linux/isapnp.h --- v2.3.27/linux/include/linux/isapnp.h Thu Aug 26 13:05:41 1999 +++ linux/include/linux/isapnp.h Fri Nov 12 11:29:37 1999 @@ -23,6 +23,7 @@ #define LINUX_ISAPNP_H #include +#include /* * Configuration registers (TODO: change by specification) diff -u --recursive --new-file v2.3.27/linux/include/linux/mount.h linux/include/linux/mount.h --- v2.3.27/linux/include/linux/mount.h Tue Jul 6 10:18:15 1999 +++ linux/include/linux/mount.h Fri Nov 12 04:36:13 1999 @@ -17,11 +17,12 @@ struct quota_mount_options { unsigned int flags; /* Flags for diskquotas on this device */ - struct semaphore semaphore; /* lock device while I/O in progress */ + struct semaphore dqio_sem; /* lock device while I/O in progress */ + struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ - char rsquash[MAXQUOTAS]; /* for quotas treat root as any other user */ + char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */ }; struct vfsmount diff -u --recursive --new-file v2.3.27/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h --- v2.3.27/linux/include/linux/pci_ids.h Sun Nov 7 16:37:34 1999 +++ linux/include/linux/pci_ids.h Fri Nov 12 10:12:11 1999 @@ -286,8 +286,10 @@ #define PCI_DEVICE_ID_SI_501 0x0406 #define PCI_DEVICE_ID_SI_496 0x0496 #define PCI_DEVICE_ID_SI_530 0x0530 +#define PCI_DEVICE_ID_SI_540 0x0540 #define PCI_DEVICE_ID_SI_601 0x0601 #define PCI_DEVICE_ID_SI_620 0x0620 +#define PCI_DEVICE_ID_SI_630 0x0630 #define PCI_DEVICE_ID_SI_5107 0x5107 #define PCI_DEVICE_ID_SI_5511 0x5511 #define PCI_DEVICE_ID_SI_5513 0x5513 diff -u --recursive --new-file v2.3.27/linux/include/linux/quota.h linux/include/linux/quota.h --- v2.3.27/linux/include/linux/quota.h Thu May 13 14:29:31 1999 +++ linux/include/linux/quota.h Fri Nov 12 04:36:13 1999 @@ -202,7 +202,7 @@ # /* nodep */ include __BEGIN_DECLS -int quotactl __P ((int, const char *, int, caddr_t)); +long quotactl __P ((int, const char *, int, caddr_t)); __END_DECLS #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.3.27/linux/include/linux/quotaops.h linux/include/linux/quotaops.h --- v2.3.27/linux/include/linux/quotaops.h Wed Aug 18 16:43:33 1999 +++ linux/include/linux/quotaops.h Fri Nov 12 11:28:02 1999 @@ -31,8 +31,8 @@ extern void dquot_free_block(const struct inode *inode, unsigned long number); extern void dquot_free_inode(const struct inode *inode, unsigned long number); -extern int dquot_transfer(struct inode *inode, struct iattr *iattr, - char direction, uid_t initiator); +extern int dquot_transfer(struct dentry *dentry, struct iattr *iattr, + uid_t initiator); /* * Operations supported for diskquotas. @@ -99,17 +99,11 @@ int error = -EDQUOT; if (dentry->d_inode->i_sb->dq_op) { - if (IS_QUOTAINIT(dentry->d_inode) == 0) - dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1); - if (dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 0, current->fsuid)) - goto out; - error = notify_change(dentry, iattr); - if (error) - dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 1, current->fsuid); + dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1); + error = dentry->d_inode->i_sb->dq_op->transfer(dentry, iattr, current->fsuid); } else { error = notify_change(dentry, iattr); } -out: return error; } diff -u --recursive --new-file v2.3.27/linux/include/net/ip.h linux/include/net/ip.h --- v2.3.27/linux/include/net/ip.h Fri Oct 22 13:21:55 1999 +++ linux/include/net/ip.h Fri Nov 12 11:29:18 1999 @@ -22,7 +22,7 @@ #ifndef _IP_H #define _IP_H - +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/include/pcmcia/bus_ops.h linux/include/pcmcia/bus_ops.h --- v2.3.27/linux/include/pcmcia/bus_ops.h Thu Nov 11 20:11:54 1999 +++ linux/include/pcmcia/bus_ops.h Fri Nov 12 04:29:47 1999 @@ -30,6 +30,8 @@ #ifndef _LINUX_BUS_OPS_H #define _LINUX_BUS_OPS_H +#include + #ifdef CONFIG_VIRTUAL_BUS typedef struct bus_operations { diff -u --recursive --new-file v2.3.27/linux/mm/bootmem.c linux/mm/bootmem.c --- v2.3.27/linux/mm/bootmem.c Sun Nov 7 16:37:34 1999 +++ linux/mm/bootmem.c Fri Nov 12 04:29:47 1999 @@ -8,7 +8,6 @@ * system memory and memory holes as well. */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/mm/highmem.c linux/mm/highmem.c --- v2.3.27/linux/mm/highmem.c Thu Nov 11 20:11:55 1999 +++ linux/mm/highmem.c Fri Nov 12 04:29:47 1999 @@ -16,6 +16,7 @@ * Copyright (C) 1999 Ingo Molnar */ +#include #include #include #include @@ -269,9 +270,9 @@ unsigned long vto; p_to = to->b_page; - vto = kmap_atomic(p_to, KM_BOUNCE_WRITE); + vto = kmap_atomic(p_to, KM_BOUNCE_READ); memcpy((char *)vto + bh_offset(to), from->b_data, to->b_size); - kunmap_atomic(vto, KM_BOUNCE_WRITE); + kunmap_atomic(vto, KM_BOUNCE_READ); } static inline void bounce_end_io (struct buffer_head *bh, int uptodate) diff -u --recursive --new-file v2.3.27/linux/net/802/fc.c linux/net/802/fc.c --- v2.3.27/linux/net/802/fc.c Sat Oct 9 11:47:50 1999 +++ linux/net/802/fc.c Fri Nov 12 04:29:47 1999 @@ -10,6 +10,7 @@ * v 1.0 03/22/99 */ +#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/net/bridge/br.c linux/net/bridge/br.c --- v2.3.27/linux/net/bridge/br.c Mon Nov 1 13:56:27 1999 +++ linux/net/bridge/br.c Fri Nov 12 04:29:47 1999 @@ -52,7 +52,6 @@ * */ -#include #include #include #include diff -u --recursive --new-file v2.3.27/linux/net/irda/irproc.c linux/net/irda/irproc.c --- v2.3.27/linux/net/irda/irproc.c Thu Nov 11 20:11:56 1999 +++ linux/net/irda/irproc.c Fri Nov 12 04:40:46 1999 @@ -25,6 +25,7 @@ #include #include +#define __NO_VERSION__ #include #include diff -u --recursive --new-file v2.3.27/linux/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c --- v2.3.27/linux/net/sunrpc/sysctl.c Thu Nov 11 20:11:56 1999 +++ linux/net/sunrpc/sysctl.c Fri Nov 12 04:40:46 1999 @@ -14,6 +14,7 @@ #include #include #include +#define __NO_VERSION__ #include #include