From 452e9f81eb5261ec8eb740cb3f8a25d18d45c412 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 11 Nov 2002 01:06:00 +0100 Subject: [ARM] makefile cleanup Added prerequisite FORCE in several rules, now kbuild build a kernel even the second time you try. Corrected several errors to avoid errornous rebuild of targets in arch/arm Lot's of trivial clean-up --- arch/arm/Makefile | 186 ++++++++++++++------------------------ arch/arm/boot/Makefile | 156 +++++++++++--------------------- arch/arm/boot/bootp/Makefile | 4 - arch/arm/boot/compressed/Makefile | 24 ++--- arch/arm/tools/Makefile | 5 +- 5 files changed, 131 insertions(+), 244 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1eab6ab76d79..ba4f87eef389 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -34,14 +34,12 @@ apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 # Note that GCC is lame - it doesn't numerically define an # architecture version macro, but instead defines a whole # series of macros. -arch-y := arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5 arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mxscale #-march=armv5te # This selects how we optimise for the processor. -tune-y := tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610 tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710 tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi @@ -58,123 +56,67 @@ CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa, CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu +#Default value +DATAADDR := . + ifeq ($(CONFIG_CPU_26),y) PROCESSOR := armo HEAD := arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o LDFLAGS_BLOB += --oformat elf26-littlearm ifeq ($(CONFIG_ROM_KERNEL),y) - DATAADDR = 0x02080000 - TEXTADDR = 0x03800000 + DATAADDR := 0x02080000 + textaddr-y := 0x03800000 else - TEXTADDR = 0x02080000 + textaddr-y := 0x02080000 endif endif ifeq ($(CONFIG_CPU_32),y) -PROCESSOR = armv +PROCESSOR := armv HEAD := arch/arm/kernel/head.o arch/arm/kernel/init_task.o -TEXTADDR = 0xC0008000 LDFLAGS_BLOB += --oformat elf32-littlearm -endif - -ifeq ($(CONFIG_ARCH_ARCA5K),y) -MACHINE = arc -endif - -ifeq ($(CONFIG_ARCH_RPC),y) -MACHINE = rpc -endif - -ifeq ($(CONFIG_ARCH_EBSA110),y) -MACHINE = ebsa110 -endif - -ifeq ($(CONFIG_ARCH_CLPS7500),y) -MACHINE = clps7500 -INCDIR = cl7500 -endif - -ifeq ($(CONFIG_FOOTBRIDGE),y) -MACHINE = footbridge -INCDIR = ebsa285 -endif - -ifeq ($(CONFIG_ARCH_CO285),y) -TEXTADDR = 0x60008000 -MACHINE = footbridge -INCDIR = ebsa285 -endif - -ifeq ($(CONFIG_ARCH_FTVPCI),y) -MACHINE = ftvpci -INCDIR = nexuspci -endif - -ifeq ($(CONFIG_ARCH_TBOX),y) -MACHINE = tbox -endif - -ifeq ($(CONFIG_ARCH_SHARK),y) -MACHINE = shark -endif - +textaddr-y := 0xC0008000 +endif + + machine-$(CONFIG_ARCH_ARCA5K) := arc + machine-$(CONFIG_ARCH_RPC) := rpc + machine-$(CONFIG_ARCH_EBSA110) := ebsa110 + machine-$(CONFIG_ARCH_CLPS7500) := clps7500 + incdir-$(CONFIG_ARCH_CLPS7500) := cl7500 + machine-$(CONFIG_FOOTBRIDGE) := footbridge + incdir-$(CONFIG_FOOTBRIDGE) := ebsa285 +textaddr-$(CONFIG_ARCH_CO285) := 0x60008000 + machine-$(CONFIG_ARCH_CO285) := footbridge + incdir-$(CONFIG_ARCH_CO285) := ebsa285 + machine-$(CONFIG_ARCH_FTVPCI) := ftvpci + incdir-$(CONFIG_ARCH_FTVPCI) := nexuspci + machine-$(CONFIG_ARCH_TBOX) := tbox + machine-$(CONFIG_ARCH_SHARK) := shark + machine-$(CONFIG_ARCH_SA1100) := sa1100 ifeq ($(CONFIG_ARCH_SA1100),y) -ifeq ($(CONFIG_SA1111),y) # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory -TEXTADDR = 0xc0208000 -endif -MACHINE = sa1100 -endif - -ifeq ($(CONFIG_ARCH_PXA),y) -MACHINE = pxa -endif - -ifeq ($(CONFIG_ARCH_L7200),y) -MACHINE = l7200 -endif - -ifeq ($(CONFIG_ARCH_INTEGRATOR),y) -MACHINE = integrator -endif - -ifeq ($(CONFIG_ARCH_CAMELOT),y) -MACHINE = epxa10db -endif - -ifeq ($(CONFIG_ARCH_CLPS711X),y) -TEXTADDR = 0xc0028000 -MACHINE = clps711x -endif - -ifeq ($(CONFIG_ARCH_FORTUNET),y) -TEXTADDR = 0xc0008000 -endif - -ifeq ($(CONFIG_ARCH_ANAKIN),y) -MACHINE = anakin -endif - -ifeq ($(CONFIG_ARCH_IOP310),y) -MACHINE = iop310 -endif - -ifeq ($(CONFIG_ARCH_ADIFCC),y) -MACHINE = adifcc -endif - +textaddr-$(CONFIG_SA1111) := 0xc0208000 +endif + machine-$(CONFIG_ARCH_PXA) := pxa + machine-$(CONFIG_ARCH_L7200) := l7200 + machine-$(CONFIG_ARCH_INTEGRATOR) := integrator + machine-$(CONFIG_ARCH_CAMELOT) := epxa10db +textaddr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 + machine-$(CONFIG_ARCH_CLPS711X) := clps711x +textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 + machine-$(CONFIG_ARCH_ANAKIN) := anakin + machine-$(CONFIG_ARCH_IOP310) := iop310 + machine-$(CONFIG_ARCH_ADIFCC) := adifcc + +MACHINE := $(machine-y) +TEXTADDR := $(textaddr-y) +ifeq ($(incdir-y),) +incdir-y := $(MACHINE) +endif +INCDIR := $(incdir-y) + export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT -# Only set INCDIR if its not already defined above -# Grr, ?= doesn't work as all the other assignment operators do. Make bug? -ifeq ($(origin INCDIR), undefined) -INCDIR :=$(MACHINE) -endif - -ifeq ($(origin DATAADDR), undefined) -DATAADDR := . -endif - # Do we have FASTFPE? FASTFPE :=arch/arm/fastfpe ifeq ($(FASTFPE),$(wildcard $(FASTFPE))) @@ -194,7 +136,10 @@ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ libs-y += arch/arm/lib/ -makeboot = $(call descend,arch/arm/boot,$(1)) +# Default target when executing plain make +all: zImage + +makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/arm/boot $(1) # Update machine arch and proc symlinks if something which affects # them changed. We use .arch and .proc to indicate when they were @@ -217,13 +162,17 @@ prepare: maketools .PHONY: maketools FORCE maketools: include/asm-arm/.arch include/asm-arm/.proc \ include/asm-arm/constants.h include/linux/version.h FORCE - +@$(call descend,arch/arm/tools, include/asm-arm/mach-types.h) + $(Q)$(MAKE) -f scripts/Makefile.build obj=arch/arm/tools include/asm-arm/mach-types.h + +# Convert bzImage to zImage +bzImage: vmlinux + $(call makeboot,arch/arm/boot/zImage) zImage Image bootpImage: vmlinux - +@$(call makeboot,arch/arm/boot/$@) + $(call makeboot,arch/arm/boot/$@) -bzImage zinstall install: vmlinux - +@$(call makeboot,$@) +zinstall install: vmlinux + $(call makeboot,$@) MRPROPER_FILES += \ include/asm-arm/arch include/asm-arm/.arch \ @@ -233,15 +182,15 @@ MRPROPER_FILES += \ # We use MRPROPER_FILES and CLEAN_FILES now archmrproper: -archclean: FORCE - +@$(call makeboot,clean) +archclean: + $(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/arm/boot # My testing targets (that short circuit a few dependencies) -zImg:; +@$(call makeboot, zImage) -Img:; +@$(call makeboot, Image) -i:; +@$(call makeboot, install) -zi:; +@$(call makeboot, zinstall) -bp:; +@$(call makeboot, bootpImage) +zImg:; $(call makeboot, arch/arm/boot/zImage) +Img:; $(call makeboot, arch/arm/boot/Image) +bp:; $(call makeboot, arch/arm/boot/bootpImage) +i:; $(call makeboot, install) +zi:; $(call makeboot, zinstall) # # Configuration targets. Use these to select a @@ -261,10 +210,9 @@ bp:; +@$(call makeboot, bootpImage) arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/config/MARKER + @: -include/asm-$(ARCH)/constants.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s - @$(generate-asm-offsets.h) < $< > $@ - -include/asm-$(ARCH)/constants.h: include/asm-$(ARCH)/constants.h.tmp +include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s @echo -n ' Generating $@' + @$(generate-asm-offsets.h) < $< > $@.tmp @$(update-if-changed) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 6c5a970afb58..61eeee5c544f 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -13,132 +13,81 @@ # PARAMS_PHYS must be with 4MB of ZRELADDR # INITRD_PHYS must be in RAM -ifeq ($(CONFIG_CPU_26),y) -ZRELADDR = 0x02080000 -PARAMS_PHYS = 0x0207c000 -INITRD_PHYS = 0x02180000 -endif - -ifeq ($(CONFIG_ARCH_RPC),y) -ZRELADDR = 0x10008000 -PARAMS_PHYS = 0x10000100 -INITRD_PHYS = 0x18000000 -endif - -ifeq ($(CONFIG_ARCH_CLPS7500),y) -ZRELADDR = 0x10008000 -endif - -ifeq ($(CONFIG_ARCH_EBSA110),y) -ZRELADDR = 0x00008000 -PARAMS_PHYS = 0x00000400 -INITRD_PHYS = 0x00800000 -endif - -ifeq ($(CONFIG_ARCH_SHARK),y) -ZTEXTADDR = 0x08508000 -ZRELADDR = 0x08008000 -endif - -ifeq ($(CONFIG_FOOTBRIDGE),y) -ZRELADDR = 0x00008000 -PARAMS_PHYS = 0x00000100 -INITRD_PHYS = 0x00800000 -endif - -ifeq ($(CONFIG_ARCH_INTEGRATOR),y) -ZRELADDR = 0x00008000 -PARAMS_PHYS = 0x00000100 -INITRD_PHYS = 0x00800000 -endif - -ifeq ($(CONFIG_ARCH_CAMELOT),y) -ZRELADDR = 0x00008000 -endif - -ifeq ($(CONFIG_ARCH_NEXUSPCI),y) -ZRELADDR = 0x40008000 -endif - -ifeq ($(CONFIG_ARCH_L7200),y) -ZRELADDR = 0xf0008000 -endif - + zreladdr-$(CONFIG_CPU_26) := 0x02080000 +params_phys-$(CONFIG_CPU_26) := 0x0207c000 +initrd_phys-$(CONFIG_CPU_26) := 0x02180000 + zreladdr-$(CONFIG_ARCH_RPC) := 0x10008000 +params_phys-$(CONFIG_ARCH_RPC) := 0x10000100 +initrd_phys-$(CONFIG_ARCH_RPC) := 0x18000000 + zreladdr-$(CONFIG_ARCH_CLPS7500) := 0x10008000 + zreladdr-$(CONFIG_ARCH_CLPS7500) := 0x10008000 + zreladdr-$(CONFIG_ARCH_EBSA110) := 0x00008000 +params_phys-$(CONFIG_ARCH_EBSA110) := 0x00000400 +initrd_phys-$(CONFIG_ARCH_EBSA110) := 0x00800000 + ztextaddr-$(CONFIG_ARCH_SHARK) := 0x08508000 + zreladdr-$(CONFIG_ARCH_SHARK) := 0x08008000 + zreladdr-$(CONFIG_FOOTBRIDGE) := 0x00008000 +params_phys-$(CONFIG_FOOTBRIDGE) := 0x00000100 +initrd_phys-$(CONFIG_FOOTBRIDGE) := 0x00800000 + zreladdr-$(CONFIG_ARCH_INTEGRATOR) := 0x00008000 +params_phys-$(CONFIG_ARCH_INTEGRATOR) := 0x00000100 +initrd_phys-$(CONFIG_ARCH_INTEGRATOR) := 0x00800000 + zreladdr-$(CONFIG_ARCH_CAMELOT) := 0x00008000 + zreladdr-$(CONFIG_ARCH_NEXUSPCI) := 0x40008000 + zreladdr-$(CONFIG_ARCH_L7200) := 0xf0008000 # The standard locations for stuff on CLPS711x type processors -ifeq ($(CONFIG_ARCH_CLPS711X),y) -ZRELADDR = 0xc0028000 -PARAMS_PHYS = 0xc0000100 -endif - + zreladdr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 +params_phys-$(CONFIG_ARCH_CLPS711X) := 0xc0000100 # Should probably have some agreement on these... -ifeq ($(CONFIG_ARCH_P720T),y) -INITRD_PHYS = 0xc0400000 -endif -ifeq ($(CONFIG_ARCH_CDB89712),y) -INITRD_PHYS = 0x00700000 -endif - +initrd_phys-$(CONFIG_ARCH_P720T) := 0xc0400000 +initrd_phys-$(CONFIG_ARCH_CDB89712) := 0x00700000 + zreladdr-$(CONFIG_ARCH_SA1100) := 0xc0008000 ifeq ($(CONFIG_ARCH_SA1100),y) -ZRELADDR = 0xc0008000 -# No defconfig file to move this into... -#ifeq ($(CONFIG_SA1100_YOPY),y) -# ZTEXTADDR = 0x00080000 -# ZBSSADDR = 0xc0200000 -#endif -ifeq ($(CONFIG_SA1111),y) - ZRELADDR = 0xc0208000 -endif -endif - -ifeq ($(CONFIG_ARCH_PXA),y) -ZRELADDR = 0xa0008000 -endif - -ifeq ($(CONFIG_ARCH_ANAKIN),y) -ZRELADDR = 0x20008000 -endif - -ifeq ($(CONFIG_ARCH_IQ80310),y) -ZRELADDR = 0xa0008000 -endif - -ifeq ($(CONFIG_ARCH_ADIFCC),y) -ZRELADDR = 0xc0008000 + zreladdr-$(CONFIG_SA1111) := 0xc0208000 endif + zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000 + zreladdr-$(CONFIG_ARCH_ANAKIN) := 0x20008000 + zreladdr-$(CONFIG_ARCH_IQ80310) := 0xa0008000 + zreladdr-$(CONFIG_ARCH_ADIFCC) := 0xc0008000 +ZRELADDR := $(zreladdr-y) +ZTEXTADDR := $(ztextaddr-y) +PARAMS_PHYS := $(params_phys-y) +INITRD_PHYS := $(initrd_phys-y) # # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly # from ROM or Flash must define ZTEXTADDR (preferably via the config) -# +# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK ifeq ($(CONFIG_ZBOOT_ROM),y) -ZTEXTADDR =$(CONFIG_ZBOOT_ROM_TEXT) -ZBSSADDR =$(CONFIG_ZBOOT_ROM_BSS) +ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) +ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) else -ZTEXTADDR =0 -ZBSSADDR =ALIGN(4) +ZTEXTADDR := 0 +ZBSSADDR := ALIGN(4) endif export ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS -include $(TOPDIR)/Rules.make +EXTRA_TARGETS := Image zImage bootpImage $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) - -bzImage: $(obj)/zImage + @echo ' Kernel: $@ is ready' $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready' $(obj)/bootpImage: $(obj)/bootp/bootp FORCE $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready' $(obj)/compressed/vmlinux: vmlinux FORCE - +@$(call descend,arch/arm/boot/compressed, $(obj)/compressed/vmlinux) + $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed $@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE - +@$(call descend,arch/arm/boot/bootp, $(obj)/bootp/bootp) + $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed $@ .PHONY: initrd initrd: @@ -157,19 +106,16 @@ zinstall: $(obj)/zImage $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \ $(obj)/zImage System.map "$(INSTALL_PATH)" -clean: - $(RM) $(addprefix $(obj)/,Image zImage bootpImage) - +@$(call descend,arch/arm/boot/bootp, clean) - +@$(call descend,arch/arm/boot/compressed, clean) +clean-files := $(addprefix $(obj)/,Image zImage bootpImage) +subdir- := bootp compressed archhelp: - @echo '* bzImage/zImage- Compressed kernel image (arch/$(ARCH)/boot/zImage)' + @echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' @echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' @echo ' bootpImage - Combined zImage and initial RAM disk' + @echo ' initrd - Create an initial image' @echo ' install - Install uncompressed kernel' @echo ' zinstall - Install compressed kernel' @echo ' Install using (your) ~/bin/installkernel or' @echo ' (distribution) /sbin/installkernel or' @echo ' install to $$(INSTALL_PATH) and run lilo' - - diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile index b4304dc33d55..f24cbc2be4ac 100644 --- a/arch/arm/boot/bootp/Makefile +++ b/arch/arm/boot/bootp/Makefile @@ -9,8 +9,6 @@ ZLDFLAGS =-p -X -T $(obj)/bootp.lds \ EXTRA_TARGETS := bootp -include $(TOPDIR)/Rules.make - # Note that bootp.lds picks up kernel.o and initrd.o $(obj)/bootp: $(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds) $(LD) $(ZLDFLAGS) -o $@ $(obj)/init.o @@ -22,5 +20,3 @@ $(obj)/initrd.o: $(INITRD) $(LD) -r -s -o $@ -b binary $(INITRD) .PHONY: $(INITRD) $(ZSYSTEM) - -clean:; $(RM) $(obj)/bootp diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 2afc113f2fbe..4b34de447ecf 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -63,28 +63,30 @@ ifeq ($(CONFIG_CPU_XSCALE),y) OBJS += head-xscale.o endif -SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;\ -s/BSS_START/$(ZBSSADDR)/;s#OBJ#$(obj)# +SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/ -EXTRA_TARGETS := vmlinux piggy.o font.o head.o $(OBJS) +EXTRA_TARGETS := vmlinux vmlinux.lds piggy piggy.gz\ + piggy.o font.o head.o $(OBJS) EXTRA_CFLAGS := $(CFLAGS_BOOT) -fpic EXTRA_AFLAGS := -traditional -include $(TOPDIR)/Rules.make - LDFLAGS_vmlinux := -p -X \ $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \ - $(addprefix $(obj)/, $(OBJS)) + $(addprefix $(obj)/, $(OBJS)) FORCE $(call if_changed,ld) + @: + +$(obj)/piggy: vmlinux FORCE + $(call if_changed,objcopy) -$(obj)/piggy: vmlinux; $(call if_changed,objcopy) -$(obj)/piggy.gz: $(obj)/piggy; $(call if_changed,gzip) +$(obj)/piggy.gz: $(obj)/piggy FORCE + $(call if_changed,gzip) LDFLAGS_piggy.o := -r -b binary -$(obj)/piggy.o: $(obj)/piggy.gz +$(obj)/piggy.o: $(obj)/piggy.gz FORCE $(call if_changed,ld) CFLAGS_font.o := -Dstatic= @@ -93,9 +95,7 @@ $(obj)/font.o: $(FONTC) $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config @sed "$(SEDFLAGS)" < $< > $@ -.PHONY: clean -clean: - rm -f $(addprefix $(obj)/,vmlinux core piggy* vmlinux.lds) +clean-files := $(addprefix $(obj)/,vmlinux piggy* vmlinux.lds) $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile index 69e89827a523..1c8014bdeb10 100644 --- a/arch/arm/tools/Makefile +++ b/arch/arm/tools/Makefile @@ -4,9 +4,6 @@ # Copyright (C) 2001 Russell King # -include $(TOPDIR)/Rules.make - include/asm-arm/mach-types.h: $(obj)/mach-types $(obj)/gen-mach-types @echo ' Generating $@' - @awk -f $(obj)/gen-mach-types $(obj)/mach-types > $@ - + @$(AWK) -f $(obj)/gen-mach-types $(obj)/mach-types > $@ -- cgit v1.2.3 From 8abc9ec22023383c7d16989ff6d6d24664e1cc1b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Nov 2002 21:43:01 -0800 Subject: Add forgotten system call number for set_tid_address() --- include/asm-i386/unistd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 181d009c30c1..794068cb7c7f 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -262,6 +262,7 @@ #define __NR_sys_epoll_ctl 255 #define __NR_sys_epoll_wait 256 #define __NR_remap_file_pages 257 +#define __NR_set_tid_address 258 /* user-visible error numbers are in the range -1 - -124: see */ -- cgit v1.2.3 From d00819951546acddaece9b76f7124db8c70e95eb Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Sun, 17 Nov 2002 06:32:15 -0500 Subject: module.c: allow modules to enter themselves during mod init --- kernel/module.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 668406fa22cd..9b8212cd32e1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1058,6 +1058,15 @@ sys_init_module(void *umod, list_add(&mod->extable.list, &extables); spin_unlock_irq(&modlist_lock); + /* Note, setting the mod->live to 1 here is safe because we haven't + * linked the module into the system's kernel symbol table yet, + * which means that the only way any other kernel code can call + * into this module right now is if this module hands out entry + * pointers to the other code. We assume that no module hands out + * entry pointers to the rest of the kernel unless it is ready to + * have them used. + */ + mod->live = 1; /* Start the module */ ret = mod->init ? mod->init() : 0; if (ret < 0) { @@ -1070,9 +1079,10 @@ sys_init_module(void *umod, /* Mark it "live" so that they can force deletion later, and we don't keep getting woken on every decrement. */ - mod->live = 1; - } else + } else { + mod->live = 0; free_module(mod); + } up(&module_mutex); return ret; } @@ -1087,7 +1097,6 @@ sys_init_module(void *umod, mod->module_init = NULL; /* All ok! */ - mod->live = 1; up(&module_mutex); return 0; } -- cgit v1.2.3 From dceeb5a959f09686d8ee59c0855a0e62cf4d9ca8 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Sun, 17 Nov 2002 06:41:15 -0500 Subject: pci/setup-bus.c: Fix compile bustage from pci header cleanup --- drivers/pci/setup-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index adc5ed2942f5..52248c5e2bf5 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -105,7 +105,7 @@ pci_setup_bridge(struct pci_bus *bus) pcibios_fixup_pbus_ranges(bus, &ranges); DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n", - bus->number, bridge->name)); + bus->number, bridge->dev.name)); /* Set up the top and bottom of the PCI I/O segment for this bus. */ if (bus->resource[0]->flags & IORESOURCE_IO) { -- cgit v1.2.3 From d368d69f7e25dc9233d33f0c5021e757138dedc3 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Sat, 16 Nov 2002 22:06:03 -0800 Subject: [PATCH] drivers/char/raw.c Missing due to header file cleanups. --- drivers/char/raw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 0b79a7605bb5..3cdd71e836d0 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -15,6 +15,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From 35abeacb11d12a7ad4c3c62c9ee261dfb46dca6e Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Sat, 16 Nov 2002 22:06:09 -0800 Subject: [PATCH] fs/autofs/dirhash.c fs/autofs/dirhash.c needs mount.h for mntget. I've added the #include into the central header file, it seems the author wants one central header for all .c files in fs/autofs --- fs/autofs/autofs_i.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index b448e1f5a32f..67365387c9ae 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef DEBUG -- cgit v1.2.3 From ea44360700f8909f41fa1c2e5d0ba9c5f3797f50 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 16 Nov 2002 22:10:10 -0800 Subject: [PATCH] More rpc cleanup... Don't share a routing for xdr_encode_mon/umon. What we really want to do is split the XDR routine into one which does SM_MON encodes, and the other which does SM_UNMON. Remove some unused "void" encoders / decoders to avoid compiler warnings. --- fs/lockd/mon.c | 41 ++++++++++++++++++++++++++--------------- fs/lockd/xdr.c | 9 ++------- fs/lockd/xdr4.c | 9 ++------- fs/nfs/nfs2xdr.c | 21 --------------------- 4 files changed, 30 insertions(+), 50 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 4b916a21da80..9875e30ec594 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -135,16 +135,12 @@ out_destroy: * XDR functions for NSM. */ -static int -xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +static u32 * +xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) { char buffer[20]; u32 addr = ntohl(argp->addr); - dprintk("nsm: xdr_encode_mon(%08x, %d, %d, %d)\n", - htonl(argp->addr), htonl(argp->prog), - htonl(argp->vers), htonl(argp->proc)); - /* * Use the dotted-quad IP address of the remote host as * identifier. Linux statd always looks up the canonical @@ -155,19 +151,34 @@ xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) (addr>>8) & 0xff, (addr) & 0xff); if (!(p = xdr_encode_string(p, buffer)) || !(p = xdr_encode_string(p, system_utsname.nodename))) - return -EIO; + return ERR_PTR(-EIO); *p++ = htonl(argp->prog); *p++ = htonl(argp->vers); *p++ = htonl(argp->proc); - /* This is the private part. Needed only for SM_MON call */ - if (rqstp->rq_task->tk_msg.rpc_proc == SM_MON) { - *p++ = argp->addr; - *p++ = argp->vers; - *p++ = argp->proto; - *p++ = 0; - } + return p; +} + +static int +xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +{ + p = xdr_encode_common(rqstp, p, argp); + if (IS_ERR(p)) + return PTR_ERR(p); + *p++ = argp->addr; + *p++ = argp->vers; + *p++ = argp->proto; + *p++ = 0; + rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); + return 0; +} +static int +xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +{ + p = xdr_encode_common(rqstp, p, argp); + if (IS_ERR(p)) + return PTR_ERR(p); rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); return 0; } @@ -209,7 +220,7 @@ static struct rpc_procinfo nsm_procedures[] = { }, [SM_UNMON] = { .p_proc = SM_UNMON, - .p_encode = (kxdrproc_t) xdr_encode_mon, + .p_encode = (kxdrproc_t) xdr_encode_unmon, .p_decode = (kxdrproc_t) xdr_decode_stat, .p_bufsiz = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2, }, diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index be810e09def1..5d4b339df1e5 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -379,18 +379,13 @@ nlmsvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) /* * Now, the client side XDR functions */ -static int -nlmclt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr) -{ - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - +#ifdef NLMCLNT_SUPPORT_SHARES static int nlmclt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) { return 0; } +#endif static int nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 1191feef76bf..389aadcd9208 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -382,18 +382,13 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) /* * Now, the client side XDR functions */ -static int -nlm4clt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr) -{ - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - +#ifdef NLMCLNT_SUPPORT_SHARES static int nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) { return 0; } +#endif static int nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 2ebc61910a76..287716bd3f51 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -44,7 +44,6 @@ extern int nfs_stat_to_errno(int stat); #define NFS_info_sz 5 #define NFS_entry_sz NFS_filename_sz+3 -#define NFS_enc_void_sz 0 #define NFS_diropargs_sz NFS_fhandle_sz+NFS_filename_sz #define NFS_sattrargs_sz NFS_fhandle_sz+NFS_sattr_sz #define NFS_readlinkargs_sz NFS_fhandle_sz @@ -56,7 +55,6 @@ extern int nfs_stat_to_errno(int stat); #define NFS_symlinkargs_sz NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz #define NFS_readdirargs_sz NFS_fhandle_sz+2 -#define NFS_dec_void_sz 0 #define NFS_attrstat_sz 1+NFS_fattr_sz #define NFS_diropres_sz 1+NFS_fhandle_sz+NFS_fattr_sz #define NFS_readlinkres_sz 1 @@ -154,16 +152,6 @@ xdr_encode_sattr(u32 *p, struct iattr *attr) /* * NFS encode functions */ -/* - * Encode void argument - */ -static int -nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy) -{ - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - /* * Encode file handle argument * GETATTR, READLINK, STATFS @@ -462,15 +450,6 @@ nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) /* * NFS XDR decode functions */ -/* - * Decode void reply - */ -static int -nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy) -{ - return 0; -} - /* * Decode simple status reply */ -- cgit v1.2.3 From abff783f611ce23b2d9718e9010325083ba72b9e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 14:57:13 +0000 Subject: [ARM] Cleanup ARM configuration - FORCE_MAX_ZONEORDER should depend on SA1111, not a collection of machine specific configuration symbols. - RPCMOUSE is obsolete; replaced by MOUSE_RISCPC. --- arch/arm/Kconfig | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5db694197244..8e7a0b7c1de4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -222,7 +222,7 @@ config SA1111 config FORCE_MAX_ZONEORDER int - depends on ASSABET_NEPONSET || SA1100_ADSBITSY || SA1100_BADGE4 || SA1100_CONSUS || SA1100_GRAPHICSMASTER || SA1100_JORNADA720 || ARCH_LUBBOCK || SA1100_PFS168 || SA1100_PT_SYSTEM3 || SA1100_XP860 + depends on SA1111 default "9" comment "Processor Type" @@ -1043,11 +1043,6 @@ config KBDMOUSE depends on ARCH_ACORN && BUSMOUSE=y && !ARCH_RPC default y -config RPCMOUSE - bool - depends on ARCH_ACORN && BUSMOUSE=y && ARCH_RPC - default y - source "drivers/media/Kconfig" source "fs/Kconfig" -- cgit v1.2.3 From 2ca933958db23a0e519bf1cb5acf6b401a6c272f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 15:31:53 +0000 Subject: [ARM] Clean up includes Remove unnecessary references to various include files from arch/arm --- arch/arm/kernel/dma-isa.c | 1 - arch/arm/kernel/dma.c | 1 - arch/arm/kernel/irq.c | 3 +-- arch/arm/kernel/plx90x0.c | 1 - arch/arm/kernel/time-acorn.c | 1 - arch/arm/kernel/time.c | 1 - arch/arm/kernel/via82c505.c | 1 - arch/arm/mach-adifcc/arch.c | 2 +- arch/arm/mach-adifcc/irq.c | 1 - arch/arm/mach-anakin/irq.c | 1 - arch/arm/mach-arc/dma.c | 1 - arch/arm/mach-arc/oldlatches.c | 1 - arch/arm/mach-clps711x/autcpu12.c | 1 - arch/arm/mach-clps711x/cdb89712.c | 1 - arch/arm/mach-clps711x/dma.c | 8 -------- arch/arm/mach-clps711x/fortunet.c | 3 --- arch/arm/mach-clps711x/mm.c | 1 - arch/arm/mach-clps711x/p720t.c | 1 - arch/arm/mach-clps711x/time.c | 2 +- arch/arm/mach-ebsa110/time.c | 1 - arch/arm/mach-epxa10db/arch.c | 3 --- arch/arm/mach-epxa10db/dma.c | 8 -------- arch/arm/mach-epxa10db/time.c | 2 -- arch/arm/mach-footbridge/cats-hw.c | 1 - arch/arm/mach-footbridge/dc21285.c | 1 - arch/arm/mach-footbridge/dma.c | 1 - arch/arm/mach-footbridge/irq.c | 2 -- arch/arm/mach-footbridge/isa-irq.c | 1 - arch/arm/mach-footbridge/mm.c | 1 - arch/arm/mach-footbridge/netwinder-hw.c | 1 - arch/arm/mach-ftvpci/core.c | 1 - arch/arm/mach-integrator/arch.c | 2 -- arch/arm/mach-integrator/dma.c | 1 - arch/arm/mach-integrator/pci.c | 1 - arch/arm/mach-integrator/pci_v3.c | 1 - arch/arm/mach-integrator/time.c | 2 +- arch/arm/mach-iop310/arch.c | 2 +- arch/arm/mach-iop310/iop310-irq.c | 1 - arch/arm/mach-iop310/iop310-pci.c | 2 -- arch/arm/mach-iop310/iq80310-irq.c | 4 ---- arch/arm/mach-iop310/iq80310-time.c | 3 --- arch/arm/mach-iop310/xs80200-irq.c | 2 -- arch/arm/mach-pxa/dma.c | 1 - arch/arm/mach-pxa/idp.c | 2 -- arch/arm/mach-pxa/irq.c | 1 - arch/arm/mach-pxa/lubbock.c | 2 -- arch/arm/mach-pxa/pm.c | 1 - arch/arm/mach-rpc/dma.c | 1 - arch/arm/mach-sa1100/adsbitsy.c | 2 -- arch/arm/mach-sa1100/assabet.c | 1 - arch/arm/mach-sa1100/dma.c | 2 +- arch/arm/mach-sa1100/flexanet.c | 1 - arch/arm/mach-sa1100/graphicsclient.c | 2 -- arch/arm/mach-sa1100/graphicsmaster.c | 2 -- arch/arm/mach-sa1100/h3600.c | 1 - arch/arm/mach-sa1100/irq.c | 2 -- arch/arm/mach-sa1100/neponset.c | 2 -- arch/arm/mach-sa1100/pm.c | 2 -- arch/arm/mach-sa1100/sa1111.c | 2 -- arch/arm/mach-sa1100/stork.c | 1 - arch/arm/mach-sa1100/system3.c | 1 - arch/arm/mach-shark/dma.c | 3 --- arch/arm/mach-tbox/core.c | 1 - arch/arm/mm/alignment.c | 2 -- arch/arm/mm/init.c | 1 - arch/arm/mm/mm-armv.c | 1 - 66 files changed, 6 insertions(+), 107 deletions(-) diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 2125bb6a1282..d75e8a9923e7 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -16,7 +16,6 @@ * arch/arm/kernel/dma-ebsa285.c * Copyright (C) 1998 Phil Blundell */ -#include #include #include #include diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 6717f735136a..0e4b21e03427 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -13,7 +13,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 1fa4f5fb25f7..a7cd6b892ffa 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -661,7 +660,7 @@ unsigned int probe_irq_mask(unsigned long irqs) unsigned int mask = 0, i; spin_lock_irq(&irq_controller_lock); - for(i = 0; i < 16 && i < NR_IRQS; i++) + for (i = 0; i < 16 && i < NR_IRQS; i++) if (irq_desc[i].probing && irq_desc[i].triggered) mask |= 1 << i; spin_unlock_irq(&irq_controller_lock); diff --git a/arch/arm/kernel/plx90x0.c b/arch/arm/kernel/plx90x0.c index f843e12267ed..60d7d3566af4 100644 --- a/arch/arm/kernel/plx90x0.c +++ b/arch/arm/kernel/plx90x0.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/kernel/time-acorn.c b/arch/arm/kernel/time-acorn.c index eb637801c7a5..8772035bfc7f 100644 --- a/arch/arm/kernel/time-acorn.c +++ b/arch/arm/kernel/time-acorn.c @@ -12,7 +12,6 @@ * 10-Oct-1996 RMK Brought up to date with arch-sa110eval * 04-Dec-1997 RMK Updated for new arch/arm/time.c */ -#include #include #include diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 655b7ed1c8e0..2af6dbda06d5 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -18,7 +18,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c index 345b9b6c73da..a4ac16dbb756 100644 --- a/arch/arm/kernel/via82c505.c +++ b/arch/arm/kernel/via82c505.c @@ -1,5 +1,4 @@ #include -#include #include #include #include diff --git a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c index 9c715a9635fd..bfc59556d9da 100644 --- a/arch/arm/mach-adifcc/arch.c +++ b/arch/arm/mach-adifcc/arch.c @@ -11,7 +11,7 @@ #include #include #include -#include + #include #include #include diff --git a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c index e8e659a54ef4..29cd529832b8 100644 --- a/arch/arm/mach-adifcc/irq.c +++ b/arch/arm/mach-adifcc/irq.c @@ -13,7 +13,6 @@ * support for PCI though. */ #include -#include #include #include diff --git a/arch/arm/mach-anakin/irq.c b/arch/arm/mach-anakin/irq.c index 46cd97f56ff1..fcf335fadc58 100644 --- a/arch/arm/mach-anakin/irq.c +++ b/arch/arm/mach-anakin/irq.c @@ -12,7 +12,6 @@ */ #include -#include #include #include diff --git a/arch/arm/mach-arc/dma.c b/arch/arm/mach-arc/dma.c index a49785206265..43c5a8d35210 100644 --- a/arch/arm/mach-arc/dma.c +++ b/arch/arm/mach-arc/dma.c @@ -10,7 +10,6 @@ * DMA functions specific to Archimedes and A5000 architecture */ #include -#include #include #include diff --git a/arch/arm/mach-arc/oldlatches.c b/arch/arm/mach-arc/oldlatches.c index c7237c40db92..5f797e6eee14 100644 --- a/arch/arm/mach-arc/oldlatches.c +++ b/arch/arm/mach-arc/oldlatches.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c index c4c28fb1a1ae..1cb34fa33d23 100644 --- a/arch/arm/mach-clps711x/autcpu12.c +++ b/arch/arm/mach-clps711x/autcpu12.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c index 56083b9a5b08..d51668d267fa 100644 --- a/arch/arm/mach-clps711x/cdb89712.c +++ b/arch/arm/mach-clps711x/cdb89712.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-clps711x/dma.c b/arch/arm/mach-clps711x/dma.c index 90857e1d452b..af5a4de38eac 100644 --- a/arch/arm/mach-clps711x/dma.c +++ b/arch/arm/mach-clps711x/dma.c @@ -17,17 +17,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include #include -#include -#include #include -#include -#include - #include void __init arch_dma_init(dma_t *dma) diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index 8037ea85e489..31ea65434883 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -21,8 +21,6 @@ */ #include #include -#include -#include #include #include @@ -32,7 +30,6 @@ #include #include -#include extern void clps711x_map_io(void); extern void clps711x_init_irq(void); diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c index a61e9b05dfb8..8c7d11e0be78 100644 --- a/arch/arm/mach-clps711x/mm.c +++ b/arch/arm/mach-clps711x/mm.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index 4de13d3d0f5d..b99cccfb773b 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c index 30613131141c..caedd7b5bf23 100644 --- a/arch/arm/mach-clps711x/time.c +++ b/arch/arm/mach-clps711x/time.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#include #include #include diff --git a/arch/arm/mach-ebsa110/time.c b/arch/arm/mach-ebsa110/time.c index c842f06b0e2a..989ab98a8d97 100644 --- a/arch/arm/mach-ebsa110/time.c +++ b/arch/arm/mach-ebsa110/time.c @@ -7,7 +7,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c index f30d0176784e..71c2257dfd50 100644 --- a/arch/arm/mach-epxa10db/arch.c +++ b/arch/arm/mach-epxa10db/arch.c @@ -19,12 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include -#include #include #include -#include #include #include diff --git a/arch/arm/mach-epxa10db/dma.c b/arch/arm/mach-epxa10db/dma.c index 2edf62a11fe0..0151e9f1c066 100644 --- a/arch/arm/mach-epxa10db/dma.c +++ b/arch/arm/mach-epxa10db/dma.c @@ -18,17 +18,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include #include -#include -#include #include -#include -#include - #include void __init arch_dma_init(dma_t *dma) diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c index d4ca520e382f..0c8b9cf7c7b7 100644 --- a/arch/arm/mach-epxa10db/time.c +++ b/arch/arm/mach-epxa10db/time.c @@ -9,13 +9,11 @@ * published by the Free Software Foundation. */ #include -#include #include #include - extern int (*set_rtc)(void); static int epxa10db_set_rtc(void) diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 160b0307fa92..0aec69fb00ad 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -5,7 +5,6 @@ * * Copyright (C) 1998, 1999 Russell King, Phil Blundell */ -#include #include #include #include diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index cbe4ba754bdb..fb0ac649543f 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -8,7 +8,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c index 7cdbf92f1c83..a6b1396b0951 100644 --- a/arch/arm/mach-footbridge/dma.c +++ b/arch/arm/mach-footbridge/dma.c @@ -11,7 +11,6 @@ * ISA DMA controllers. */ #include -#include #include #include diff --git a/arch/arm/mach-footbridge/irq.c b/arch/arm/mach-footbridge/irq.c index df59f879d8fc..d4d2662ab040 100644 --- a/arch/arm/mach-footbridge/irq.c +++ b/arch/arm/mach-footbridge/irq.c @@ -14,9 +14,7 @@ * 26-Jan-1999 PJB Don't use IACK on CATS * 16-Mar-1999 RMK Added autodetect of ISA PICs */ -#include #include -#include #include #include diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index 6b70ecb14ab8..124e4ab8d97e 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -14,7 +14,6 @@ * 26-Jan-1999 PJB Don't use IACK on CATS * 16-Mar-1999 RMK Added autodetect of ISA PICs */ -#include #include #include #include diff --git a/arch/arm/mach-footbridge/mm.c b/arch/arm/mach-footbridge/mm.c index e9054bf77c2a..400932cfdead 100644 --- a/arch/arm/mach-footbridge/mm.c +++ b/arch/arm/mach-footbridge/mm.c @@ -11,7 +11,6 @@ */ #include #include -#include #include #include diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index 587fb687476d..c81775b1a42d 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -7,7 +7,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c index 5fec4ef21b68..ea6d5c34e87f 100644 --- a/arch/arm/mach-ftvpci/core.c +++ b/arch/arm/mach-ftvpci/core.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ #include -#include #include #include diff --git a/arch/arm/mach-integrator/arch.c b/arch/arm/mach-integrator/arch.c index be2ac9afcc96..0a1fd15cf64a 100644 --- a/arch/arm/mach-integrator/arch.c +++ b/arch/arm/mach-integrator/arch.c @@ -19,8 +19,6 @@ */ #include #include -#include -#include #include #include diff --git a/arch/arm/mach-integrator/dma.c b/arch/arm/mach-integrator/dma.c index a53feed419d2..aae6f23cd72b 100644 --- a/arch/arm/mach-integrator/dma.c +++ b/arch/arm/mach-integrator/dma.c @@ -18,7 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c index 0c23671a70e7..58683093b818 100644 --- a/arch/arm/mach-integrator/pci.c +++ b/arch/arm/mach-integrator/pci.c @@ -21,7 +21,6 @@ * * PCI functions for Integrator */ -#include #include #include #include diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index 7c87676a73d8..2abfa3b524d5 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -21,7 +21,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c index fc32a809d9f3..39606096fbd6 100644 --- a/arch/arm/mach-integrator/time.c +++ b/arch/arm/mach-integrator/time.c @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ #include -#include +#include #include #include diff --git a/arch/arm/mach-iop310/arch.c b/arch/arm/mach-iop310/arch.c index 9ff7a4c2963c..401ef090e50d 100644 --- a/arch/arm/mach-iop310/arch.c +++ b/arch/arm/mach-iop310/arch.c @@ -13,7 +13,7 @@ #include #include #include -#include + #include #include #include diff --git a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c index 653482d1191a..67639c9142cc 100644 --- a/arch/arm/mach-iop310/iop310-irq.c +++ b/arch/arm/mach-iop310/iop310-irq.c @@ -14,7 +14,6 @@ * */ #include -#include #include #include diff --git a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c index 50faa6fecfcd..d5585f12430c 100644 --- a/arch/arm/mach-iop310/iop310-pci.c +++ b/arch/arm/mach-iop310/iop310-pci.c @@ -11,10 +11,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include -#include #include #include #include diff --git a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c index e9ff595590e7..7fdd36e1c1f4 100644 --- a/arch/arm/mach-iop310/iq80310-irq.c +++ b/arch/arm/mach-iop310/iq80310-irq.c @@ -14,10 +14,6 @@ * Moved demux from asm to C - DS * Fixes for various revision boards - DS */ -#include -#include -#include -#include #include #include diff --git a/arch/arm/mach-iop310/iq80310-time.c b/arch/arm/mach-iop310/iq80310-time.c index 1151c6b3db28..42311bca889d 100644 --- a/arch/arm/mach-iop310/iq80310-time.c +++ b/arch/arm/mach-iop310/iq80310-time.c @@ -11,14 +11,11 @@ * published by the Free Software Foundation. * */ -#include -#include #include #include #include #include #include -#include #include #include diff --git a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c index 2d3af7c6b02e..d5d5784df8f8 100644 --- a/arch/arm/mach-iop310/xs80200-irq.c +++ b/arch/arm/mach-iop310/xs80200-irq.c @@ -11,8 +11,6 @@ * published by the Free Software Foundation. */ #include -#include -#include #include #include diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index e2c141ca9619..69ee386d94e6 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index e07988986b17..71b64a6d9fcc 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -17,9 +17,7 @@ #include #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 67fdf38f8e69..81c6e8a72496 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -14,7 +14,6 @@ #include #include -#include #include #include diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index c58183dc334d..336f55987d09 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -16,9 +16,7 @@ #include #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index a52714acfd8b..8e738ed14e12 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index e81acb720463..dab328a0d6ab 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -9,7 +9,6 @@ * * DMA functions specific to RiscPC architecture */ -#include #include #include #include diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c index d5eb9b677449..d677abeea697 100644 --- a/arch/arm/mach-sa1100/adsbitsy.c +++ b/arch/arm/mach-sa1100/adsbitsy.c @@ -11,8 +11,6 @@ */ #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d538b98d4284..6d775017ab7b 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c index 11e0121b1b84..8366f546a0d8 100644 --- a/arch/arm/mach-sa1100/dma.c +++ b/arch/arm/mach-sa1100/dma.c @@ -11,8 +11,8 @@ */ #include +#include #include -#include #include #include diff --git a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c index 3135f09aa12e..0a40c7831515 100644 --- a/arch/arm/mach-sa1100/flexanet.c +++ b/arch/arm/mach-sa1100/flexanet.c @@ -11,7 +11,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c index 9c69428bb048..eb420d53a93d 100644 --- a/arch/arm/mach-sa1100/graphicsclient.c +++ b/arch/arm/mach-sa1100/graphicsclient.c @@ -11,8 +11,6 @@ */ #include #include -#include -#include #include #include diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c index d3eddf63205e..db88613a49ce 100644 --- a/arch/arm/mach-sa1100/graphicsmaster.c +++ b/arch/arm/mach-sa1100/graphicsmaster.c @@ -9,8 +9,6 @@ */ #include #include -#include -#include #include #include diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 41e19e37d0c0..dd875ba0b559 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index c0440f8c8c37..46f3baf9cabf 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -11,8 +11,6 @@ */ #include #include -#include -#include #include #include diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 71c60c3c1467..23a681189b96 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -4,8 +4,6 @@ */ #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 76e0da5b973e..2e99c722be48 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c index 54a40462b2dc..3d2d93c6ea84 100644 --- a/arch/arm/mach-sa1100/sa1111.c +++ b/arch/arm/mach-sa1100/sa1111.c @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c index 703a513a94d0..0c34c9d61bb8 100644 --- a/arch/arm/mach-sa1100/stork.c +++ b/arch/arm/mach-sa1100/stork.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c index d0dc614b0b87..6e47c1cda8eb 100644 --- a/arch/arm/mach-sa1100/system3.c +++ b/arch/arm/mach-sa1100/system3.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c index 1a73aa9187ca..835989a02918 100644 --- a/arch/arm/mach-shark/dma.c +++ b/arch/arm/mach-shark/dma.c @@ -9,12 +9,9 @@ */ #include -#include #include #include -#include - #include void __init arch_dma_init(dma_t *dma) diff --git a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c index 64555b92d34c..e9099444b2c2 100644 --- a/arch/arm/mach-tbox/core.c +++ b/arch/arm/mach-tbox/core.c @@ -7,7 +7,6 @@ * Extra MM routines for the Tbox architecture */ #include -#include #include #include diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index db227d31264c..5c9ff8269e44 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -19,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ff3347e2669f..2775beae8d03 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -9,7 +9,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index a0bc8550cf08..b94b270f242c 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -9,7 +9,6 @@ * * Page table sludge for ARM v3 and v4 processor architectures. */ -#include #include #include #include -- cgit v1.2.3 From bd51d9ad6761f096a0c8a301432a5cf80af8cef9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 16:21:13 +0000 Subject: [ARM] Fix flush_dcache_page() Make flush_dcache_page() handle user space mappings correctly; with a VIVT cache, we need to make sure that any user space cache lines are coherent with the kernels view of the same page of memory. --- arch/arm/mm/fault-armv.c | 72 ++++++++++++++++++++++++++++++++------- arch/arm/mm/proc-syms.c | 4 ++- include/asm-arm/proc-armv/cache.h | 8 +---- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index f8ad035fdf01..940b75d75bb9 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -131,21 +131,22 @@ do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) * We take the easy way out of this problem - we make the * PTE uncacheable. However, we leave the write buffer on. */ -static void adjust_pte(struct vm_area_struct *vma, unsigned long address) +static int adjust_pte(struct vm_area_struct *vma, unsigned long address) { pgd_t *pgd; pmd_t *pmd; pte_t *pte, entry; + int ret = 0; pgd = pgd_offset(vma->vm_mm, address); if (pgd_none(*pgd)) - return; + goto no_pgd; if (pgd_bad(*pgd)) goto bad_pgd; pmd = pmd_offset(pgd, address); if (pmd_none(*pmd)) - return; + goto no_pmd; if (pmd_bad(*pmd)) goto bad_pmd; @@ -161,23 +162,64 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address) pte_val(entry) &= ~L_PTE_CACHEABLE; set_pte(pte, entry); flush_tlb_page(vma, address); + ret = 1; } pte_unmap(pte); - return; + return ret; bad_pgd: pgd_ERROR(*pgd); pgd_clear(pgd); - return; +no_pgd: + return 0; bad_pmd: pmd_ERROR(*pmd); pmd_clear(pmd); - return; +no_pmd: + return 0; +} + +void __flush_dcache_page(struct page *page) +{ + struct mm_struct *mm = current->active_mm; + struct list_head *l; + unsigned long kaddr = (unsigned long)page_address(page); + + cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0); + + if (!page->mapping) + return; + + /* + * With a VIVT cache, we need to also write back + * and invalidate any user data. + */ + list_for_each(l, &page->mapping->i_mmap_shared) { + struct vm_area_struct *mpnt; + unsigned long off; + + mpnt = list_entry(l, struct vm_area_struct, shared); + + /* + * If this VMA is not in our MM, we can ignore it. + */ + if (mpnt->vm_mm != mm) + continue; + + if (page->index < mpnt->vm_pgoff) + continue; + + off = page->index - mpnt->vm_pgoff; + if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + continue; + + flush_cache_page(mpnt, off); + } } static void -make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page) +make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) { struct list_head *l; struct mm_struct *mm = vma->vm_mm; @@ -213,14 +255,17 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page) if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) continue; + off = mpnt->vm_start + (off << PAGE_SHIFT); + /* * Ok, it is within mpnt. Fix it up. */ - adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); - aliases ++; + aliases += adjust_pte(mpnt, off); } if (aliases) adjust_pte(vma, addr); + else + flush_cache_page(vma, addr); } /* @@ -245,9 +290,12 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) return; page = pfn_to_page(pfn); if (page->mapping) { - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - __flush_dcache_page(page); + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); + unsigned long kaddr = (unsigned long)page_address(page); + + if (dirty) + cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0); - make_coherent(vma, addr, page); + make_coherent(vma, addr, page, dirty); } } diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index fe84d27a9681..ced3f8122b57 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mm/proc-syms.c * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,6 +15,8 @@ #include #include +EXPORT_SYMBOL(__flush_dcache_page); + #ifndef MULTI_CPU EXPORT_SYMBOL(cpu_cache_clean_invalidate_all); EXPORT_SYMBOL(cpu_cache_clean_invalidate_range); diff --git a/include/asm-arm/proc-armv/cache.h b/include/asm-arm/proc-armv/cache.h index fe678c2b0d7e..216987fe30ef 100644 --- a/include/asm-arm/proc-armv/cache.h +++ b/include/asm-arm/proc-armv/cache.h @@ -93,11 +93,7 @@ #define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \ !list_empty(&(map)->i_mmap_shared)) -static inline void __flush_dcache_page(struct page *page) -{ - unsigned long virt = (unsigned long)page_address(page); - cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0); -} +extern void __flush_dcache_page(struct page *); static inline void flush_dcache_page(struct page *page) { @@ -116,8 +112,6 @@ static inline void flush_dcache_page(struct page *page) */ #define flush_icache_page(vma,page) do { } while (0) -#define clean_dcache_entry(_s) cpu_dcache_clean_entry((unsigned long)(_s)) - /* * I cache coherency stuff. * -- cgit v1.2.3 From 8d2c59fd8bcc060969973d7fb2e3f657bae78ca3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 19:17:13 +0000 Subject: [ARM] Optimise set_pmd Since we store two hardware pte tables contiguously, a common operation is to set two pmd entries. Rather than call set_pmd() with the associated overhead twice, we set the two PMD entries, and then call cpu_flush_pmd() to perform any CPU specific handling. --- arch/arm/mm/mm-armv.c | 28 +++++++++++++++------------- arch/arm/mm/proc-arm1020.S | 8 +++----- arch/arm/mm/proc-arm6_7.S | 30 +++++------------------------- arch/arm/mm/proc-arm720.S | 10 +++------- arch/arm/mm/proc-arm920.S | 8 +++----- arch/arm/mm/proc-arm922.S | 8 +++----- arch/arm/mm/proc-arm926.S | 8 +++----- arch/arm/mm/proc-sa110.S | 12 +++++------- arch/arm/mm/proc-syms.c | 2 +- arch/arm/mm/proc-xscale.S | 8 +++----- include/asm-arm/proc-armv/pgalloc.h | 20 ++++++++++---------- include/asm-arm/proc-armv/pgtable.h | 11 ++++++----- 12 files changed, 60 insertions(+), 93 deletions(-) diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index b94b270f242c..33e0237223f9 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -165,14 +165,13 @@ free: static inline void alloc_init_section(unsigned long virt, unsigned long phys, int prot) { - pmd_t *pmdp, pmd; + pmd_t *pmdp; pmdp = pmd_offset(pgd_offset_k(virt), virt); if (virt & (1 << 20)) pmdp++; - pmd_val(pmd) = phys | prot; - set_pmd(pmdp, pmd); + set_pmd(pmdp, __pmd(phys | prot)); } /* @@ -185,19 +184,20 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot) static inline void alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot) { - pmd_t *pmdp, pmd; + pmd_t *pmdp; pte_t *ptep; pmdp = pmd_offset(pgd_offset_k(virt), virt); if (pmd_none(*pmdp)) { + unsigned long pmdval; ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); - pmd_val(pmd) = __pa(ptep) | prot_l1; - set_pmd(pmdp, pmd); - pmd_val(pmd) += 256 * sizeof(pte_t); - set_pmd(pmdp + 1, pmd); + pmdval = __pa(ptep) | prot_l1; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + cpu_flush_pmd(pmdp); } ptep = pte_offset_kernel(pmdp, virt); @@ -359,8 +359,9 @@ static void __init create_mapping(struct map_desc *md) */ void setup_mm_for_reboot(char mode) { + unsigned long pmdval; pgd_t *pgd; - pmd_t pmd; + pmd_t *pmd; int i; if (current->mm && current->mm->pgd) @@ -369,10 +370,11 @@ void setup_mm_for_reboot(char mode) pgd = init_mm.pgd; for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { - pmd_val(pmd) = (i << PGDIR_SHIFT) | - PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | - PMD_TYPE_SECT; - set_pmd(pmd_offset(pgd + i, i << PGDIR_SHIFT), pmd); + pmdval = (i << PGDIR_SHIFT) | + PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | + PMD_BIT4 | PMD_TYPE_SECT; + pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT); + set_pmd(pmd, __pmd(pmdval)); } } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index c07da1b6e873..9e936e435f18 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -365,17 +365,15 @@ ENTRY(cpu_arm1020_set_pgd) mov pc, lr /* - * cpu_arm1020_set_pmd(pmdp, pmd) + * cpu_arm1020_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_arm1020_set_pmd) - str r1, [r0] +ENTRY(cpu_arm1020_flush_pmd) #ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) @@ -515,7 +513,7 @@ arm1020_processor_functions: /* pgtable */ .word cpu_arm1020_set_pgd - .word cpu_arm1020_set_pmd + .word cpu_arm1020_flush_pmd .word cpu_arm1020_set_pte .size arm1020_processor_functions, . - arm1020_processor_functions diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index 1b1055d27614..0405e3b21603 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -234,34 +234,14 @@ ENTRY(cpu_arm7_set_pgd) mov pc, lr /* - * Function: arm6_set_pmd () + * Function: arm6_flush_pmd(pmdp) * * Params : r0 = Address to set - * : r1 = value to set - * - * Purpose : Set a PMD and flush it out of any WB cache - */ -ENTRY(cpu_arm6_set_pmd) - and r2, r1, #11 - teq r2, #1 - teqne r2, #9 - teqne r2, #10 - orreq r1, r1, #16 @ Updatable = 1 if Page table/Cacheable section - str r1, [r0] - mov pc, lr - -/* - * Function: arm7_set_pmd () - * - * Params : r0 = Address to set - * : r1 = value to set * * Purpose : Set a PMD and flush it out of any WB cache */ -ENTRY(cpu_arm7_set_pmd) - tst r1, #3 - orrne r1, r1, #16 @ Updatable bit is always set on ARM7 - str r1, [r0] +ENTRY(cpu_arm6_flush_pmd) +ENTRY(cpu_arm7_flush_pmd) mov pc, lr /* @@ -368,7 +348,7 @@ ENTRY(arm6_processor_functions) /* pgtable */ .word cpu_arm6_set_pgd - .word cpu_arm6_set_pmd + .word cpu_arm6_flush_pmd .word cpu_arm6_set_pte .size arm6_processor_functions, . - arm6_processor_functions @@ -402,7 +382,7 @@ ENTRY(arm7_processor_functions) /* pgtable */ .word cpu_arm7_set_pgd - .word cpu_arm7_set_pmd + .word cpu_arm7_flush_pmd .word cpu_arm7_set_pte .size arm7_processor_functions, . - arm7_processor_functions diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index ab4152a7ed39..f3396cbdd79a 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -115,17 +115,13 @@ ENTRY(cpu_arm720_set_pgd) mov pc, lr /* - * Function: arm720_set_pmd () + * Function: arm720_flush_pmd(pmdp) * * Params : r0 = Address to set - * : r1 = value to set * * Purpose : Set a PMD and flush it out of any WB cache */ -ENTRY(cpu_arm720_set_pmd) - tst r1, #3 - orrne r1, r1, #16 @ Updatable bit is - str r1, [r0] @ always set on ARM720 +ENTRY(cpu_arm720_flush_pmd) mov pc, lr /* @@ -222,7 +218,7 @@ ENTRY(arm720_processor_functions) /* pgtable */ .word cpu_arm720_set_pgd - .word cpu_arm720_set_pmd + .word cpu_arm720_flush_pmd .word cpu_arm720_set_pte .size arm720_processor_functions, . - arm720_processor_functions diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 59ebba740113..46206021205e 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -368,17 +368,15 @@ ENTRY(cpu_arm920_set_pgd) mov pc, lr /* - * cpu_arm920_set_pmd(pmdp, pmd) + * cpu_arm920_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_arm920_set_pmd) - str r1, [r0] +ENTRY(cpu_arm920_flush_pmd) mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr @@ -503,7 +501,7 @@ arm920_processor_functions: /* pgtable */ .word cpu_arm920_set_pgd - .word cpu_arm920_set_pmd + .word cpu_arm920_flush_pmd .word cpu_arm920_set_pte .size arm920_processor_functions, . - arm920_processor_functions diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index e213895147f5..d74cf416cc27 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -369,17 +369,15 @@ ENTRY(cpu_arm922_set_pgd) mov pc, lr /* - * cpu_arm922_set_pmd(pmdp, pmd) + * cpu_arm922_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_arm922_set_pmd) - str r1, [r0] +ENTRY(cpu_arm922_flush_pmd) mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr @@ -502,7 +500,7 @@ arm922_processor_functions: /* pgtable */ .word cpu_arm922_set_pgd - .word cpu_arm922_set_pmd + .word cpu_arm922_flush_pmd .word cpu_arm922_set_pte .size arm922_processor_functions, . - arm922_processor_functions diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 78f6c9996290..766103efa986 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -350,17 +350,15 @@ ENTRY(cpu_arm926_set_pgd) mov pc, lr /* - * cpu_arm926_set_pmd(pmdp, pmd) + * cpu_arm926_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_arm926_set_pmd) - str r1, [r0] +ENTRY(cpu_arm926_flush_pmd) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif @@ -500,7 +498,7 @@ arm926_processor_functions: /* pgtable */ .word cpu_arm926_set_pgd - .word cpu_arm926_set_pmd + .word cpu_arm926_flush_pmd .word cpu_arm926_set_pte .size arm926_processor_functions, . - arm926_processor_functions diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 69a111109b9c..fec7e5e8576b 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -425,18 +425,16 @@ ENTRY(cpu_sa1100_set_pgd) mov pc, lr /* - * cpu_sa110_set_pmd(pmdp, pmd) + * cpu_sa110_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_sa110_set_pmd) -ENTRY(cpu_sa1100_set_pmd) - str r1, [r0] +ENTRY(cpu_sa110_flush_pmd) +ENTRY(cpu_sa1100_flush_pmd) mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr @@ -544,7 +542,7 @@ ENTRY(sa110_processor_functions) /* pgtable */ .word cpu_sa110_set_pgd - .word cpu_sa110_set_pmd + .word cpu_sa110_flush_pmd .word cpu_sa110_set_pte .size sa110_processor_functions, . - sa110_processor_functions @@ -584,7 +582,7 @@ ENTRY(sa1100_processor_functions) /* pgtable */ .word cpu_sa1100_set_pgd - .word cpu_sa1100_set_pmd + .word cpu_sa1100_flush_pmd .word cpu_sa1100_set_pte .size sa1100_processor_functions, . - sa1100_processor_functions diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index ced3f8122b57..47c5448e619f 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -27,7 +27,7 @@ EXPORT_SYMBOL(cpu_dcache_invalidate_range); EXPORT_SYMBOL(cpu_icache_invalidate_range); EXPORT_SYMBOL(cpu_icache_invalidate_page); EXPORT_SYMBOL(cpu_set_pgd); -EXPORT_SYMBOL(cpu_set_pmd); +EXPORT_SYMBOL(cpu_flush_pmd); EXPORT_SYMBOL(cpu_set_pte); #else EXPORT_SYMBOL(processor); diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 2d4bbb5b91d3..c8f2b34b59d1 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -573,17 +573,15 @@ ENTRY(cpu_xscale_set_pgd) cpwait_ret lr, ip /* - * cpu_xscale_set_pmd(pmdp, pmd) + * cpu_xscale_flush_pmd(pmdp) * * Set a level 1 translation table entry, and clean it out of * any caches such that the MMUs can load it correctly. * * pmdp: pointer to PMD entry - * pmd: PMD value to store */ .align 5 -ENTRY(cpu_xscale_set_pmd) - str r1, [r0] +ENTRY(cpu_xscale_flush_pmd) mov ip, #0 mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer @@ -721,7 +719,7 @@ ENTRY(xscale_processor_functions) /* pgtable */ .word cpu_xscale_set_pgd - .word cpu_xscale_set_pmd + .word cpu_xscale_flush_pmd .word cpu_xscale_set_pte .size xscale_processor_functions, . - xscale_processor_functions diff --git a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h index 53e760417601..4440be79d5ac 100644 --- a/include/asm-arm/proc-armv/pgalloc.h +++ b/include/asm-arm/proc-armv/pgalloc.h @@ -96,7 +96,7 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) { unsigned long pte_ptr = (unsigned long)ptep; - pmd_t pmd; + unsigned long pmdval; BUG_ON(mm != &init_mm); @@ -105,21 +105,21 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) * address of the PTE table */ pte_ptr -= PTRS_PER_PTE * sizeof(void *); - pmd_val(pmd) = __pa(pte_ptr) | _PAGE_KERNEL_TABLE; - set_pmd(pmdp, pmd); - pmd_val(pmd) += 256 * sizeof(pte_t); - set_pmd(pmdp + 1, pmd); + pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + cpu_flush_pmd(pmdp); } static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) { - pmd_t pmd; + unsigned long pmdval; BUG_ON(mm == &init_mm); - pmd_val(pmd) = __pa(page_address(ptep)) | _PAGE_USER_TABLE; - set_pmd(pmdp, pmd); - pmd_val(pmd) += 256 * sizeof(pte_t); - set_pmd(pmdp + 1, pmd); + pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + cpu_flush_pmd(pmdp); } diff --git a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h index ea268a27e9a5..34c898876c5a 100644 --- a/include/asm-arm/proc-armv/pgtable.h +++ b/include/asm-arm/proc-armv/pgtable.h @@ -115,16 +115,17 @@ #include -#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER)) -#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL)) +#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) +#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) #define pmd_bad(pmd) (pmd_val(pmd) & 2) -#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd) +#define set_pmd(pmdp,pmd) do { *pmdp = pmd; cpu_flush_pmd(pmdp); } while (0) static inline void pmd_clear(pmd_t *pmdp) { - set_pmd(pmdp, __pmd(0)); - set_pmd(pmdp + 1, __pmd(0)); + pmdp[0], __pmd(0)); + pmdp[1], __pmd(0)); + cpu_flush_pmd(pmdp); } static inline pte_t *pmd_page_kernel(pmd_t pmd) -- cgit v1.2.3 From e0029ad169911fc812a4e12768983a1f31a462aa Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 21:37:10 +0000 Subject: [ARM] Finally kill old ecard device discovery interfaces. This cset kills the old racy ecard device discovery interfaces, converting the remaining drivers to use the new LDM-based interface. --- arch/arm/kernel/ecard.c | 48 +- drivers/acorn/block/mfmhd.c | 126 ++-- drivers/acorn/net/ether1.c | 5 - drivers/acorn/net/ether3.c | 5 - drivers/acorn/net/etherh.c | 4 - drivers/acorn/scsi/acornscsi.c | 282 +++---- drivers/acorn/scsi/arxescsi.c | 264 +++---- drivers/acorn/scsi/cumana_1.c | 308 +++----- drivers/acorn/scsi/cumana_2.c | 313 ++++---- drivers/acorn/scsi/ecoscsi.c | 1 + drivers/acorn/scsi/eesox.c | 337 ++++----- drivers/acorn/scsi/fas216.c | 1627 ++++++++++++++++++++++++---------------- drivers/acorn/scsi/fas216.h | 14 + drivers/acorn/scsi/oak.c | 256 +++---- drivers/acorn/scsi/powertec.c | 348 ++++----- drivers/acorn/scsi/queue.c | 22 + drivers/acorn/scsi/queue.h | 9 + include/asm-arm/ecard.h | 17 +- 18 files changed, 2047 insertions(+), 1939 deletions(-) diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 2b291c31ff8b..1206e7d9fd66 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -989,42 +989,6 @@ nomem: return rc; } -static ecard_t *finding_pos; - -void ecard_startfind(void) -{ - finding_pos = NULL; -} - -ecard_t *ecard_find(int cid, const card_ids *cids) -{ - if (!finding_pos) - finding_pos = cards; - else - finding_pos = finding_pos->next; - - for (; finding_pos; finding_pos = finding_pos->next) { - if (finding_pos->claimed) - continue; - - if (finding_pos->dev.driver) - continue; - - if (!cids) { - if ((finding_pos->cid.id ^ cid) == 0) - break; - } else { - const struct ecard_id *id; - - id = ecard_match_device(cids, finding_pos); - if (id) - break; - } - } - - return finding_pos; -} - /* * Initialise the expansion card system. * Locate all hardware - interrupt management and @@ -1087,10 +1051,15 @@ static int ecard_drv_probe(struct device *dev) struct expansion_card *ec = ECARD_DEV(dev); struct ecard_driver *drv = ECARD_DRV(dev->driver); const struct ecard_id *id; + int ret; id = ecard_match_device(drv->id_table, ec); - return drv->probe(ec, id); + ecard_claim(ec); + ret = drv->probe(ec, id); + if (ret) + ecard_release(ec); + return ret; } static int ecard_drv_remove(struct device *dev) @@ -1099,6 +1068,7 @@ static int ecard_drv_remove(struct device *dev) struct ecard_driver *drv = ECARD_DRV(dev->driver); drv->remove(ec); + ecard_release(ec); return 0; } @@ -1144,12 +1114,8 @@ static int ecard_bus_init(void) postcore_initcall(ecard_bus_init); -EXPORT_SYMBOL(ecard_startfind); -EXPORT_SYMBOL(ecard_find); EXPORT_SYMBOL(ecard_readchunk); EXPORT_SYMBOL(ecard_address); - EXPORT_SYMBOL(ecard_register_driver); EXPORT_SYMBOL(ecard_remove_driver); - EXPORT_SYMBOL(ecard_bus_type); diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c index bd2294d8d4de..01287e5452a4 100644 --- a/drivers/acorn/block/mfmhd.c +++ b/drivers/acorn/block/mfmhd.c @@ -160,13 +160,6 @@ struct hd_geometry { #ifndef DEBUG /*#define DEBUG */ #endif -/* - * List of card types that we recognise - */ -static const card_ids mfm_cids[] = { - { MANU_ACORN, PROD_ACORN_MFM }, - { 0xffff, 0xffff } -}; /* * End of configuration */ @@ -1230,8 +1223,6 @@ static struct block_device_operations mfm_fops = .ioctl = mfm_ioctl, }; -static struct expansion_card *ecs; - /* * See if there is a controller at the address presently at mfm_addr * @@ -1266,44 +1257,18 @@ static int mfm_probecontroller (unsigned int mfm_addr) return 1; } -/* - * Look for a MFM controller - first check the motherboard, then the podules - * The podules have an extra interrupt enable that needs to be played with - * - * The HDC is accessed at MEDIUM IOC speeds. - */ -static int __init mfm_init (void) +static int mfm_do_init(unsigned char irqmask) { - unsigned char irqmask; - int i; - - if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) { - mfm_addr = ONBOARD_MFM_ADDRESS; - mfm_IRQPollLoc = IOC_IRQSTATB; - mfm_irqenable = 0; - mfm_irq = IRQ_HARDDISK; - irqmask = 0x08; /* IL3 pin */ - } else { - ecs = ecard_find(0, mfm_cids); - if (!ecs) { - mfm_addr = 0; - return -1; - } - - mfm_addr = ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800; - mfm_IRQPollLoc = ioaddr(mfm_addr + 0x400); - mfm_irqenable = mfm_IRQPollLoc; - mfm_irq = ecs->irq; - irqmask = 0x08; - - ecard_claim(ecs); - } + int i, ret; printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq); + + ret = -EBUSY; if (!request_region (mfm_addr, 10, "mfm")) goto out1; - if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) { + ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops); + if (ret) { printk("mfm_init: unable to get major number %d\n", MAJOR_NR); goto out2; } @@ -1319,8 +1284,10 @@ static int __init mfm_init (void) lastspecifieddrive = -1; mfm_drives = mfm_initdrives(); - if (!mfm_drives) + if (!mfm_drives) { + ret = -ENODEV; goto out3; + } for (i = 0; i < mfm_drives; i++) { struct gendisk *disk = alloc_disk(64); @@ -1335,7 +1302,8 @@ static int __init mfm_init (void) printk("mfm: detected %d hard drive%s\n", mfm_drives, mfm_drives == 1 ? "" : "s"); - if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL)) { + ret = request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL); + if (ret) { printk("mfm: unable to get IRQ%d\n", mfm_irq); goto out4; } @@ -1359,19 +1327,17 @@ out3: out2: release_region(mfm_addr, 10); out1: - ecard_release(ecs); - return -1; + return ret; Enomem: while (i--) put_disk(mfm_gendisk[i]); goto out3; } -static void __exit mfm_exit(void) +static void mfm_do_exit(void) { int i; - if (ecs && mfm_irqenable) - outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ + free_irq(mfm_irq, NULL); for (i = 0; i < mfm_drives; i++) { del_gendisk(mfm_gendisk[i]); @@ -1379,12 +1345,72 @@ static void __exit mfm_exit(void) } blk_cleanup_queue(&mfm_queue); unregister_blkdev(MAJOR_NR, "mfm"); - if (ecs) - ecard_release(ecs); if (mfm_addr) release_region(mfm_addr, 10); } +static int __devinit mfm_probe(struct expansion_card *ec, struct ecard_id *id) +{ + if (mfm_addr) + return -EBUSY; + + mfm_addr = ecard_address(ec, ECARD_IOC, ECARD_MEDIUM) + 0x800; + mfm_IRQPollLoc = ioaddr(mfm_addr + 0x400); + mfm_irqenable = mfm_IRQPollLoc; + mfm_irq = ec->irq; + + return mfm_do_init(0x08); +} + +static void __devexit mfm_remove(struct expansion_card *ec) +{ + outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ + mfm_do_exit(); +} + +static const struct ecard_id mfm_cids[] = { + { MANU_ACORN, PROD_ACORN_MFM }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver mfm_driver = { + .probe = mfm_probe, + .remove = __devexit(mfm_remove), + .id_table = mfm_cids, + .drv = { + .name = "mfm", + }, +}; + +/* + * Look for a MFM controller - first check the motherboard, then the podules + * The podules have an extra interrupt enable that needs to be played with + * + * The HDC is accessed at MEDIUM IOC speeds. + */ +static int __init mfm_init (void) +{ + unsigned char irqmask; + + if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) { + mfm_addr = ONBOARD_MFM_ADDRESS; + mfm_IRQPollLoc = IOC_IRQSTATB; + mfm_irqenable = 0; + mfm_irq = IRQ_HARDDISK; + return mfm_do_init(0x08); /* IL3 pin */ + } else { + return ecard_register_driver(&mfm_driver); + } +} + +static void __exit mfm_exit(void) +{ + if (mfm_addr == ONBOARD_MFM_ADDRESS) + mfm_do_exit(); + else + ecard_unregister_driver(&mfm_driver); +} + module_init(mfm_init) module_exit(mfm_exit) MODULE_LICENSE("GPL"); diff --git a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c index d20d361c85a6..16baa4718194 100644 --- a/drivers/acorn/net/ether1.c +++ b/drivers/acorn/net/ether1.c @@ -1021,8 +1021,6 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id) ether1_banner(); - ecard_claim(ec); - dev = init_etherdev(NULL, sizeof(struct ether1_priv)); if (!dev) { ret = -ENOMEM; @@ -1077,7 +1075,6 @@ release: unregister_netdev(dev); kfree(dev); out: - ecard_release(ec); return ret; } @@ -1092,8 +1089,6 @@ static void __devexit ether1_remove(struct expansion_card *ec) release_region(dev->base_addr, 16); release_region(dev->base_addr + 0x800, 4096); kfree(dev); - - ecard_release(ec); } static const struct ecard_id ether1_ids[] = { diff --git a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c index 1300a42e2b03..97b98fda2c55 100644 --- a/drivers/acorn/net/ether3.c +++ b/drivers/acorn/net/ether3.c @@ -830,8 +830,6 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id) ether3_banner(); - ecard_claim(ec); - dev = init_etherdev(NULL, sizeof(struct dev_priv)); if (!dev) { ret = -ENOMEM; @@ -917,7 +915,6 @@ free: unregister_netdev(dev); kfree(dev); out: - ecard_release(ec); return ret; } @@ -930,8 +927,6 @@ static void __devexit ether3_remove(struct expansion_card *ec) unregister_netdev(dev); release_region(dev->base_addr, 128); kfree(dev); - - ecard_release(ec); } static const struct ecard_id ether3_ids[] = { diff --git a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c index 4ffe92dd478f..4cabcdab7e37 100644 --- a/drivers/acorn/net/etherh.c +++ b/drivers/acorn/net/etherh.c @@ -568,8 +568,6 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) etherh_banner(); - ecard_claim(ec); - dev = init_etherdev(NULL, sizeof(struct etherh_priv)); if (!dev) { ret = -ENOMEM; @@ -725,7 +723,6 @@ free: kfree(dev->priv); kfree(dev); out: - ecard_release(ec); return ret; } @@ -744,7 +741,6 @@ static void __devexit etherh_remove(struct expansion_card *ec) ec->ops = NULL; kfree(ec->irq_data); - ecard_release(ec); } static const struct ecard_id etherh_ids[] = { diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c index ad7469425a94..099c22550153 100644 --- a/drivers/acorn/scsi/acornscsi.c +++ b/drivers/acorn/scsi/acornscsi.c @@ -109,10 +109,7 @@ * If not set, then use PIO mode (not currently supported). */ #define USE_DMAC -/* - * List of devices that the driver will recognise - */ -#define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI } + /* * ==================================================================================== */ @@ -2832,148 +2829,6 @@ int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) /*============================================================================================== * initialisation & miscellaneous support */ -static struct expansion_card *ecs[MAX_ECARDS]; - -/* - * Prototype: void acornscsi_init(AS_Host *host) - * Purpose : initialise the AS_Host structure for one interface & setup hardware - * Params : host - host to setup - */ -static -void acornscsi_host_init(AS_Host *host) -{ - memset(&host->stats, 0, sizeof (host->stats)); - queue_initialise(&host->queues.issue); - queue_initialise(&host->queues.disconnected); - msgqueue_initialise(&host->scsi.msgs); - - acornscsi_resetcard(host); -} - -int acornscsi_detect(Scsi_Host_Template * tpnt) -{ - static const card_ids acornscsi_cids[] = { ACORNSCSI_LIST, { 0xffff, 0xffff } }; - int i, count = 0; - struct Scsi_Host *instance; - AS_Host *host; - - tpnt->proc_name = "acornscsi"; - - for (i = 0; i < MAX_ECARDS; i++) - ecs[i] = NULL; - - ecard_startfind(); - - while(1) { - ecs[count] = ecard_find(0, acornscsi_cids); - if (!ecs[count]) - break; - - if (ecs[count]->irq == 0xff) { - printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n"); - continue; - } - - ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */ - - instance = scsi_register(tpnt, sizeof(AS_Host)); - if (!instance) { - ecard_release(ecs[count]); - break; - } - - host = (AS_Host *)instance->hostdata; - - instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); - instance->irq = ecs[count]->irq; - - host->host = instance; - host->scsi.io_port = ioaddr(instance->io_port + 0x800); - host->scsi.irq = instance->irq; - host->card.io_intr = POD_SPACE(instance->io_port) + 0x800; - host->card.io_page = POD_SPACE(instance->io_port) + 0xc00; - host->card.io_ram = ioaddr(instance->io_port); - host->dma.io_port = instance->io_port + 0xc00; - host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800; - - ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr); - ecs[count]->irqmask = 0x0a; - - if (!request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)")) - goto err_1; - if (!request_region(host->card.io_intr, 1, "acornscsi(intr)")) - goto err_2; - if (!request_region(host->card.io_page, 1, "acornscsi(page)")) - goto err_3; -#ifdef USE_DMAC - if (!request_region(host->dma.io_port, 256, "acornscsi(dmac)")) - goto err_4; -#endif - if (!request_region(instance->io_port, 2048, "acornscsi(ram)")) - goto err_5; - - if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) { - printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, host->scsi.irq); - host->scsi.irq = NO_IRQ; - } - - acornscsi_host_init(host); - - ++count; - } - return count; - -err_5: -#ifdef USE_DMAC - release_region(host->dma.io_port, 256); -#endif -err_4: - release_region(host->card.io_page, 1); -err_3: - release_region(host->card.io_intr, 1); -err_2: - release_region(instance->io_port + 0x800, 2); -err_1: - scsi_unregister(instance); - return 0; -} - -/* - * Function: int acornscsi_release(struct Scsi_Host *host) - * Purpose : release all resources used by this adapter - * Params : host - driver structure to release - * Returns : nothing of any consequence - */ -int acornscsi_release(struct Scsi_Host *instance) -{ - AS_Host *host = (AS_Host *)instance->hostdata; - int i; - - /* - * Put card into RESET state - */ - outb(0x80, host->card.io_page); - - if (host->scsi.irq != NO_IRQ) - free_irq(host->scsi.irq, host); - - release_region(instance->io_port + 0x800, 2); - release_region(host->card.io_intr, 1); - release_region(host->card.io_page, 1); - release_region(host->dma.io_port, 256); - release_region(instance->io_port, 2048); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0)) - ecard_release(ecs[i]); - - msgqueue_free(&host->scsi.msgs); - queue_free(&host->queues.disconnected); - queue_free(&host->queues.issue); - - return 0; -} /* * Function: char *acornscsi_info(struct Scsi_Host *host) @@ -3126,10 +2981,9 @@ static Scsi_Host_Template acornscsi_template = { .module = THIS_MODULE, .proc_info = acornscsi_proc_info, .name = "AcornSCSI", - .detect = acornscsi_detect, - .release = acornscsi_release, .info = acornscsi_info, .queuecommand = acornscsi_queuecmd, +#warning fixme .abort = acornscsi_abort, .reset = acornscsi_reset, .can_queue = 16, @@ -3137,22 +2991,137 @@ static Scsi_Host_Template acornscsi_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .unchecked_isa_dma = 0, - .use_clustering = DISABLE_CLUSTERING + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "acornscsi", }; -static int __init acornscsi_init(void) +static int __devinit +acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) { - scsi_register_host(&acornscsi_template); - if (acornscsi_template.present) - return 0; + struct Scsi_Host *host; + AS_Host *ashost; + int ret = -ENOMEM; + + host = scsi_register(&acornscsi_template, sizeof(AS_Host)); + if (!host) + goto out; - scsi_unregister_host(&acornscsi_template); - return -ENODEV; + ashost = (AS_Host *)host->hostdata; + + host->io_port = ecard_address(ec, ECARD_MEMC, 0); + host->irq = ec->irq; + + ashost->host = host; + ashost->scsi.io_port = ioaddr(host->io_port + 0x800); + ashost->scsi.irq = host->irq; + ashost->card.io_intr = POD_SPACE(host->io_port) + 0x800; + ashost->card.io_page = POD_SPACE(host->io_port) + 0xc00; + ashost->card.io_ram = ioaddr(host->io_port); + ashost->dma.io_port = host->io_port + 0xc00; + ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800; + + ec->irqaddr = (char *)ioaddr(ashost->card.io_intr); + ec->irqmask = 0x0a; + + ret = -EBUSY; + if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)")) + goto err_1; + if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)")) + goto err_2; + if (!request_region(ashost->card.io_page, 1, "acornscsi(page)")) + goto err_3; +#ifdef USE_DMAC + if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)")) + goto err_4; +#endif + if (!request_region(host->io_port, 2048, "acornscsi(ram)")) + goto err_5; + + ret = request_irq(host->irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", ashost); + if (ret) { + printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", + host->host_no, ashost->scsi.irq, ret); + goto err_6; + } + + memset(&ashost->stats, 0, sizeof (ashost->stats)); + queue_initialise(&ashost->queues.issue); + queue_initialise(&ashost->queues.disconnected); + msgqueue_initialise(&ashost->scsi.msgs); + + acornscsi_resetcard(ashost); + + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + free_irq(host->irq, ashost); + err_6: + release_region(host->io_port, 2048); + err_5: +#ifdef USE_DMAC + release_region(ashost->dma.io_port, 256); +#endif + err_4: + release_region(ashost->card.io_page, 1); + err_3: + release_region(ashost->card.io_intr, 1); + err_2: + release_region(host->io_port + 0x800, 2); + err_1: + scsi_unregister(host); + out: + return ret; +} + +static void __devexit acornscsi_remove(struct expansion_card *ec) +{ + struct Scsi_Host *host = ecard_get_drvdata(ec); + AS_Host *ashost = (AS_Host *)host->hostdata; + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + + /* + * Put card into RESET state + */ + outb(0x80, ashost->card.io_page); + + free_irq(host->irq, ashost); + + release_region(host->io_port + 0x800, 2); + release_region(ashost->card.io_intr, 1); + release_region(ashost->card.io_page, 1); + release_region(ashost->dma.io_port, 256); + release_region(host->io_port, 2048); + + msgqueue_free(&ashost->scsi.msgs); + queue_free(&ashost->queues.disconnected); + queue_free(&ashost->queues.issue); +} + +static const struct ecard_id acornscsi_cids[] = { + { MANU_ACORN, PROD_ACORN_SCSI }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver acornscsi_driver = { + .probe = acornscsi_probe, + .remove = __devexit_p(acornscsi_remove), + .id_table = acornscsi_cids, + .drv = { + .name = "acornscsi", + }, +}; + +static int __init acornscsi_init(void) +{ + return ecard_register_driver(&acornscsi_driver); } static void __exit acornscsi_exit(void) { - scsi_unregister_host(&acornscsi_template); + ecard_remove_driver(&acornscsi_driver); } module_init(acornscsi_init); @@ -3161,4 +3130,3 @@ module_exit(acornscsi_exit); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("AcornSCSI driver"); MODULE_LICENSE("GPL"); - diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c index d2ab33346cbe..aa6454f0a2c3 100644 --- a/drivers/acorn/scsi/arxescsi.c +++ b/drivers/acorn/scsi/arxescsi.c @@ -37,21 +37,29 @@ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" -#include "arxescsi.h" #include "fas216.h" -/* Hmm - this should go somewhere else */ -#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) +struct arxescsi_info { + FAS216_Info info; -/* Configuration */ -#define ARXESCSI_XTALFREQ 24 -#define ARXESCSI_ASYNC_PERIOD 200 -#define ARXESCSI_SYNC_DEPTH 0 + /* other info... */ + unsigned int cstatus; /* card status register */ + unsigned int dmaarea; /* Pseudo DMA area */ +}; -/* - * List of devices that the driver will recognise - */ -#define ARXESCSI_LIST { MANU_ARXE, PROD_ARXE_SCSI } +#define CSTATUS_IRQ (1 << 0) +#define CSTATUS_DRQ (1 << 0) + +#ifndef CAN_QUEUE +#define CAN_QUEUE 1 +#endif + +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 1 +#endif + +/* Hmm - this should go somewhere else */ +#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) /* * Version @@ -60,8 +68,6 @@ #define VER_MINOR 1 #define VER_PATCH 1 -static struct expansion_card *ecs[MAX_ECARDS]; - /* * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type) * Purpose : initialises DMA/PIO @@ -85,7 +91,7 @@ arxescsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, /* Faster transfer routines, written by SH to speed up the loops */ -static __inline__ unsigned char getb(unsigned int address, unsigned int reg) +static inline unsigned char getb(unsigned int address, unsigned int reg) { unsigned char value; @@ -96,7 +102,7 @@ static __inline__ unsigned char getb(unsigned int address, unsigned int reg) return value; } -static __inline__ unsigned int getw(unsigned int address, unsigned int reg) +static inline unsigned int getw(unsigned int address, unsigned int reg) { unsigned int value; @@ -109,7 +115,7 @@ static __inline__ unsigned int getw(unsigned int address, unsigned int reg) return value; } -static __inline__ void putw(unsigned int address, unsigned int reg, unsigned long value) +static inline void putw(unsigned int address, unsigned int reg, unsigned long value) { __asm__ __volatile__( "mov %0, %0, lsl #16\n\t" @@ -157,7 +163,7 @@ void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned int io) void arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer) { - ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata; + struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; unsigned int length, io, error=0; unsigned char *addr; @@ -247,106 +253,6 @@ static void arxescsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) */ } -/* - * Function: int arxescsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises ARXE SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int arxescsi_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids arxescsi_cids[] = { ARXESCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "arxescsi"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - ARXEScsi_Info *info; - - ecs[count] = ecard_find(0, arxescsi_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (ARXEScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0) + 0x0800; - host->irq = NO_IRQ; - host->dma_channel = NO_DMA; - host->can_queue = 0; /* no command queueing */ - info = (ARXEScsi_Info *)host->hostdata; - - info->info.scsi.io_port = host->io_port; - info->info.scsi.irq = host->irq; - info->info.scsi.io_shift = 3; - info->info.ifcfg.clockrate = ARXESCSI_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = ARXESCSI_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = ARXESCSI_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 0; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = arxescsi_dma_setup; - info->info.dma.pseudo = arxescsi_dma_pseudo; - info->info.dma.stop = arxescsi_dma_stop; - info->dmaarea = host->io_port + 128; - info->cstatus = host->io_port + 384; - - ecs[count]->irqaddr = (unsigned char *)BUS_ADDR(host->io_port); - ecs[count]->irqmask = CSTATUS_IRQ; - - if (!request_region(host->io_port, 120, "arxescsi-fas")) { - ecard_release(ecs[count]); - scsi_unregister(host); - break; - } - - if (!request_region(host->io_port + 128, 384, "arxescsi-dma")) { - ecard_release(ecs[count]); - release_region(host->io_port, 120); - scsi_unregister(host); - break; - } - - printk("scsi%d: Has no interrupts - using polling mode\n", - host->host_no); - - fas216_init(host); - ++count; - } - return count; -} - -/* - * Function: int arxescsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - * Returns : nothing - */ -int arxescsi_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - release_region(host->io_port, 120); - release_region(host->io_port + 128, 384); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && host->io_port == (ecard_address(ecs[i], ECARD_MEMC, 0) + 0x0800)) - ecard_release(ecs[i]); - return 0; -} - /* * Function: const char *arxescsi_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, @@ -355,7 +261,7 @@ int arxescsi_release(struct Scsi_Host *host) */ const char *arxescsi_info(struct Scsi_Host *host) { - ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata; + struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; static char string[100], *p; p = string; @@ -385,14 +291,14 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset, { int pos, begin; struct Scsi_Host *host; - ARXEScsi_Info *info; + struct arxescsi_info *info; Scsi_Device *scd; host = scsi_host_hn_get(host_no); if (!host) return 0; - info = (ARXEScsi_Info *)host->hostdata; + info = (struct arxescsi_info *)host->hostdata; if (inout == 1) return -EINVAL; @@ -424,22 +330,122 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset, return pos; } -static Scsi_Host_Template arxescsi_template = ARXEScsi; +static Scsi_Host_Template arxescsi_template = { + .proc_info = arxescsi_proc_info, + .name = "ARXE SCSI card", + .info = arxescsi_info, + .command = fas216_command, + .queuecommand = fas216_queue_command, + .eh_host_reset_handler = fas216_eh_host_reset, + .eh_bus_reset_handler = fas216_eh_bus_reset, + .eh_device_reset_handler = fas216_eh_device_reset, + .eh_abort_handler = fas216_eh_abort, + .can_queue = 0, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "arxescsi", +}; + +static int __devinit +arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + struct Scsi_Host *host; + struct arxescsi_info *info; + int ret = -ENOMEM; -static int __init init_arxe_scsi_driver(void) + host = scsi_register(&arxescsi_template, sizeof(struct arxescsi_info)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_MEMC, 0) + 0x0800; + host->irq = NO_IRQ; + host->dma_channel = NO_DMA; + + info = (struct arxescsi_info *)host->hostdata; + info->info.scsi.io_port = host->io_port; + info->info.scsi.irq = host->irq; + info->info.scsi.io_shift = 3; + info->info.ifcfg.clockrate = 24; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 0; + info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 0; + info->info.ifcfg.wide_max_size = 0; + info->info.dma.setup = arxescsi_dma_setup; + info->info.dma.pseudo = arxescsi_dma_pseudo; + info->info.dma.stop = arxescsi_dma_stop; + info->dmaarea = host->io_port + 128; + info->cstatus = host->io_port + 384; + + ec->irqaddr = (unsigned char *)BUS_ADDR(host->io_port); + ec->irqmask = CSTATUS_IRQ; + + if (!request_region(host->io_port, 120, "arxescsi-fas")) { + ret = -EBUSY; + goto out_free; + } + + if (!request_region(host->io_port + 128, 384, "arxescsi-dma")) { + ret = -EBUSY; + goto out_release; + } + + printk("scsi%d: Has no interrupts - using polling mode\n", + host->host_no); + + fas216_init(host); + + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + release_region(host->io_port + 128, 384); + out_release: + release_region(host->io_port, 120); + out_free: + scsi_unregister(host); + out: + return ret; +} + +static void __devexit arxescsi_release(struct expansion_card *ec) { - arxescsi_template.module = THIS_MODULE; - scsi_register_host(&arxescsi_template); - if (arxescsi_template.present) - return 0; + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + fas216_release(host); + + release_region(host->io_port + 128, 384); + release_region(host->io_port, 120); + scsi_unregister(host); +} - scsi_unregister_host(&arxescsi_template); - return -ENODEV; +static const struct ecard_id arxescsi_cids[] = { + { MANU_ARXE, PROD_ARXE_SCSI }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver arxescsi_driver = { + .probe = arxescsi_probe, + .remove = __devexit_p(arxescsi_remove), + .id_table = arxescsi_cids, + .drv = { + .name = "arxescsi", + }, +}; + +static int __init init_arxe_scsi_driver(void) +{ + return ecard_register_driver(&arxescsi_driver); } static void __exit exit_arxe_scsi_driver(void) { - scsi_unregister_host(&arxescsi_template); + ecard_remove_driver(&arxescsi_driver); } module_init(init_arxe_scsi_driver); diff --git a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c index 2f722722d07d..308e438198a4 100644 --- a/drivers/acorn/scsi/cumana_1.c +++ b/drivers/acorn/scsi/cumana_1.c @@ -1,56 +1,13 @@ -#define AUTOSENSE -#define PSEUDO_DMA - /* * Generic Generic NCR5380 driver * - * Copyright 1995, Russell King - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - - -/* - * Options : - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - */ - -/* - * $Log: cumana_1.c,v $ - * Revision 1.3 1998/05/03 20:45:32 alan - * ARM SCSI update. This adds the eesox driver and massively updates the - * Cumana driver. The folks who bought cumana arent anal retentive all - * docs are secret weenies so now there are docs .. - * - * Revision 1.2 1998/03/08 05:49:46 davem - * Merge to 2.1.89 - * - * Revision 1.1 1998/02/23 02:45:22 davem - * Merge to 2.1.88 - * + * Copyright 1995-2002, Russell King */ - #include #include #include #include +#include #include #include @@ -64,28 +21,19 @@ #include -#define CUMANASCSI_PUBLIC_RELEASE 1 - -static const card_ids cumanascsi_cids[] = { - { MANU_CUMANA, PROD_CUMANA_SCSI_1 }, - { 0xffff, 0xffff } -}; - -#define NCR5380_implementation_fields \ - int port, ctrl - -#define NCR5380_local_declare() \ - struct Scsi_Host *_instance - -#define NCR5380_setup(instance) \ - _instance = instance +#define AUTOSENSE +#define PSEUDO_DMA -#define NCR5380_read(reg) cumanascsi_read(_instance, reg) -#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value) +#define CUMANASCSI_PUBLIC_RELEASE 1 -#define NCR5380_intr cumanascsi_intr -#define NCR5380_queue_command cumanascsi_queue_command -#define NCR5380_proc_info cumanascsi_proc_info +#define NCR5380_implementation_fields int port, ctrl +#define NCR5380_local_declare() struct Scsi_Host *_instance +#define NCR5380_setup(instance) _instance = instance +#define NCR5380_read(reg) cumanascsi_read(_instance, reg) +#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value) +#define NCR5380_intr cumanascsi_intr +#define NCR5380_queue_command cumanascsi_queue_command +#define NCR5380_proc_info cumanascsi_proc_info int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); @@ -95,112 +43,13 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, #include "../../scsi/NCR5380.h" -/* - * Function : cumanascsi_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - void cumanascsi_setup(char *str, int *ints) { } -#define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800) -#define CUMANA_IRQ(card) ((card)->irq) -/* - * Function : int cumanascsi_detect(Scsi_Host_Template * tpnt) - * - * Purpose : initializes cumana NCR5380 driver based on the - * command line / compile time port and irq definitions. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ -static struct expansion_card *ecs[4]; - -int cumanascsi_detect(Scsi_Host_Template * tpnt) +const char *cumanascsi_info(struct Scsi_Host *spnt) { - int count = 0; - struct Scsi_Host *instance; - - tpnt->proc_name = "CumanaSCSI-1"; - - memset (ecs, 0, sizeof (ecs)); - - while(1) { - if((ecs[count] = ecard_find(0, cumanascsi_cids)) == NULL) - break; - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if (!instance) - break; - instance->io_port = CUMANA_ADDRESS(ecs[count]); - instance->irq = CUMANA_IRQ(ecs[count]); - - NCR5380_init(instance, 0); - ecard_claim(ecs[count]); - - instance->n_io_port = 255; - if ( !(request_region (instance->io_port, instance->n_io_port, "CumanaSCSI-1")) ) { - ecard_release(ecs[count]); - scsi_unregister(instance); - break; - } - - ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; - outb(0x00, instance->io_port - 577); - - if (instance->irq != IRQ_NONE) - if (request_irq(instance->irq, cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - - if (instance->irq == IRQ_NONE) { - printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no); - } - - printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) - printk ("s disabled"); - else - printk (" %d", instance->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", instance->host_no); - NCR5380_print_options(instance); - printk("\n"); - - ++count; - } - return count; -} - -int cumanascsi_release (struct Scsi_Host *shpnt) -{ - int i; - - if (shpnt->irq != IRQ_NONE) - free_irq (shpnt->irq, NULL); - if (shpnt->io_port) - release_region (shpnt->io_port, shpnt->n_io_port); - - for (i = 0; i < 4; i++) - if (shpnt->io_port == CUMANA_ADDRESS(ecs[i])) - ecard_release (ecs[i]); - return 0; -} - -const char * cumanascsi_info (struct Scsi_Host *spnt) { - return ""; + return ""; } #ifdef NOT_EFFICIENT @@ -219,8 +68,8 @@ const char * cumanascsi_info (struct Scsi_Host *spnt) { #define L(v) (((v)<<16)|((v) & 0x0000ffff)) #define H(v) (((v)>>16)|((v) & 0xffff0000)) -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int +NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) { int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; int oldctrl = *ctrl; @@ -289,8 +138,8 @@ end: return len; } -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int +NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len) { int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; int oldctrl = *ctrl; @@ -367,25 +216,25 @@ end: static char cumanascsi_read(struct Scsi_Host *instance, int reg) { - int iobase = instance->io_port; - int i; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + unsigned int iobase = instance->io_port; + int i; + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - CTRL(iobase, 0); - i = inb(iobase + 64 + reg); - CTRL(iobase, 0x40); + CTRL(iobase, 0); + i = inb(iobase + 64 + reg); + CTRL(iobase, 0x40); - return i; + return i; } static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) { - int iobase = instance->io_port; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + int iobase = instance->io_port; + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - CTRL(iobase, 0); - outb(value, iobase + 64 + reg); - CTRL(iobase, 0x40); + CTRL(iobase, 0); + outb(value, iobase + 64 + reg); + CTRL(iobase, 0x40); } #undef CTRL @@ -395,8 +244,6 @@ static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) static Scsi_Host_Template cumanascsi_template = { .module = THIS_MODULE, .name = "Cumana 16-bit SCSI", - .detect = cumanascsi_detect, - .release = cumanascsi_release, .info = cumanascsi_info, .queuecommand = cumanascsi_queue_command, .eh_abort_handler = NCR5380_abort, @@ -408,26 +255,101 @@ static Scsi_Host_Template cumanascsi_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .unchecked_isa_dma = 0, - .use_clustering = DISABLE_CLUSTERING + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "CumanaSCSI-1", }; -static int __init cumanascsi_init(void) +static int __devinit +cumanascsi1_probe(struct expansion_card *ec, struct ecard_ids *id) { - scsi_register_host(&cumanascsi_template); - if (cumanascsi_template.present) - return 0; + struct Scsi_Host *host; + int ret = -ENOMEM; + + host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800; + host->irq = ec->irq; + + NCR5380_init(host, 0); - scsi_unregister_host(&cumanascsi_template); - return -ENODEV; + host->n_io_port = 255; + if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { + ret = -EBUSY; + goto out_free; + } + + ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0; + outb(0x00, host->io_port - 577); + + ret = request_irq(host->irq, cumanascsi_intr, SA_INTERRUPT, + "CumanaSCSI-1", host); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_release; + } + + printk("scsi%d: at port 0x%08lx irq %d", + host->host_no, host->io_port, host->irq); + printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", + tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE); + printk("\nscsi%d:", host->host_no); + NCR5380_print_options(host); + printk("\n"); + + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + free_irq(host->irq, host); + out_release: + release_region(host->io_port, host->n_io_port); + out_free: + scsi_unregister(host); + out: + return ret; +} + +static void __devexit cumanascsi1_remove(struct expansion_card *ec) +{ + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + + scsi_remove_host(host); + free_irq(host->irq, host); + release_region(host->io_port, host->n_io_port); + scsi_remove(host); +} + +static const struct ecard_ids cumanascsi1_cids[] = { + { MANU_CUMANA, PROD_CUMANA_SCSI_1 }, + { 0xffff, 0xffff } +}; + +static struct ecard_driver cumanascsi1_driver = { + .probe = cumanascsi1_probe, + .remove = __devexit_p(cumanascsi1_remove), + .id_table = cumanascsi1_cids, + .drv = { + .name = "cumanascsi1", + }, +}; + +static int __init cumanascsi_init(void) +{ + return ecard_register_driver(&cumanascsi1_driver); } static void __exit cumanascsi_exit(void) { - scsi_unregister_host(&cumanascsi_template); + ecard_remove_driver(&cumanascsi1_driver); } module_init(cumanascsi_init); module_exit(cumanascsi_exit); +MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines"); MODULE_LICENSE("GPL"); - diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c index a1a245890c2f..33aa30401b1a 100644 --- a/drivers/acorn/scsi/cumana_2.c +++ b/drivers/acorn/scsi/cumana_2.c @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/scsi/cumana_2.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -42,16 +42,6 @@ #include -/* Configuration */ -#define CUMANASCSI2_XTALFREQ 40 -#define CUMANASCSI2_ASYNC_PERIOD 200 -#define CUMANASCSI2_SYNC_DEPTH 7 - -/* - * List of devices that the driver will recognise - */ -#define CUMANASCSI2_LIST { MANU_CUMANA, PROD_CUMANA_SCSI_2 } - #define CUMANASCSI2_STATUS (0) #define STATUS_INT (1 << 0) #define STATUS_DRQ (1 << 1) @@ -73,15 +63,12 @@ #define CUMANASCSI2_FAS216_OFFSET (0xc0) #define CUMANASCSI2_FAS216_SHIFT 0 +#define CUMANASCSI2_FAS216_SIZE (16) /* * Version */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 4 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.00 (13/11/2002 2.5.47)" /* * Use term=0,1,0,0,0 to turn terminators on/off @@ -90,16 +77,15 @@ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; #define NR_SG 256 -typedef struct { +struct cumanascsi2_info { FAS216_Info info; - /* other info... */ unsigned int status; /* card status register */ unsigned int alatch; /* Control register */ unsigned int terms; /* Terminator state */ unsigned int dmaarea; /* Pseudo DMA area */ struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} CumanaScsi2_Info; +}; #define CSTATUS_IRQ (1 << 0) #define CSTATUS_DRQ (1 << 1) @@ -129,12 +115,8 @@ cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr) } static const expansioncard_ops_t cumanascsi_2_ops = { - cumanascsi_2_irqenable, - cumanascsi_2_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = cumanascsi_2_irqenable, + .irqdisable = cumanascsi_2_irqdisable, }; /* Prototype: void cumanascsi_2_terminator_ctl(host, on_off) @@ -145,7 +127,7 @@ static const expansioncard_ops_t cumanascsi_2_ops = { static void cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; if (on_off) { info->terms = 1; @@ -182,7 +164,7 @@ static fasdmatype_t cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; int dmach = host->dma_channel; outb(ALATCH_DIS_DMA, info->alatch); @@ -233,7 +215,7 @@ static void cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; unsigned int length; unsigned char *addr; @@ -307,129 +289,13 @@ end: static void cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; if (host->dma_channel != NO_DMA) { outb(ALATCH_DIS_DMA, info->alatch); disable_dma(host->dma_channel); } } -/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises Cumana SCSI 2 driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -cumanascsi_2_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids cumanascsi_2_cids[] = - { CUMANASCSI2_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "cumanascs2"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - CumanaScsi2_Info *info; - - ecs[count] = ecard_find(0, cumanascsi_2_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (CumanaScsi2_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (CumanaScsi2_Info *)host->hostdata; - - info->terms = term[count] ? 1 : 0; - cumanascsi_2_terminator_ctl(host, info->terms); - - info->info.scsi.io_port = host->io_port + CUMANASCSI2_FAS216_OFFSET; - info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = CUMANASCSI2_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = CUMANASCSI2_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = CUMANASCSI2_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = cumanascsi_2_dma_setup; - info->info.dma.pseudo = cumanascsi_2_dma_pseudo; - info->info.dma.stop = cumanascsi_2_dma_stop; - info->dmaarea = host->io_port + CUMANASCSI2_PSEUDODMA; - info->status = host->io_port + CUMANASCSI2_STATUS; - info->alatch = host->io_port + CUMANASCSI2_ALATCH; - - ecs[count]->irqaddr = (unsigned char *)ioaddr(info->status); - ecs[count]->irqmask = STATUS_INT; - ecs[count]->irq_data = (void *)info->alatch; - ecs[count]->ops = (expansioncard_ops_t *)&cumanascsi_2_ops; - - if (!request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, - 16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas")) { - scsi_unregister(host); - ecard_release(ecs[count]); - break; - } - - - if (host->irq != NO_IRQ && - request_irq(host->irq, cumanascsi_2_intr, - SA_INTERRUPT, "cumanascsi2", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; - info->info.scsi.irq = NO_IRQ; - } - - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "cumanascsi2")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } - - fas216_init(host); - ++count; - } - return count; -} - -/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - */ -int cumanascsi_2_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, - 16 << CUMANASCSI2_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && host->io_port == ecard_address (ecs[i], ECARD_MEMC, 0)) - ecard_release (ecs[i]); - return 0; -} - /* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -437,15 +303,14 @@ int cumanascsi_2_release(struct Scsi_Host *host) */ const char *cumanascsi_2_info(struct Scsi_Host *host) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; static char string[100], *p; p = string; p += sprintf(p, "%s ", host->hostt->name); p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->terms ? "n" : "ff"); + p += sprintf(p, "v%s terminators o%s", + VERSION, info->terms ? "n" : "ff"); return string; } @@ -499,7 +364,7 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, { int pos, begin; struct Scsi_Host *host; - CumanaScsi2_Info *info; + struct cumanascsi2_info *info; Scsi_Device *scd; host = scsi_host_hn_get(host_no); @@ -509,12 +374,12 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, if (inout == 1) return cumanascsi_2_set_proc_info(host, buffer, length); - info = (CumanaScsi2_Info *)host->hostdata; + info = (struct cumanascsi2_info *)host->hostdata; begin = 0; pos = sprintf(buffer, - "Cumana SCSI II driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + "Cumana SCSI II driver version v%s\n", + VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", @@ -556,35 +421,148 @@ static Scsi_Host_Template cumanascsi2_template = { .module = THIS_MODULE, .proc_info = cumanascsi_2_proc_info, .name = "Cumana SCSI II", - .detect = cumanascsi_2_detect, - .release = cumanascsi_2_release, .info = cumanascsi_2_info, - .can_queue = 1, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, .eh_device_reset_handler = fas216_eh_device_reset, .eh_abort_handler = fas216_eh_abort, + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "cumanascsi2", }; -static int __init cumanascsi2_init(void) +static int __devinit +cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id) { - scsi_register_host(&cumanascsi2_template); - if (cumanascsi2_template.present) - return 0; + struct Scsi_Host *host; + struct cumanascsi2_info *info; + int ret = -ENOMEM; + + host = scsi_register(&cumanascsi2_template, sizeof (struct cumanascsi2_info)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_MEMC, 0); + host->irq = ec->irq; + host->dma_channel = ec->dma; + + if (!request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + CUMANASCSI2_FAS216_SIZE, "cumanascsi2-fas")) { + ret = -EBUSY; + goto out_free; + } + + ecard_set_drvdata(ec, host); + + info = (struct cumanascsi2_info *)host->hostdata; + info->dmaarea = host->io_port + CUMANASCSI2_PSEUDODMA; + info->status = host->io_port + CUMANASCSI2_STATUS; + info->alatch = host->io_port + CUMANASCSI2_ALATCH; + + ec->irqaddr = (unsigned char *)ioaddr(info->status); + ec->irqmask = STATUS_INT; + ec->irq_data = (void *)info->alatch; + ec->ops = (expansioncard_ops_t *)&cumanascsi_2_ops; + + cumanascsi_2_terminator_ctl(host, term[ec->slot_no]); + + info->info.scsi.io_port = host->io_port + CUMANASCSI2_FAS216_OFFSET; + info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.dma.setup = cumanascsi_2_dma_setup; + info->info.dma.pseudo = cumanascsi_2_dma_pseudo; + info->info.dma.stop = cumanascsi_2_dma_stop; + + ret = request_irq(host->irq, cumanascsi_2_intr, + SA_INTERRUPT, "cumanascsi2", host); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_region; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "cumanascsi2")) { + printk("scsi%d: DMA%d not free, using PIO\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + } + } + + fas216_init(host); + + ret = scsi_add_host(host); + if (ret == 0) + goto out; - scsi_unregister_host(&cumanascsi2_template); - return -ENODEV; + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + out_region: + release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + CUMANASCSI2_FAS216_SIZE); + out_free: + scsi_unregister(host); + + out: + return ret; +} + +static void __devexit cumanascsi2_remove(struct expansion_card *ec) +{ + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + CUMANASCSI2_FAS216_SIZE); + + scsi_unregister(host); +} + +static const struct ecard_id cumanascsi2_cids[] = { + { MANU_CUMANA, PROD_CUMANA_SCSI_2 }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver cumanascsi2_driver = { + .probe = cumanascsi2_probe, + .remove = __devexit_p(cumanascsi2_remove), + .id_table = cumanascsi2_cids, + .drv = { + .name = "cumanascsi2", + }, +}; + +static int __init cumanascsi2_init(void) +{ + return ecard_register_driver(&cumanascsi2_driver); } static void __exit cumanascsi2_exit(void) { - scsi_unregister_host(&cumanascsi2_template); + ecard_remove_driver(&cumanascsi2_driver); } module_init(cumanascsi2_init); @@ -595,4 +573,3 @@ MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines"); MODULE_PARM(term, "1-8i"); MODULE_PARM_DESC(term, "SCSI bus termination"); MODULE_LICENSE("GPL"); - diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c index 9a8e70376295..e1fe32536477 100644 --- a/drivers/acorn/scsi/ecoscsi.c +++ b/drivers/acorn/scsi/ecoscsi.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c index 047e8db0431d..dc1da2c312bc 100644 --- a/drivers/acorn/scsi/eesox.c +++ b/drivers/acorn/scsi/eesox.c @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/scsi/eesox.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -48,18 +48,9 @@ #include -/* Configuration */ -#define EESOX_XTALFREQ 40 -#define EESOX_ASYNC_PERIOD 200 -#define EESOX_SYNC_DEPTH 7 - -/* - * List of devices that the driver will recognise - */ -#define EESOXSCSI_LIST { MANU_EESOX, PROD_EESOX_SCSI2 } - #define EESOX_FAS216_OFFSET 0xc00 #define EESOX_FAS216_SHIFT 3 +#define EESOX_FAS216_SIZE (16 << EESOX_FAS216_SHIFT) #define EESOX_STATUS 0xa00 #define EESOX_STAT_INTR 0x01 @@ -75,11 +66,7 @@ /* * Version */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 3 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.00 (13/11/2002 2.5.47)" /* * Use term=0,1,0,0,0 to turn terminators on/off @@ -88,19 +75,14 @@ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; #define NR_SG 256 -struct control { - unsigned int io_port; - unsigned int control; -}; - -typedef struct { +struct eesoxscsi_info { FAS216_Info info; - struct control control; - + unsigned int ctl_port; + unsigned int control; unsigned int dmaarea; /* Pseudo DMA area */ struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} EESOXScsi_Info; +}; /* Prototype: void eesoxscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on EESOX SCSI card @@ -110,11 +92,11 @@ typedef struct { static void eesoxscsi_irqenable(struct expansion_card *ec, int irqnr) { - struct control *control = (struct control *)ec->irq_data; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - control->control |= EESOX_INTR_ENABLE; + info->control |= EESOX_INTR_ENABLE; - outb(control->control, control->io_port); + outb(info->control, info->ctl_port); } /* Prototype: void eesoxscsi_irqdisable(ec, irqnr) @@ -125,20 +107,16 @@ eesoxscsi_irqenable(struct expansion_card *ec, int irqnr) static void eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr) { - struct control *control = (struct control *)ec->irq_data; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - control->control &= ~EESOX_INTR_ENABLE; + info->control &= ~EESOX_INTR_ENABLE; - outb(control->control, control->io_port); + outb(info->control, info->ctl_port); } static const expansioncard_ops_t eesoxscsi_ops = { - eesoxscsi_irqenable, - eesoxscsi_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = eesoxscsi_irqenable, + .irqdisable = eesoxscsi_irqdisable, }; /* Prototype: void eesoxscsi_terminator_ctl(*host, on_off) @@ -149,16 +127,16 @@ static const expansioncard_ops_t eesoxscsi_ops = { static void eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; unsigned long flags; spin_lock_irqsave(host->host_lock, flags); if (on_off) - info->control.control |= EESOX_TERM_ENABLE; + info->control |= EESOX_TERM_ENABLE; else - info->control.control &= ~EESOX_TERM_ENABLE; + info->control &= ~EESOX_TERM_ENABLE; - outb(info->control.control, info->control.io_port); + outb(info->control, info->ctl_port); spin_unlock_irqrestore(host->host_lock, flags); } @@ -188,7 +166,7 @@ static fasdmatype_t eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; int dmach = host->dma_channel; if (dmach != NO_DMA && @@ -224,7 +202,7 @@ static void eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t dir, int transfer_size) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; unsigned int status; unsigned int length = SCp->this_residual; union { @@ -321,116 +299,6 @@ eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) disable_dma(host->dma_channel); } -/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises EESOX SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -eesoxscsi_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids eesoxscsi_cids[] = - { EESOXSCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "eesox"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while(1) { - EESOXScsi_Info *info; - - ecs[count] = ecard_find(0, eesoxscsi_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (EESOXScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (EESOXScsi_Info *)host->hostdata; - - info->control.io_port = host->io_port + EESOX_CONTROL; - info->control.control = term[count] ? EESOX_TERM_ENABLE : 0; - outb(info->control.control, info->control.io_port); - - ecs[count]->irqaddr = (unsigned char *) - ioaddr(host->io_port + EESOX_STATUS); - ecs[count]->irqmask = EESOX_STAT_INTR; - ecs[count]->irq_data = &info->control; - ecs[count]->ops = (expansioncard_ops_t *)&eesoxscsi_ops; - - info->info.scsi.io_port = host->io_port + EESOX_FAS216_OFFSET; - info->info.scsi.io_shift = EESOX_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = EESOX_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = EESOX_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = EESOX_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = eesoxscsi_dma_setup; - info->info.dma.pseudo = eesoxscsi_dma_pseudo; - info->info.dma.stop = eesoxscsi_dma_stop; - info->dmaarea = host->io_port + EESOX_DMA_OFFSET; - - request_region(host->io_port + EESOX_FAS216_OFFSET, - 16 << EESOX_FAS216_SHIFT, "eesox2-fas"); - - if (host->irq != NO_IRQ && - request_irq(host->irq, eesoxscsi_intr, - SA_INTERRUPT, "eesox", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; - } - - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "eesox")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } - - fas216_init(host); - ++count; - } - return count; -} - -/* Prototype: int eesoxscsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - */ -int eesoxscsi_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && - host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) - ecard_release(ecs[i]); - return 0; -} - /* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -438,15 +306,15 @@ int eesoxscsi_release(struct Scsi_Host *host) */ const char *eesoxscsi_info(struct Scsi_Host *host) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; static char string[100], *p; p = string; p += sprintf(p, "%s ", host->hostt->name); p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + p += sprintf(p, "v%s terminators o%s", + VERSION, + info->control & EESOX_TERM_ENABLE ? "n" : "ff"); return string; } @@ -500,7 +368,7 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, { int pos, begin; struct Scsi_Host *host; - EESOXScsi_Info *info; + struct eesoxscsi_info *info; Scsi_Device *scd; host = scsi_host_hn_get(host_no); @@ -510,28 +378,28 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, if (inout == 1) return eesoxscsi_set_proc_info(host, buffer, length); - info = (EESOXScsi_Info *)host->hostdata; + info = (struct eesoxscsi_info *)host->hostdata; begin = 0; pos = sprintf(buffer, - "EESOX SCSI driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + "EESOX SCSI driver version v%s\n", + VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", - info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + info->control & EESOX_TERM_ENABLE ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:\n"); + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; - proc_print_scsidevice (scd, buffer, &len, pos); + proc_print_scsidevice(scd, buffer, &len, pos); pos += len; - pos += sprintf (buffer+pos, "Extensions: "); + pos += sprintf(buffer+pos, "Extensions: "); if (scd->tagged_supported) - pos += sprintf (buffer+pos, "TAG %sabled [%d] ", + pos += sprintf(buffer+pos, "TAG %sabled [%d] ", scd->tagged_queue ? "en" : "dis", scd->current_tag); pos += sprintf (buffer+pos, "\n"); @@ -553,35 +421,144 @@ static Scsi_Host_Template eesox_template = { .module = THIS_MODULE, .proc_info = eesoxscsi_proc_info, .name = "EESOX SCSI", - .detect = eesoxscsi_detect, - .release = eesoxscsi_release, .info = eesoxscsi_info, - .can_queue = 1, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, .eh_device_reset_handler = fas216_eh_device_reset, .eh_abort_handler = fas216_eh_abort, + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "eesox", }; -static int __init eesox_init(void) +static int __devinit +eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) { - scsi_register_host(&eesox_template); - if (eesox_template.present) - return 0; + struct Scsi_Host *host; + struct eesoxscsi_info *info; + int ret = -ENOMEM; + + host = scsi_register(&eesox_template, + sizeof(struct eesoxscsi_info)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); + host->irq = ec->irq; + host->dma_channel = ec->dma; + + if (!request_region(host->io_port + EESOX_FAS216_OFFSET, + EESOX_FAS216_SIZE, "eesox2-fas")) { + ret = -EBUSY; + goto out_free; + } + + ecard_set_drvdata(ec, host); + + info = (struct eesoxscsi_info *)host->hostdata; + info->ctl_port = host->io_port + EESOX_CONTROL; + info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0; + outb(info->control, info->ctl_port); + + ec->irqaddr = (unsigned char *)ioaddr(host->io_port + EESOX_STATUS); + ec->irqmask = EESOX_STAT_INTR; + ec->irq_data = info; + ec->ops = (expansioncard_ops_t *)&eesoxscsi_ops; + + info->info.scsi.io_port = host->io_port + EESOX_FAS216_OFFSET; + info->info.scsi.io_shift = EESOX_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.dma.setup = eesoxscsi_dma_setup; + info->info.dma.pseudo = eesoxscsi_dma_pseudo; + info->info.dma.stop = eesoxscsi_dma_stop; + info->dmaarea = host->io_port + EESOX_DMA_OFFSET; + + ret = request_irq(host->irq, eesoxscsi_intr, + SA_INTERRUPT, "eesox", host); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_region; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "eesox")) { + printk("scsi%d: DMA%d not free, DMA disabled\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + } + } - scsi_unregister_host(&eesox_template); - return -ENODEV; + fas216_init(host); + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + out_region: + release_region(host->io_port + EESOX_FAS216_OFFSET, + EESOX_FAS216_SIZE); + out_free: + scsi_unregister(host); + out: + return ret; +} + +static void __devexit eesoxscsi_remove(struct expansion_card *ec) +{ + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + release_region(host->io_port + EESOX_FAS216_OFFSET, EESOX_FAS216_SIZE); + scsi_unregister(host); +} + +static const struct ecard_id eesoxscsi_cids[] = { + { MANU_EESOX, PROD_EESOX_SCSI2 }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver eesoxscsi_driver = { + .probe = eesoxscsi_probe, + .remove = __devexit_p(eesoxscsi_remove), + .id_table = eesoxscsi_cids, + .drv = { + .name = "eesoxscsi", + }, +}; + +static int __init eesox_init(void) +{ + return ecard_register_driver(&eesoxscsi_driver); } static void __exit eesox_exit(void) { - scsi_unregister_host(&eesox_template); + ecard_remove_driver(&eesoxscsi_driver); } module_init(eesox_init); diff --git a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c index 77bd624a7b95..158f1be92658 100644 --- a/drivers/acorn/scsi/fas216.c +++ b/drivers/acorn/scsi/fas216.c @@ -93,14 +93,18 @@ #undef SCSI2_TAG #undef DEBUG_CONNECT -#undef DEBUG_BUSSERVICE -#undef DEBUG_FUNCTIONDONE #undef DEBUG_MESSAGES #undef CHECK_STRUCTURE -static struct { int stat, ssr, isr, ph; } list[8]; -static int ptr; +#define LOG_CONNECT (1 << 0) +#define LOG_BUSSERVICE (1 << 1) +#define LOG_FUNCTIONDONE (1 << 2) +#define LOG_MESSAGES (1 << 3) +#define LOG_BUFFER (1 << 4) +#define LOG_ERROR (1 << 8) + +static int level_mask = LOG_ERROR; static void fas216_dumpstate(FAS216_Info *info) { @@ -120,6 +124,13 @@ static void fas216_dumpstate(FAS216_Info *info) inb(REG_CNTL3(info)), inb(REG_CTCH(info))); } +static void print_SCp(Scsi_Pointer *SCp, const char *prefix, const char *suffix) +{ + printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s", + prefix, SCp->ptr, SCp->this_residual, SCp->buffer, + SCp->buffers_residual, suffix); +} + static void fas216_dumpinfo(FAS216_Info *info) { static int used = 0; @@ -140,9 +151,7 @@ static void fas216_dumpinfo(FAS216_Info *info) info->scsi.type, info->scsi.phase, info->scsi.reconnected.target, info->scsi.reconnected.lun, info->scsi.reconnected.tag); - printk(" SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual, - info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual); + print_SCp(&info->scsi.SCp, " SCp={ ", " }\n"); printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", info->scsi.async_stp, info->scsi.disconnectable, info->scsi.aborting); @@ -156,7 +165,7 @@ static void fas216_dumpinfo(FAS216_Info *info) info->ifcfg.clockrate, info->ifcfg.select_timeout, info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); for (i = 0; i < 8; i++) { - printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", + printk(" busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", i, info->busyluns[i], i, info->device[i].disconnect_ok, info->device[i].stp, info->device[i].sof, info->device[i].sync_state); @@ -229,29 +238,73 @@ static char fas216_target(FAS216_Info *info) return 'H'; } +static void fas216_log(FAS216_Info *info, int level, char *fmt, ...) +{ + va_list args; + static char buf[1024]; + + if (level != 0 && !(level & level_mask)) + return; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + printk("scsi%d.%c: %s\n", info->host->host_no, fas216_target(info), buf); +} + +#define PH_SIZE 32 + +static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE]; +static int ph_ptr; + static void add_debug_list(int stat, int ssr, int isr, int ph) { - list[ptr].stat = stat; - list[ptr].ssr = ssr; - list[ptr].isr = isr; - list[ptr].ph = ph; + ph_list[ph_ptr].stat = stat; + ph_list[ph_ptr].ssr = ssr; + ph_list[ph_ptr].isr = isr; + ph_list[ph_ptr].ph = ph; + + ph_ptr = (ph_ptr + 1) & (PH_SIZE-1); +} + +static struct { int command; void *from; } cmd_list[8]; +static int cmd_ptr; + +static void fas216_cmd(FAS216_Info *info, unsigned int command) +{ + cmd_list[cmd_ptr].command = command; + cmd_list[cmd_ptr].from = __builtin_return_address(0); - ptr = (ptr + 1) & 7; + cmd_ptr = (cmd_ptr + 1) & 7; + + outb(command, REG_CMD(info)); } static void print_debug_list(void) { int i; - i = ptr; + i = ph_ptr; + + printk(KERN_ERR "SCSI IRQ trail\n"); + do { + printk(" %02x:%02x:%02x:%1x", + ph_list[i].stat, ph_list[i].ssr, + ph_list[i].isr, ph_list[i].ph); + i = (i + 1) & (PH_SIZE - 1); + if (((i ^ ph_ptr) & 7) == 0) + printk("\n"); + } while (i != ph_ptr); + if ((i ^ ph_ptr) & 7) + printk("\n"); - printk(KERN_ERR "SCSI IRQ trail: "); + i = cmd_ptr; + printk(KERN_ERR "FAS216 commands: "); do { - printk("%02X:%02X:%02X:%1X ", - list[i].stat, list[i].ssr, - list[i].isr, list[i].ph); + printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from); i = (i + 1) & 7; - } while (i != ptr); + } while (i != cmd_ptr); printk("\n"); } @@ -299,10 +352,9 @@ fas216_get_last_msg(FAS216_Info *info, int pos) packed_msg = msg->msg[0]; } -#ifdef DEBUG_MESSAGES - printk("Message: %04X found at position %02X\n", - packed_msg, pos); -#endif + fas216_log(info, LOG_MESSAGES, + "Message: %04x found at position %02x\n", packed_msg, pos); + return packed_msg; } @@ -313,8 +365,7 @@ fas216_get_last_msg(FAS216_Info *info, int pos) * : ns - period in ns (between subsequent bytes) * Returns : Value suitable for REG_STP */ -static int -fas216_syncperiod(FAS216_Info *info, int ns) +static int fas216_syncperiod(FAS216_Info *info, int ns) { int value = (info->ifcfg.clockrate * ns) / 1000; @@ -336,8 +387,7 @@ fas216_syncperiod(FAS216_Info *info, int ns) * a transfer period >= 200ns - otherwise the chip will violate * the SCSI timings. */ -static void -fas216_set_sync(FAS216_Info *info, int target) +static void fas216_set_sync(FAS216_Info *info, int target) { outb(info->device[target].sof, REG_SOF(info)); outb(info->device[target].stp, REG_STP(info)); @@ -365,9 +415,9 @@ fas216_set_sync(FAS216_Info *info, int target) * Using the correct method assures compatibility with wide data * transfers and future enhancements. * - * We will always initiate a synchronous transfer negociation request on + * We will always initiate a synchronous transfer negotiation request on * every INQUIRY or REQUEST SENSE message, unless the target itself has - * at some point performed a synchronous transfer negociation request, or + * at some point performed a synchronous transfer negotiation request, or * we have synchronous transfers disabled for this device. */ @@ -376,8 +426,7 @@ fas216_set_sync(FAS216_Info *info, int target) * Params : info - state structure for interface * : msg - message from target */ -static void -fas216_handlesync(FAS216_Info *info, char *msg) +static void fas216_handlesync(FAS216_Info *info, char *msg) { struct fas216_device *dev = &info->device[info->SCpnt->target]; enum { sync, async, none, reject } res = none; @@ -393,7 +442,7 @@ fas216_handlesync(FAS216_Info *info, char *msg) * message with a MESSAGE REJECT message. * * Hence, if we get this condition, we disable - * negociation for this device. + * negotiation for this device. */ if (dev->sync_state == neg_inprogress) { dev->sync_state = neg_invalid; @@ -411,14 +460,14 @@ fas216_handlesync(FAS216_Info *info, char *msg) res = reject; break; - /* We were not negociating a synchronous transfer, - * but the device sent us a negociation request. + /* We were not negotiating a synchronous transfer, + * but the device sent us a negotiation request. * Honour the request by sending back a SDTR * message containing our capability, limited by * the targets capability. */ default: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); if (msg[4] > info->ifcfg.sync_max_depth) msg[4] = info->ifcfg.sync_max_depth; if (msg[3] < 1000 / info->ifcfg.clockrate) @@ -437,7 +486,7 @@ fas216_handlesync(FAS216_Info *info, char *msg) res = sync; break; - /* We initiated the synchronous transfer negociation, + /* We initiated the synchronous transfer negotiation, * and have successfully received a response from the * target. The synchronous transfer agreement has been * reached. Note: if the values returned are out of our @@ -466,7 +515,7 @@ fas216_handlesync(FAS216_Info *info, char *msg) break; case reject: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; @@ -488,8 +537,7 @@ fas216_handlesync(FAS216_Info *info, char *msg) * Params : info - state structure for interface * : msg - message from target */ -static void -fas216_handlewide(FAS216_Info *info, char *msg) +static void fas216_handlewide(FAS216_Info *info, char *msg) { struct fas216_device *dev = &info->device[info->SCpnt->target]; enum { wide, bit8, none, reject } res = none; @@ -505,7 +553,7 @@ fas216_handlewide(FAS216_Info *info, char *msg) * WDTR message with a MESSAGE REJECT message. * * Hence, if we get this condition, we never - * reattempt negociation for this device. + * reattempt negotiation for this device. */ if (dev->wide_state == neg_inprogress) { dev->wide_state = neg_invalid; @@ -523,14 +571,14 @@ fas216_handlewide(FAS216_Info *info, char *msg) res = reject; break; - /* We were not negociating a wide data transfer, - * but the device sent is a negociation request. + /* We were not negotiating a wide data transfer, + * but the device sent is a negotiation request. * Honour the request by sending back a WDTR * message containing our capability, limited by * the targets capability. */ default: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); if (msg[3] > info->ifcfg.wide_max_size) msg[3] = info->ifcfg.wide_max_size; @@ -542,7 +590,7 @@ fas216_handlewide(FAS216_Info *info, char *msg) res = wide; break; - /* We initiated the wide data transfer negociation, + /* We initiated the wide data transfer negotiation, * and have successfully received a response from the * target. The synchronous transfer agreement has been * reached. Note: if the values returned are out of our @@ -567,7 +615,7 @@ fas216_handlewide(FAS216_Info *info, char *msg) break; case reject: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; @@ -586,13 +634,14 @@ fas216_handlewide(FAS216_Info *info, char *msg) * Params : info - interface's local pointer to update * bytes_transferred - number of bytes transferred */ -static void -fas216_updateptrs(FAS216_Info *info, int bytes_transferred) +static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) { Scsi_Pointer *SCp = &info->scsi.SCp; fas216_checkmagic(info); + BUG_ON(bytes_transferred < 0); + info->SCpnt->request_bufflen -= bytes_transferred; while (bytes_transferred != 0) { @@ -623,8 +672,7 @@ fas216_updateptrs(FAS216_Info *info, int bytes_transferred) * direction - direction to transfer data (DMA_OUT/DMA_IN) * Notes : this is incredibly slow */ -static void -fas216_pio(FAS216_Info *info, fasdmadir_t direction) +static void fas216_pio(FAS216_Info *info, fasdmadir_t direction) { fas216_checkmagic(info); @@ -634,53 +682,94 @@ fas216_pio(FAS216_Info *info, fasdmadir_t direction) put_next_SCp_byte(&info->scsi.SCp, inb(REG_FF(info))); } +static void fas216_cleanuptransfer(FAS216_Info *info) +{ + unsigned long total, residual, fifo; + + if (info->dma.transfer_type == fasdma_real_all) + total = info->SCpnt->request_bufflen; + else + total = info->scsi.SCp.this_residual; + + residual = inb(REG_CTCL(info)) + (inb(REG_CTCM(info)) << 8) + + (inb(REG_CTCH(info)) << 16); + + fifo = inb(REG_CFIS(info)) & CFIS_CF; + + fas216_log(info, LOG_BUFFER, "cleaning up from previous " + "transfer: length 0x%06x, residual 0x%x, fifo %d", + total, residual, fifo); + + /* + * If we were performing Data-Out, the transfer counter + * counts down each time a byte is transferred by the + * host to the FIFO. This means we must include the + * bytes left in the FIFO from the transfer counter. + */ + if (info->scsi.phase == PHASE_DATAOUT) { + residual += fifo; + fifo = 0; + } + + if (info->dma.transfer_type != fasdma_none && + info->dma.transfer_type != fasdma_pio) { + fas216_updateptrs(info, total - residual); + } + + /* + * If we were performing Data-In, then the FIFO counter + * contains the number of bytes not transferred via DMA + * from the on-board FIFO. Read them manually. + */ + if (info->scsi.phase == PHASE_DATAIN) { + while (fifo && info->scsi.SCp.ptr) { + *info->scsi.SCp.ptr = inb(REG_FF(info)); + fas216_updateptrs(info, 1); + fifo--; + } + } + + info->dma.transfer_type = fasdma_none; +} + /* Function: void fas216_starttransfer(FAS216_Info *info, * fasdmadir_t direction) * Purpose : Start a DMA/PIO transfer off of/on to card * Params : info - interface from which device disconnected from * direction - transfer direction (DMA_OUT/DMA_IN) */ -static void -fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) +static void fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction) { fasdmatype_t dmatype; + int phase = (direction == DMA_OUT) ? PHASE_DATAOUT : PHASE_DATAIN; fas216_checkmagic(info); - info->scsi.phase = (direction == DMA_OUT) ? - PHASE_DATAOUT : PHASE_DATAIN; + if (phase != info->scsi.phase) { + info->scsi.phase = phase; - if (info->dma.transfer_type != fasdma_none && - info->dma.transfer_type != fasdma_pio) { - unsigned long total, residual; - - if (info->dma.transfer_type == fasdma_real_all) - total = info->SCpnt->request_bufflen; - else - total = info->scsi.SCp.this_residual; - - residual = (inb(REG_CFIS(info)) & CFIS_CF) + - inb(REG_CTCL(info)) + - (inb(REG_CTCM(info)) << 8) + - (inb(REG_CTCH(info)) << 16); - fas216_updateptrs(info, total - residual); + if (direction == DMA_OUT) + fas216_cmd(info, CMD_FLUSHFIFO); + } else { + fas216_cleanuptransfer(info); } - info->dma.transfer_type = fasdma_none; + + fas216_log(info, LOG_BUFFER, + "starttransfer: buffer %p length 0x%06x reqlen 0x%06x", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual, + info->SCpnt->request_bufflen); if (!info->scsi.SCp.ptr) { - printk("scsi%d.%c: null buffer passed to " - "fas216_starttransfer\n", info->host->host_no, - fas216_target(info)); + fas216_log(info, LOG_ERROR, "null buffer passed to " + "fas216_starttransfer"); + print_SCp(&info->scsi.SCp, "SCp: ", "\n"); + print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n"); return; } - /* flush FIFO */ - if (flush_fifo) - outb(CMD_FLUSHFIFO, REG_CMD(info)); - /* - * Default to PIO mode or DMA mode if we have a synchronous - * transfer agreement. + * Default to PIO mode or DMA mode if we have + * a synchronous transfer agreement. */ if (info->device[info->SCpnt->target].sof && info->dma.setup) dmatype = fasdma_real_all; @@ -694,41 +783,45 @@ fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) switch (dmatype) { case fasdma_pio: + fas216_log(info, LOG_BUFFER, "PIO transfer"); outb(0, REG_SOF(info)); outb(info->scsi.async_stp, REG_STP(info)); outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); fas216_pio(info, direction); break; case fasdma_pseudo: + fas216_log(info, LOG_BUFFER, "pseudo transfer"); outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); info->dma.pseudo(info->host, &info->scsi.SCp, direction, info->SCpnt->transfersize); break; case fasdma_real_block: + fas216_log(info, LOG_BUFFER, "block dma transfer"); outb(info->scsi.SCp.this_residual, REG_STCL(info)); outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); break; case fasdma_real_all: + fas216_log(info, LOG_BUFFER, "total dma transfer"); outb(info->SCpnt->request_bufflen, REG_STCL(info)); outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info)); outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); break; default: - printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, LOG_BUFFER | LOG_ERROR, + "invalid FAS216 DMA type"); break; } } @@ -737,51 +830,49 @@ fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) * Purpose : Stop a DMA transfer onto / off of the card * Params : info - interface from which device disconnected from */ -static void -fas216_stoptransfer(FAS216_Info *info) +static void fas216_stoptransfer(FAS216_Info *info) { fas216_checkmagic(info); - if (info->dma.transfer_type != fasdma_none && - info->dma.transfer_type != fasdma_pio) { - unsigned long total, residual; + if ((info->dma.transfer_type == fasdma_real_all || + info->dma.transfer_type == fasdma_real_block) && + info->dma.stop) + info->dma.stop(info->host, &info->scsi.SCp); - if ((info->dma.transfer_type == fasdma_real_all || - info->dma.transfer_type == fasdma_real_block) && - info->dma.stop) - info->dma.stop(info->host, &info->scsi.SCp); - - if (info->dma.transfer_type == fasdma_real_all) - total = info->SCpnt->request_bufflen; - else - total = info->scsi.SCp.this_residual; + fas216_cleanuptransfer(info); - residual = (inb(REG_CFIS(info)) & CFIS_CF) + - inb(REG_CTCL(info)) + - (inb(REG_CTCM(info)) << 8) + - (inb(REG_CTCH(info)) << 16); - fas216_updateptrs(info, total - residual); - info->dma.transfer_type = fasdma_none; - } if (info->scsi.phase == PHASE_DATAOUT) - outb(CMD_FLUSHFIFO, REG_CMD(info)); + fas216_cmd(info, CMD_FLUSHFIFO); +} + +static void fas216_aborttransfer(FAS216_Info *info) +{ + fas216_checkmagic(info); + + if ((info->dma.transfer_type == fasdma_real_all || + info->dma.transfer_type == fasdma_real_block) && + info->dma.stop) + info->dma.stop(info->host, &info->scsi.SCp); + + info->dma.transfer_type = fasdma_none; + fas216_cmd(info, CMD_FLUSHFIFO); } /* Function: void fas216_disconnected_intr(FAS216_Info *info) * Purpose : handle device disconnection * Params : info - interface from which device disconnected from */ -static void -fas216_disconnect_intr(FAS216_Info *info) +static void fas216_disconnect_intr(FAS216_Info *info) { fas216_checkmagic(info); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no, - fas216_target(info), info->scsi.phase); -#endif + fas216_log(info, LOG_CONNECT, "disconnect phase=%02x", + info->scsi.phase); + msgqueue_flush(&info->scsi.msgs); + fas216_cmd(info, CMD_ENABLESEL); + switch (info->scsi.phase) { case PHASE_SELECTION: /* while selecting - no target */ case PHASE_SELSTEPS: @@ -789,7 +880,6 @@ fas216_disconnect_intr(FAS216_Info *info) break; case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ - outb(CMD_ENABLESEL, REG_CMD(info)); info->scsi.disconnectable = 1; info->scsi.reconnected.tag = 0; info->scsi.phase = PHASE_IDLE; @@ -841,19 +931,16 @@ fas216_reselected_intr(FAS216_Info *info) info->device[SCpnt->target].sync_state = neg_wait; } -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no, - fas216_target(info), info->scsi.phase); -#endif + fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase); if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) { printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", info->host->host_no); - outb(CMD_SETATN, REG_CMD(info)); - outb(CMD_MSGACCEPTED, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); return; } @@ -877,11 +964,11 @@ fas216_reselected_intr(FAS216_Info *info) * Something went wrong - send an initiator error to * the target. */ - outb(CMD_SETATN, REG_CMD(info)); - outb(CMD_MSGACCEPTED, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); return; } @@ -903,6 +990,9 @@ fas216_reselected_intr(FAS216_Info *info) info->scsi.reconnected.lun = identify_msg; info->scsi.reconnected.tag = 0; + /* set up for synchronous transfers */ + fas216_set_sync(info, target); + ok = 0; if (info->scsi.disconnectable && info->SCpnt && info->SCpnt->target == target && info->SCpnt->lun == identify_msg) @@ -922,12 +1012,12 @@ fas216_reselected_intr(FAS216_Info *info) * record of this command, we can't send * an INITIATOR DETECTED ERROR message. */ - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); info->scsi.phase = PHASE_MSGOUT_EXPECT; } - outb(CMD_MSGACCEPTED, REG_CMD(info)); + fas216_cmd(info, CMD_MSGACCEPTED); } /* Function: void fas216_finish_reconnect(FAS216_Info *info) @@ -939,28 +1029,20 @@ fas216_finish_reconnect(FAS216_Info *info) { fas216_checkmagic(info); -#ifdef DEBUG_CONNECT - printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", + fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x", info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag, info->scsi.reconnected.target, info->scsi.reconnected.lun, info->scsi.reconnected.tag); -#endif if (info->scsi.disconnectable && info->SCpnt) { info->scsi.disconnectable = 0; if (info->SCpnt->target == info->scsi.reconnected.target && info->SCpnt->lun == info->scsi.reconnected.lun && info->SCpnt->tag == info->scsi.reconnected.tag) { -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: reconnected", - info->host->host_no, fas216_target(info)); -#endif + fas216_log(info, LOG_CONNECT, "reconnected"); } else { queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: had to move command to disconnected queue\n", - info->host->host_no, fas216_target(info)); -#endif + fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue"); info->SCpnt = NULL; } } @@ -969,20 +1051,19 @@ fas216_finish_reconnect(FAS216_Info *info) info->scsi.reconnected.target, info->scsi.reconnected.lun, info->scsi.reconnected.tag); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: had to get command", - info->host->host_no, fas216_target(info)); -#endif + fas216_log(info, LOG_CONNECT, "had to get command"); } if (!info->SCpnt) { - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); + #if 0 if (info->scsi.reconnected.tag) msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); else #endif msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; } else { @@ -990,122 +1071,14 @@ fas216_finish_reconnect(FAS216_Info *info) * Restore data pointer from SAVED data pointer */ info->scsi.SCp = info->SCpnt->SCp; -#ifdef DEBUG_CONNECT - printk(", data pointers: [%p, %X]", + fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif - } -#ifdef DEBUG_CONNECT - printk("\n"); -#endif -} - -static int fas216_wait_cmd(FAS216_Info *info, int cmd) -{ - int tout; - int stat; - - outb(cmd, REG_CMD(info)); - - for (tout = 1000; tout; tout -= 1) { - stat = inb(REG_STAT(info)); - if (stat & STAT_INT) - break; - udelay(1); } - - return stat; -} - -static int fas216_get_msg_byte(FAS216_Info *info) -{ - int stat; - - stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - inb(REG_INST(info)); - - stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - inb(REG_INST(info)); - - return inb(REG_FF(info)); - -timedout: - printk("scsi%d.%c: timed out waiting for message byte\n", - info->host->host_no, fas216_target(info)); - return -1; - -unexpected_phase_change: - printk("scsi%d.%c: unexpected phase change: status = %02X\n", - info->host->host_no, fas216_target(info), stat); - - return -2; } -/* Function: void fas216_message(FAS216_Info *info) - * Purpose : handle a function done interrupt from FAS216 chip - * Params : info - interface which caused function done interrupt - */ -static void fas216_message(FAS216_Info *info) +static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen) { - unsigned char *message = info->scsi.message; - unsigned int msglen = 1, i; - int msgbyte = 0; - - fas216_checkmagic(info); - - message[0] = inb(REG_FF(info)); - - if (message[0] == EXTENDED_MESSAGE) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) { - message[1] = msgbyte; - - for (msglen = 2; msglen < message[1] + 2; msglen++) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) - message[msglen] = msgbyte; - else - break; - } - } - } - - info->scsi.msglen = msglen; - -#ifdef DEBUG_MESSAGES - { - int i; - - printk("scsi%d.%c: message in: ", - info->host->host_no, fas216_target(info)); - for (i = 0; i < msglen; i++) - printk("%02X ", message[i]); - printk("\n"); - } -#endif - - if (info->scsi.phase == PHASE_RECONNECTED) { - if (message[0] == SIMPLE_QUEUE_TAG) - info->scsi.reconnected.tag = message[1]; - fas216_finish_reconnect(info); - info->scsi.phase = PHASE_MSGIN; - } + int i; switch (message[0]) { case COMMAND_COMPLETE: @@ -1131,11 +1104,9 @@ static void fas216_message(FAS216_Info *info) */ info->SCpnt->SCp = info->scsi.SCp; info->SCpnt->SCp.sent_command = 0; -#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk("scsi%d.%c: save data pointers: [%p, %X]\n", - info->host->host_no, fas216_target(info), + fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, + "save data pointers: [%p, %X]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif break; case RESTORE_POINTERS: @@ -1146,11 +1117,9 @@ static void fas216_message(FAS216_Info *info) * Restore current data pointer from SAVED data pointer */ info->scsi.SCp = info->SCpnt->SCp; -#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk("scsi%d.%c: restore data pointers: [%p, %X]\n", - info->host->host_no, fas216_target(info), + fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, + "restore data pointers: [%p, 0x%x]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif break; case DISCONNECT: @@ -1174,8 +1143,7 @@ static void fas216_message(FAS216_Info *info) break; default: - printk("scsi%d.%c: reject, last message %04X\n", - info->host->host_no, fas216_target(info), + fas216_log(info, 0, "reject, last message 0x%04x", fas216_get_last_msg(info, info->scsi.msgin_fifo)); } break; @@ -1188,9 +1156,7 @@ static void fas216_message(FAS216_Info *info) goto unrecognised; /* handled above - print a warning since this is untested */ - printk("scsi%d.%c: reconnect queue tag %02X\n", - info->host->host_no, fas216_target(info), - message[1]); + fas216_log(info, 0, "reconnect queue tag 0x%02x", message[1]); break; case EXTENDED_MESSAGE: @@ -1198,11 +1164,11 @@ static void fas216_message(FAS216_Info *info) goto unrecognised; switch (message[2]) { - case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ + case EXTENDED_SDTR: /* Sync transfer negotiation request/reply */ fas216_handlesync(info, message); break; - case EXTENDED_WDTR: /* Wide transfer negociation request/reply */ + case EXTENDED_WDTR: /* Wide transfer negotiation request/reply */ fas216_handlewide(info, message); break; @@ -1214,12 +1180,10 @@ static void fas216_message(FAS216_Info *info) default: goto unrecognised; } - outb(CMD_MSGACCEPTED, REG_CMD(info)); return; unrecognised: - printk("scsi%d.%c: unrecognised message, rejecting\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, 0, "unrecognised message, rejecting"); printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info)); for (i = 0; i < msglen; i++) printk("%s%02X", i & 31 ? " " : "\n ", message[i]); @@ -1230,68 +1194,192 @@ unrecognised: * I can't use SETATN since the chip gives me an * invalid command interrupt when I do. Weird. */ -outb(CMD_NOP, REG_CMD(info)); +fas216_cmd(info, CMD_NOP); fas216_dumpstate(info); - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; fas216_dumpstate(info); - outb(CMD_MSGACCEPTED, REG_CMD(info)); } -/* Function: void fas216_send_command(FAS216_Info *info) - * Purpose : send a command to a target after all message bytes have been sent - * Params : info - interface which caused bus service - */ -static void fas216_send_command(FAS216_Info *info) +static int fas216_wait_cmd(FAS216_Info *info, int cmd) { - int i; - - fas216_checkmagic(info); - - outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info)); - outb(CMD_FLUSHFIFO, REG_CMD(info)); + int tout; + int stat; - /* load command */ - for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++) - outb(info->SCpnt->cmnd[i], REG_FF(info)); + fas216_cmd(info, cmd); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + for (tout = 1000; tout; tout -= 1) { + stat = inb(REG_STAT(info)); + if (stat & (STAT_INT|STAT_PARITYERROR)) + break; + udelay(1); + } - info->scsi.phase = PHASE_COMMAND; + return stat; } -/* Function: void fas216_send_messageout(FAS216_Info *info, int start) - * Purpose : handle bus service to send a message - * Params : info - interface which caused bus service - * Note : We do not allow the device to change the data direction! - */ -static void fas216_send_messageout(FAS216_Info *info, int start) +static int fas216_get_msg_byte(FAS216_Info *info) { - unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); + unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); - fas216_checkmagic(info); + if ((stat & STAT_INT) == 0) + goto timedout; - outb(CMD_FLUSHFIFO, REG_CMD(info)); + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; - if (tot_msglen) { - struct message *msg; - int msgnr = 0; + inb(REG_INST(info)); - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - int i; + stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); - for (i = start; i < msg->length; i++) - outb(msg->msg[i], REG_FF(info)); + if ((stat & STAT_INT) == 0) + goto timedout; - msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); - start = 0; + if (stat & STAT_PARITYERROR) + goto parity_error; + + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; + + inb(REG_INST(info)); + + return inb(REG_FF(info)); + +timedout: + fas216_log(info, LOG_ERROR, "timed out waiting for message byte"); + return -1; + +unexpected_phase_change: + fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat); + return -2; + +parity_error: + fas216_log(info, LOG_ERROR, "parity error during message in phase"); + return -3; +} + +/* Function: void fas216_message(FAS216_Info *info) + * Purpose : handle a function done interrupt from FAS216 chip + * Params : info - interface which caused function done interrupt + */ +static void fas216_message(FAS216_Info *info) +{ + unsigned char *message = info->scsi.message; + unsigned int msglen = 1; + int msgbyte = 0; + + fas216_checkmagic(info); + + message[0] = inb(REG_FF(info)); + + if (message[0] == EXTENDED_MESSAGE) { + msgbyte = fas216_get_msg_byte(info); + + if (msgbyte >= 0) { + message[1] = msgbyte; + + for (msglen = 2; msglen < message[1] + 2; msglen++) { + msgbyte = fas216_get_msg_byte(info); + + if (msgbyte >= 0) + message[msglen] = msgbyte; + else + break; + } + } + } + + if (msgbyte == -3) + goto parity_error; + + info->scsi.msglen = msglen; + +#ifdef DEBUG_MESSAGES + { + int i; + + printk("scsi%d.%c: message in: ", + info->host->host_no, fas216_target(info)); + for (i = 0; i < msglen; i++) + printk("%02X ", message[i]); + printk("\n"); + } +#endif + + if (info->scsi.phase == PHASE_RECONNECTED) { + if (message[0] == SIMPLE_QUEUE_TAG) + info->scsi.reconnected.tag = message[1]; + fas216_finish_reconnect(info); + info->scsi.phase = PHASE_MSGIN; + } + + fas216_parse_message(info, message, msglen); + fas216_cmd(info, CMD_MSGACCEPTED); + return; + +parity_error: + fas216_cmd(info, CMD_SETATN); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); + return; +} + +/* Function: void fas216_send_command(FAS216_Info *info) + * Purpose : send a command to a target after all message bytes have been sent + * Params : info - interface which caused bus service + */ +static void fas216_send_command(FAS216_Info *info) +{ + int i; + + fas216_checkmagic(info); + + fas216_cmd(info, CMD_NOP|CMD_WITHDMA); + fas216_cmd(info, CMD_FLUSHFIFO); + + /* load command */ + for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++) + outb(info->SCpnt->cmnd[i], REG_FF(info)); + + fas216_cmd(info, CMD_TRANSFERINFO); + + info->scsi.phase = PHASE_COMMAND; +} + +/* Function: void fas216_send_messageout(FAS216_Info *info, int start) + * Purpose : handle bus service to send a message + * Params : info - interface which caused bus service + * Note : We do not allow the device to change the data direction! + */ +static void fas216_send_messageout(FAS216_Info *info, int start) +{ + unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); + + fas216_checkmagic(info); + + fas216_cmd(info, CMD_FLUSHFIFO); + + if (tot_msglen) { + struct message *msg; + int msgnr = 0; + + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + int i; + + for (i = start; i < msg->length; i++) + outb(msg->msg[i], REG_FF(info)); + + msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); + start = 0; } } else outb(NOP, REG_FF(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); info->scsi.phase = PHASE_MSGOUT; } @@ -1306,10 +1394,9 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne { fas216_checkmagic(info); -#ifdef DEBUG_BUSSERVICE - printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); -#endif + fas216_log(info, LOG_BUSSERVICE, + "bus service: stat=%02x ssr=%02x phase=%02x", + stat, ssr, info->scsi.phase); switch (info->scsi.phase) { case PHASE_SELECTION: @@ -1337,7 +1424,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne break; } - outb(CMD_NOP, REG_CMD(info)); + fas216_cmd(info, CMD_NOP); #define STATE(st,ph) ((ph) << 3 | (st)) /* This table describes the legal SCSI state transitions, @@ -1352,11 +1439,11 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ - fas216_starttransfer(info, DMA_IN, 0); + fas216_starttransfer(info, DMA_IN); return; case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 0); + fas216_starttransfer(info, DMA_OUT); return; /* Reselmsgin -> Data Out */ @@ -1366,7 +1453,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 1); + fas216_starttransfer(info, DMA_OUT); return; /* Reselmsgin -> Status */ @@ -1381,7 +1468,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ status: - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); + fas216_cmd(info, CMD_INITCMDCOMPLETE); info->scsi.phase = PHASE_STATUS; return; @@ -1392,8 +1479,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_FLUSHFIFO, REG_CMD(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_FLUSHFIFO); + fas216_cmd(info, CMD_TRANSFERINFO); info->scsi.phase = PHASE_MSGIN; return; @@ -1401,7 +1488,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_MESGIN, PHASE_RECONNECTED): case STATE(STAT_MESGIN, PHASE_MSGIN): info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); return; /* Reselmsgin -> Command */ @@ -1412,11 +1499,43 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne fas216_send_command(info); info->scsi.phase = PHASE_COMMAND; return; - /* Selection -> Message Out */ + + + /* + * Selection -> Message Out + */ case STATE(STAT_MESGOUT, PHASE_SELECTION): fas216_send_messageout(info, 1); return; - /* Any -> Message Out */ + + /* + * Message Out -> Message Out + */ + case STATE(STAT_MESGOUT, PHASE_SELSTEPS): + case STATE(STAT_MESGOUT, PHASE_MSGOUT): + /* + * If we get another message out phase, this usually + * means some parity error occurred. Resend complete + * set of messages. If we have more than one byte to + * send, we need to assert ATN again. + */ + if (info->device[info->SCpnt->target].parity_check) { + /* + * We were testing... good, the device + * supports parity checking. + */ + info->device[info->SCpnt->target].parity_check = 0; + info->device[info->SCpnt->target].parity_enabled = 1; + outb(info->scsi.cfg[0], REG_CNTL1(info)); + } + + if (msgqueue_msglength(&info->scsi.msgs) > 1) + fas216_cmd(info, CMD_SETATN); + /*FALLTHROUGH*/ + + /* + * Any -> Message Out + */ case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): fas216_send_messageout(info, 0); return; @@ -1435,29 +1554,14 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne printk(KERN_ERR "scsi%d.%c: " "target trying to receive more command bytes\n", info->host->host_no, fas216_target(info)); - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); outb(15, REG_STCL(info)); outb(0, REG_STCM(info)); outb(0, REG_STCH(info)); - outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; - return; - - /* Selection -> Message Out */ - case STATE(STAT_MESGOUT, PHASE_SELSTEPS): - case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */ - /* If we get another message out phase, this - * usually means some parity error occurred. - * Resend complete set of messages. If we have - * more than 1 byte to send, we need to assert - * ATN again. - */ - if (msgqueue_msglength(&info->scsi.msgs) > 1) - outb(CMD_SETATN, REG_CMD(info)); - - fas216_send_messageout(info, 0); return; } @@ -1466,11 +1570,11 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne info->host->host_no, fas216_target(info), fas216_bus_phase(stat)); msgqueue_flush(&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); return; } printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", @@ -1481,9 +1585,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne return; bad_is: - printk("scsi%d.%c: bus service at step %d?\n", - info->host->host_no, fas216_target(info), - ssr & IS_BITS); + fas216_log(info, 0, "bus service at step %d?", ssr & IS_BITS); print_debug_list(); fas216_done(info, DID_ERROR); @@ -1497,41 +1599,90 @@ bad_is: */ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) { - int status, message; + unsigned int fifo_len = inb(REG_CFIS(info)) & CFIS_CF; + unsigned int status, message; fas216_checkmagic(info); -#ifdef DEBUG_FUNCTIONDONE - printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); -#endif + fas216_log(info, LOG_FUNCTIONDONE, + "function done: stat=%02x ssr=%02x phase=%02x", + stat, ssr, info->scsi.phase); + switch (info->scsi.phase) { case PHASE_STATUS: /* status phase - read status and msg */ + if (fifo_len != 2) { + fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len); + } status = inb(REG_FF(info)); message = inb(REG_FF(info)); info->scsi.SCp.Message = message; info->scsi.SCp.Status = status; info->scsi.phase = PHASE_DONE; - outb(CMD_MSGACCEPTED, REG_CMD(info)); + fas216_cmd(info, CMD_MSGACCEPTED); break; case PHASE_IDLE: /* reselected? */ case PHASE_MSGIN: /* message in phase */ case PHASE_RECONNECTED: /* reconnected command */ if ((stat & STAT_BUSMASK) == STAT_MESGIN) { - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + info->scsi.msgin_fifo = fifo_len; fas216_message(info); break; } default: - printk("scsi%d.%c: internal phase %s for function done?" - " What do I do with this?\n", - info->host->host_no, fas216_target(info), - fas216_drv_phase(info)); + fas216_log(info, 0, "internal phase %s for function done?" + " What do I do with this?", + fas216_target(info), fas216_drv_phase(info)); } } +static void fas216_bus_reset(FAS216_Info *info) +{ + neg_t sync_state, wide_state; + int i; + + msgqueue_flush(&info->scsi.msgs); + + info->scsi.reconnected.target = 0; + info->scsi.reconnected.lun = 0; + info->scsi.reconnected.tag = 0; + + if (info->ifcfg.wide_max_size == 0) + wide_state = neg_invalid; + else +#ifdef SCSI2_WIDE + wide_state = neg_wait; +#else + wide_state = neg_invalid; +#endif + + if (info->host->dma_channel == NO_DMA || !info->dma.setup) + sync_state = neg_invalid; + else +#ifdef SCSI2_SYNC + sync_state = neg_wait; +#else + sync_state = neg_invalid; +#endif + + info->scsi.phase = PHASE_IDLE; + info->SCpnt = NULL; /* bug! */ + + for (i = 0; i < 8; i++) { + info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; + info->device[i].sync_state = sync_state; + info->device[i].wide_state = wide_state; + info->device[i].period = info->ifcfg.asyncperiod / 4; + info->device[i].stp = info->scsi.async_stp; + info->device[i].sof = 0; + info->device[i].wide_xfer = 0; + } + + info->rst_bus_status = 1; + wake_up(&info->eh_wait); +} + /* Function: void fas216_intr(struct Scsi_Host *instance) * Purpose : handle interrupts from the interface to progress a command * Params : instance - interface to service @@ -1551,11 +1702,13 @@ void fas216_intr(struct Scsi_Host *instance) if (stat & STAT_INT) { if (isr & INST_BUSRESET) { - printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no); - scsi_report_bus_reset(instance, 0); + fas216_log(info, 0, "bus reset detected"); + fas216_bus_reset(info); + scsi_report_bus_reset(info->host, 0); } else if (isr & INST_ILLEGALCMD) { - printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); + fas216_log(info, LOG_ERROR, "illegal command given\n"); fas216_dumpstate(info); + print_debug_list(); } else if (isr & INST_DISCONNECT) fas216_disconnect_intr(info); else if (isr & INST_RESELECTED) /* reselected */ @@ -1565,108 +1718,123 @@ void fas216_intr(struct Scsi_Host *instance) else if (isr & INST_FUNCDONE) /* function done */ fas216_funcdone_intr(info, stat, ssr); else - printk("scsi%d.%c: unknown interrupt received:" - " phase %s isr %02X ssr %02X stat %02X\n", - instance->host_no, fas216_target(info), + fas216_log(info, 0, "unknown interrupt received:" + " phase %s isr %02X ssr %02X stat %02X", fas216_drv_phase(info), isr, ssr, stat); } } -/* Function: void fas216_kick(FAS216_Info *info) - * Purpose : kick a command to the interface - interface should be idle - * Params : info - our host interface to kick - * Notes : Interrupts are always disabled! - */ -static void fas216_kick(FAS216_Info *info) +static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - Scsi_Cmnd *SCpnt = NULL; - int tot_msglen, from_queue = 0, disconnect_ok; + int tot_msglen; - fas216_checkmagic(info); + /* following what the ESP driver says */ + outb(0, REG_STCL(info)); + outb(0, REG_STCM(info)); + outb(0, REG_STCH(info)); + fas216_cmd(info, CMD_NOP | CMD_WITHDMA); - /* - * Obtain the next command to process. - */ - do { - if (info->reqSCpnt) { - SCpnt = info->reqSCpnt; - info->reqSCpnt = NULL; - break; - } + /* flush FIFO */ + fas216_cmd(info, CMD_FLUSHFIFO); - if (info->origSCpnt) { - SCpnt = info->origSCpnt; - info->origSCpnt = NULL; - break; + /* load bus-id and timeout */ + outb(BUSID(SCpnt->target), REG_SDID(info)); + outb(info->ifcfg.select_timeout, REG_STIM(info)); + + /* synchronous transfers */ + fas216_set_sync(info, SCpnt->target); + + tot_msglen = msgqueue_msglength(&info->scsi.msgs); + +#ifdef DEBUG_MESSAGES + { + struct message *msg; + int msgnr = 0, i; + + printk("scsi%d.%c: message out: ", + info->host->host_no, '0' + SCpnt->target); + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + printk("{ "); + for (i = 0; i < msg->length; i++) + printk("%02x ", msg->msg[i]); + printk("} "); } + printk("\n"); + } +#endif - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&info->queues.issue, - info->busyluns); - from_queue = 1; - break; + if (tot_msglen == 1 || tot_msglen == 3) { + /* + * We have an easy message length to send... + */ + struct message *msg; + int msgnr = 0, i; + + info->scsi.phase = PHASE_SELSTEPS; + + /* load message bytes */ + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + for (i = 0; i < msg->length; i++) + outb(msg->msg[i], REG_FF(info)); + msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); } - } while (0); - if (!SCpnt) /* no command pending - just exit */ - return; + /* load command */ + for (i = 0; i < SCpnt->cmd_len; i++) + outb(SCpnt->cmnd[i], REG_FF(info)); - if (info->scsi.disconnectable && info->SCpnt) { - queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); - info->scsi.disconnectable = 0; - info->SCpnt = NULL; - printk("scsi%d.%c: moved command to disconnected queue\n", - info->host->host_no, fas216_target(info)); + if (tot_msglen == 1) + fas216_cmd(info, CMD_SELECTATN); + else + fas216_cmd(info, CMD_SELECTATN3); + } else { + /* + * We have an unusual number of message bytes to send. + * Load first byte into fifo, and issue SELECT with ATN and + * stop steps. + */ + struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); + + outb(msg->msg[0], REG_FF(info)); + msg->fifo = 1; + + fas216_cmd(info, CMD_SELECTATNSTOP); + } +} + +/* + * Decide whether we need to perform a parity test on this device. + * Can also be used to force parity error conditions during initial + * information transfer phase (message out) for test purposes. + */ +static int parity_test(FAS216_Info *info, int target) +{ +#if 0 + if (target == 3) { + info->device[3].parity_check = 0; + return 1; } +#endif + return info->device[target].parity_check; +} + +static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ + int disconnect_ok; + + if (parity_test(info, SCpnt->target)) + outb(info->scsi.cfg[0] | CNTL1_PTE, REG_CNTL1(info)); + else + outb(info->scsi.cfg[0], REG_CNTL1(info)); /* * claim host busy */ info->scsi.phase = PHASE_SELECTION; - info->SCpnt = SCpnt; info->scsi.SCp = SCpnt->SCp; + info->SCpnt = SCpnt; info->dma.transfer_type = fasdma_none; -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: starting cmd %02X", - info->host->host_no, '0' + SCpnt->target, - SCpnt->cmnd[0]); -#endif - - if (from_queue) { -#ifdef SCSI2_TAG - /* - * tagged queuing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && - SCpnt->cmnd[0] != INQUIRY) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } else -#endif - set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - - info->stats.removes += 1; - switch (SCpnt->cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: - info->stats.writes += 1; - break; - case READ_6: - case READ_10: - case READ_12: - info->stats.reads += 1; - break; - default: - info->stats.miscs += 1; - break; - } - } - /* * Don't allow request sense commands to disconnect. */ @@ -1710,14 +1878,68 @@ static void fas216_kick(FAS216_Info *info) #endif } while (0); + __fas216_start_command(info, SCpnt); +} + +static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ +#ifdef SCSI2_TAG + /* + * tagged queuing - allocate a new tag to this command + */ + if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && + SCpnt->cmnd[0] != INQUIRY) { + SCpnt->device->current_tag += 1; + if (SCpnt->device->current_tag == 0) + SCpnt->device->current_tag = 1; + SCpnt->tag = SCpnt->device->current_tag; + } else +#endif + set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + + info->stats.removes += 1; + switch (SCpnt->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: + info->stats.writes += 1; + break; + case READ_6: + case READ_10: + case READ_12: + info->stats.reads += 1; + break; + default: + info->stats.miscs += 1; + break; + } +} + +static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ + struct message *msg; + + /* + * claim host busy + */ + info->scsi.phase = PHASE_SELECTION; + info->scsi.SCp = SCpnt->SCp; + info->SCpnt = SCpnt; + info->dma.transfer_type = fasdma_none; + + fas216_log(info, LOG_ERROR, "sending bus device reset"); + + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET); + /* following what the ESP driver says */ outb(0, REG_STCL(info)); outb(0, REG_STCM(info)); outb(0, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_NOP | CMD_WITHDMA); /* flush FIFO */ - outb(CMD_FLUSHFIFO, REG_CMD(info)); + fas216_cmd(info, CMD_FLUSHFIFO); /* load bus-id and timeout */ outb(BUSID(SCpnt->target), REG_SDID(info)); @@ -1726,68 +1948,110 @@ static void fas216_kick(FAS216_Info *info) /* synchronous transfers */ fas216_set_sync(info, SCpnt->target); - tot_msglen = msgqueue_msglength(&info->scsi.msgs); + msg = msgqueue_getmsg(&info->scsi.msgs, 0); -#ifdef DEBUG_MESSAGES - { - struct message *msg; - int msgnr = 0, i; + outb(BUS_DEVICE_RESET, REG_FF(info)); + msg->fifo = 1; - printk("scsi%d.%c: message out: ", - info->host->host_no, '0' + SCpnt->target); - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - printk("{ "); - for (i = 0; i < msg->length; i++) - printk("%02x ", msg->msg[i]); - printk("} "); + fas216_cmd(info, CMD_SELECTATNSTOP); +} + +/* Function: void fas216_kick(FAS216_Info *info) + * Purpose : kick a command to the interface - interface should be idle + * Params : info - our host interface to kick + * Notes : Interrupts are always disabled! + */ +static void fas216_kick(FAS216_Info *info) +{ + Scsi_Cmnd *SCpnt = NULL; +#define TYPE_OTHER 0 +#define TYPE_RESET 1 +#define TYPE_QUEUE 2 + int where_from = TYPE_OTHER; + + fas216_checkmagic(info); + + /* + * Obtain the next command to process. + */ + do { + if (info->rstSCpnt) { + SCpnt = info->rstSCpnt; + /* don't remove it */ + where_from = TYPE_RESET; + break; + } + + if (info->reqSCpnt) { + SCpnt = info->reqSCpnt; + info->reqSCpnt = NULL; + break; } - printk("\n"); - } -#endif - - if (tot_msglen == 1 || tot_msglen == 3) { - /* - * We have an easy message length to send... - */ - struct message *msg; - int msgnr = 0, i; - info->scsi.phase = PHASE_SELSTEPS; + if (info->origSCpnt) { + SCpnt = info->origSCpnt; + info->origSCpnt = NULL; + break; + } - /* load message bytes */ - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - for (i = 0; i < msg->length; i++) - outb(msg->msg[i], REG_FF(info)); - msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); + /* retrieve next command */ + if (!SCpnt) { + SCpnt = queue_remove_exclude(&info->queues.issue, + info->busyluns); + where_from = TYPE_QUEUE; + break; } + } while (0); - /* load command */ - for (i = 0; i < SCpnt->cmd_len; i++) - outb(SCpnt->cmnd[i], REG_FF(info)); + if (!SCpnt) /* no command pending - just exit */ + return; - if (tot_msglen == 1) - outb(CMD_SELECTATN, REG_CMD(info)); - else - outb(CMD_SELECTATN3, REG_CMD(info)); - } else { - /* - * We have an unusual number of message bytes to send. - * Load first byte into fifo, and issue SELECT with ATN and - * stop steps. - */ - struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); + if (info->scsi.disconnectable && info->SCpnt) { + fas216_log(info, LOG_CONNECT, + "moved command for %d to disconnected queue", + info->SCpnt->target); + queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); + info->scsi.disconnectable = 0; + info->SCpnt = NULL; + } - outb(msg->msg[0], REG_FF(info)); - msg->fifo = 1; +#if defined(DEBUG_CONNECT) || defined(DEBUG_MESSAGES) + printk("scsi%d.%c: starting ", + info->host->host_no, '0' + SCpnt->target); + print_command(SCpnt->cmnd); +#endif - outb(CMD_SELECTATNSTOP, REG_CMD(info)); + switch (where_from) { + case TYPE_QUEUE: + fas216_allocate_tag(info, SCpnt); + case TYPE_OTHER: + fas216_start_command(info, SCpnt); + break; + case TYPE_RESET: + fas216_do_bus_device_reset(info, SCpnt); + break; } -#ifdef DEBUG_CONNECT - printk(", data pointers [%p, %X]\n", + fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif - /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */ + + /* + * should now get either DISCONNECT or + * (FUNCTION DONE with BUS SERVICE) interrupt + */ +} + +/* + * Clean up from issuing a BUS DEVICE RESET message to a device. + */ +static void +fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ + fas216_log(info, LOG_ERROR, "fas216 device reset complete"); + + info->rstSCpnt = NULL; + info->rst_dev_status = 1; + wake_up(&info->eh_wait); } /* Function: void fas216_rq_sns_done(info, SCpnt, result) @@ -1799,11 +2063,9 @@ static void fas216_kick(FAS216_Info *info) static void fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) { -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: request sense complete, result=%04X%02X%02X\n", - info->host->host_no, '0' + SCpnt->target, result, - SCpnt->SCp.Message, SCpnt->SCp.Status); -#endif + fas216_log(info, LOG_CONNECT, + "request sense complete, result=0x%04x%02x%02x", + result, SCpnt->SCp.Message, SCpnt->SCp.Status); if (result != DID_OK || SCpnt->SCp.Status != GOOD) /* @@ -1812,7 +2074,8 @@ fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) * confuse the higher levels. */ memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - +//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->target); +//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); } /* * Note that we don't set SCpnt->result, since that should * reflect the status of the command that we were asked by @@ -1850,10 +2113,11 @@ fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) goto done; /* - * If the command returned CHECK_CONDITION status, - * request the sense information. + * If the command returned CHECK_CONDITION or COMMAND_TERMINATED + * status, request the sense information. */ - if (info->scsi.SCp.Status == CHECK_CONDITION) + if (status_byte(SCpnt->result) == CHECK_CONDITION || + status_byte(SCpnt->result) == COMMAND_TERMINATED) goto request_sense; /* @@ -1888,8 +2152,15 @@ fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) } } -done: SCpnt->scsi_done(SCpnt); - return; +done: + if (SCpnt->scsi_done) { + SCpnt->scsi_done(SCpnt); + return; + } + + panic("scsi%d.H: null scsi_done function in fas216_done", + info->host->host_no); + request_sense: memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); @@ -1928,6 +2199,7 @@ static void fas216_done(FAS216_Info *info, unsigned int result) { void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int); Scsi_Cmnd *SCpnt; + unsigned long flags; fas216_checkmagic(info); @@ -1938,12 +2210,8 @@ static void fas216_done(FAS216_Info *info, unsigned int result) info->SCpnt = NULL; info->scsi.phase = PHASE_IDLE; - if (!SCpnt->scsi_done) - goto no_done; - if (info->scsi.aborting) { - printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, 0, "uncaught abort - returning DID_ABORT"); result = DID_ABORT; info->scsi.aborting = 0; } @@ -1966,21 +2234,23 @@ static void fas216_done(FAS216_Info *info, unsigned int result) * the sense information, fas216_kick will re-assert the busy * status. */ + info->device[SCpnt->target].parity_check = 0; clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; fn(info, SCpnt, result); - if (info->scsi.irq != NO_IRQ) - fas216_kick(info); + if (info->scsi.irq != NO_IRQ) { + spin_lock_irqsave(&info->host_lock, flags); + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); + spin_unlock_irqrestore(&info->host_lock, flags); + } return; no_command: panic("scsi%d.H: null command in fas216_done", info->host->host_no); -no_done: - panic("scsi%d.H: null scsi_done function in fas216_done", - info->host->host_no); } /* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) @@ -1998,9 +2268,9 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) fas216_checkmagic(info); #ifdef DEBUG_CONNECT - printk("scsi%d.%c: received queuable command (%p) %02X\n", - SCpnt->host->host_no, '0' + SCpnt->target, - SCpnt, SCpnt->cmnd[0]); + printk("scsi%d.H: received command for id %d (%p) ", + SCpnt->host->host_no, SCpnt->target, SCpnt); + print_command(SCpnt->cmnd); #endif SCpnt->scsi_done = done; @@ -2012,6 +2282,8 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) info->stats.queues += 1; SCpnt->tag = 0; + spin_lock(&info->host_lock); + /* * Add command into execute queue and let it complete under * whatever scheme we're using. @@ -2022,8 +2294,14 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) * If we successfully added the command, * kick the interface to get it moving. */ - if (result == 0 && (!info->SCpnt || info->scsi.disconnectable)) + if (result == 0 && info->scsi.phase == PHASE_IDLE) fas216_kick(info); + spin_unlock(&info->host_lock); + +#ifdef DEBUG_CONNECT + printk("scsi%d.H: queue %s\n", info->host->host_no, + result ? "failure" : "success"); +#endif return result; } @@ -2092,23 +2370,41 @@ int fas216_command(Scsi_Cmnd *SCpnt) return SCpnt->result; } -enum res_abort { - res_failed, /* unable to abort */ +/* + * Error handler timeout function. Indicate that we timed out, + * and wake up any error handler process so it can continue. + */ +static void fas216_eh_timer(unsigned long data) +{ + FAS216_Info *info = (FAS216_Info *)data; + + fas216_log(info, LOG_ERROR, "error handling timed out\n"); + + del_timer(&info->eh_timer); + + if (info->rst_bus_status == 0) + info->rst_bus_status = -1; + if (info->rst_dev_status == 0) + info->rst_dev_status = -1; + + wake_up(&info->eh_wait); +} + +enum res_find { + res_failed, /* not found */ res_success, /* command on issue queue */ - res_success_clear, /* command marked tgt/lun busy */ res_hw_abort /* command on disconnected dev */ }; /* - * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) + * Prototype: enum res_find fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) * Purpose : decide how to abort a command * Params : SCpnt - command to abort * Returns : abort status */ -static enum res_abort -fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) +static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - enum res_abort res = res_failed; + enum res_find res = res_failed; if (queue_remove_cmd(&info->queues.issue, SCpnt)) { /* @@ -2156,8 +2452,9 @@ fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) * been set. */ info->origSCpnt = NULL; + clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); printk("waiting for execution "); - res = res_success_clear; + res = res_success; } else printk("unknown "); @@ -2179,22 +2476,15 @@ int fas216_eh_abort(Scsi_Cmnd *SCpnt) info->stats.aborts += 1; + printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no); + print_command(SCpnt->data_cmnd); + print_debug_list(); fas216_dumpstate(info); - fas216_dumpinfo(info); - printk(KERN_WARNING "scsi%d: abort ", info->host->host_no); - - switch (fas216_do_abort(info, SCpnt)) { - /* - * We managed to find the command and cleared it out. - * We do not expect the command to be executing on the - * target, but we have set the busylun bit. - */ - case res_success_clear: - printk("clear "); - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt); + switch (fas216_find_command(info, SCpnt)) { /* * We found the command, and cleared it out. Either * the command is still known to be executing on the @@ -2225,132 +2515,161 @@ int fas216_eh_abort(Scsi_Cmnd *SCpnt) return result; } -/* Function: void fas216_reset_state(FAS216_Info *info) - * Purpose : Initialise driver internal state - * Params : info - state to initialise +/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the device associated with this command + * Params : SCpnt - command specifing device to reset + * Returns : FAILED if unable to reset + * Notes : We won't be re-entered, so we'll only have one device + * reset on the go at one time. */ -static void fas216_reset_state(FAS216_Info *info) +int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) { - neg_t sync_state, wide_state; - int i; + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + unsigned long flags; + int i, res = FAILED, target = SCpnt->target; - fas216_checkmagic(info); + fas216_log(info, LOG_ERROR, "device reset for target %d", target); - /* - * Clear out all stale info in our state structure - */ - memset(info->busyluns, 0, sizeof(info->busyluns)); - msgqueue_flush(&info->scsi.msgs); - info->scsi.reconnected.target = 0; - info->scsi.reconnected.lun = 0; - info->scsi.reconnected.tag = 0; - info->scsi.disconnectable = 0; - info->scsi.aborting = 0; - info->scsi.phase = PHASE_IDLE; - info->scsi.async_stp = - fas216_syncperiod(info, info->ifcfg.asyncperiod); + spin_lock_irqsave(&info->host_lock, flags); - if (info->ifcfg.wide_max_size == 0) - wide_state = neg_invalid; - else -#ifdef SCSI2_WIDE - wide_state = neg_wait; -#else - wide_state = neg_invalid; -#endif + do { + /* + * If we are currently connected to a device, and + * it is the device we want to reset, there is + * nothing we can do here. Chances are it is stuck, + * and we need a bus reset. + */ + if (info->SCpnt && !info->scsi.disconnectable && + info->SCpnt->target == SCpnt->target) + break; - if (info->host->dma_channel == NO_DMA || !info->dma.setup) - sync_state = neg_invalid; - else -#ifdef SCSI2_SYNC - sync_state = neg_wait; -#else - sync_state = neg_invalid; -#endif + /* + * We're going to be resetting this device. Remove + * all pending commands from the driver. By doing + * so, we guarantee that we won't touch the command + * structures except to process the reset request. + */ + queue_remove_all_target(&info->queues.issue, target); + queue_remove_all_target(&info->queues.disconnected, target); + if (info->origSCpnt && info->origSCpnt->target == target) + info->origSCpnt = NULL; + if (info->reqSCpnt && info->reqSCpnt->target == target) + info->reqSCpnt = NULL; + for (i = 0; i < 8; i++) + clear_bit(target * 8 + i, info->busyluns); - for (i = 0; i < 8; i++) { - info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; - info->device[i].sync_state = sync_state; - info->device[i].wide_state = wide_state; - info->device[i].period = info->ifcfg.asyncperiod / 4; - info->device[i].stp = info->scsi.async_stp; - info->device[i].sof = 0; - info->device[i].wide_xfer = 0; - } + /* + * Hijack this SCSI command structure to send + * a bus device reset message to this device. + */ + SCpnt->host_scribble = (void *)fas216_devicereset_done; - /* - * Drain all commands on disconnected queue - */ - while (queue_remove(&info->queues.disconnected) != NULL); + info->rst_dev_status = 0; + info->rstSCpnt = SCpnt; - /* - * Remove executing commands. - */ - info->SCpnt = NULL; - info->reqSCpnt = NULL; - info->origSCpnt = NULL; -} + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); -/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the device associated with this command - * Params : SCpnt - command specifing device to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + mod_timer(&info->eh_timer, 30 * HZ); + spin_unlock_irqrestore(&info->host_lock, flags); - printk("scsi%d.%c: %s: called\n", - info->host->host_no, '0' + SCpnt->target, __FUNCTION__); - return FAILED; + /* + * Wait up to 30 seconds for the reset to complete. + */ + wait_event(info->eh_wait, info->rst_dev_status); + + del_timer_sync(&info->eh_timer); + spin_lock_irqsave(&info->host_lock, flags); + info->rstSCpnt = NULL; + + if (info->rst_dev_status == 1) + res = SUCCESS; + } while (0); + + SCpnt->host_scribble = NULL; + spin_unlock_irqrestore(&info->host_lock, flags); + + fas216_log(info, LOG_ERROR, "device reset complete: %s\n", + res == SUCCESS ? "success" : "failed"); + + return res; } /* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) * Purpose : Reset the bus associated with the command * Params : SCpnt - command specifing bus to reset * Returns : FAILED if unable to reset - * Notes : io_request_lock is taken, and irqs are disabled + * Notes : Further commands are blocked. */ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - int result = FAILED; + unsigned long flags; + Scsi_Device *SDpnt; fas216_checkmagic(info); + fas216_log(info, LOG_ERROR, "resetting bus"); info->stats.bus_resets += 1; - printk("scsi%d.%c: %s: resetting bus\n", - info->host->host_no, '0' + SCpnt->target, __FUNCTION__); + spin_lock_irqsave(&info->host_lock, flags); /* - * Attempt to stop all activity on this interface. + * Stop all activity on this interface. */ + fas216_aborttransfer(info); outb(info->scsi.cfg[2], REG_CNTL3(info)); - fas216_stoptransfer(info); /* - * Clear any pending interrupts + * Clear any pending interrupts. */ while (inb(REG_STAT(info)) & STAT_INT) inb(REG_INST(info)); + info->rst_bus_status = 0; + /* - * Reset the SCSI bus + * For each attached hard-reset device, clear out + * all command structures. Leave the running + * command in place. */ - outb(CMD_RESETSCSI, REG_CMD(info)); - udelay(5); + for (SDpnt = info->host->host_queue; SDpnt; SDpnt = SDpnt->next) { + int i; + + if (SDpnt->soft_reset) + continue; + + queue_remove_all_target(&info->queues.issue, SDpnt->id); + queue_remove_all_target(&info->queues.disconnected, SDpnt->id); + if (info->origSCpnt && info->origSCpnt->target == SDpnt->id) + info->origSCpnt = NULL; + if (info->reqSCpnt && info->reqSCpnt->target == SDpnt->id) + info->reqSCpnt = NULL; + info->SCpnt = NULL; + + for (i = 0; i < 8; i++) + clear_bit(SDpnt->id * 8 + i, info->busyluns); + } /* - * Clear reset interrupt + * Reset the SCSI bus. Device cleanup happens in + * the interrupt handler. */ - if (inb(REG_STAT(info)) & STAT_INT && - inb(REG_INST(info)) & INST_BUSRESET) - result = SUCCESS; + fas216_cmd(info, CMD_RESETSCSI); - fas216_reset_state(info); + mod_timer(&info->eh_timer, jiffies + HZ); + spin_unlock_irqrestore(&info->host_lock, flags); - return result; + /* + * Wait one second for the interrupt. + */ + wait_event(info->eh_wait, info->rst_bus_status); + del_timer_sync(&info->eh_timer); + + fas216_log(info, LOG_ERROR, "bus reset complete: %s\n", + info->rst_bus_status == 1 ? "success" : "failed"); + + return info->rst_bus_status == 1 ? SUCCESS : FAILED; } /* Function: void fas216_init_chip(FAS216_Info *info) @@ -2387,7 +2706,7 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) /* * Reset the SCSI chip. */ - outb(CMD_RESETCHIP, REG_CMD(info)); + fas216_cmd(info, CMD_RESETCHIP); /* * Ugly ugly ugly! @@ -2396,13 +2715,13 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) * IRQs after the sleep. */ spin_unlock_irq(info->host->host_lock); - scsi_sleep(25*HZ/100); + scsi_sleep(50 * HZ/100); spin_lock_irq(info->host->host_lock); /* * Release the SCSI reset. */ - outb(CMD_NOP, REG_CMD(info)); + fas216_cmd(info, CMD_NOP); fas216_init_chip(info); @@ -2509,6 +2828,44 @@ static int fas216_detect_type(FAS216_Info *info) return TYPE_NCR53C9x; } +/* Function: void fas216_reset_state(FAS216_Info *info) + * Purpose : Initialise driver internal state + * Params : info - state to initialise + */ +static void fas216_reset_state(FAS216_Info *info) +{ + int i; + + fas216_checkmagic(info); + + fas216_bus_reset(info); + + /* + * Clear out all stale info in our state structure + */ + memset(info->busyluns, 0, sizeof(info->busyluns)); + info->scsi.disconnectable = 0; + info->scsi.aborting = 0; + + for (i = 0; i < 8; i++) { + info->device[i].parity_enabled = 0; + info->device[i].parity_check = 1; + } + + /* + * Drain all commands on disconnected queue + */ + while (queue_remove(&info->queues.disconnected) != NULL); + + /* + * Remove executing commands. + */ + info->SCpnt = NULL; + info->reqSCpnt = NULL; + info->rstSCpnt = NULL; + info->origSCpnt = NULL; +} + /* Function: int fas216_init(struct Scsi_Host *instance) * Purpose : initialise FAS/NCR/AMD SCSI ic. * Params : instance - a driver-specific filled-out structure @@ -2519,12 +2876,22 @@ int fas216_init(struct Scsi_Host *instance) FAS216_Info *info = (FAS216_Info *)instance->hostdata; int type; - info->magic_start = MAGIC; - info->magic_end = MAGIC; - info->host = instance; - info->scsi.cfg[0] = instance->this_id; - info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; - info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; + info->magic_start = MAGIC; + info->magic_end = MAGIC; + info->host = instance; + info->scsi.cfg[0] = instance->this_id | CNTL1_PERE; + info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; + info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; + info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); + + info->rst_dev_status = -1; + info->rst_bus_status = -1; + init_waitqueue_head(&info->eh_wait); + init_timer(&info->eh_timer); + info->eh_timer.data = (unsigned long)info; + info->eh_timer.function = fas216_eh_timer; + + spin_lock_init(&info->host_lock); memset(&info->stats, 0, sizeof(info->stats)); @@ -2561,7 +2928,7 @@ int fas216_init(struct Scsi_Host *instance) * scsi standard says wait 250ms */ spin_unlock_irq(info->host->host_lock); - scsi_sleep(25*HZ/100); + scsi_sleep(100*HZ/100); spin_lock_irq(info->host->host_lock); outb(info->scsi.cfg[0], REG_CNTL1(info)); @@ -2621,7 +2988,6 @@ int fas216_info(FAS216_Info *info, char *buffer) int fas216_print_host(FAS216_Info *info, char *buffer) { - return sprintf(buffer, "\n" "Chip : %s\n" @@ -2634,8 +3000,9 @@ int fas216_print_host(FAS216_Info *info, char *buffer) int fas216_print_stats(FAS216_Info *info, char *buffer) { - return sprintf(buffer, - "\n" + char *p = buffer; + + p += sprintf(p, "\n" "Command Statistics:\n" " Queued : %u\n" " Issued : %u\n" @@ -2652,6 +3019,8 @@ int fas216_print_stats(FAS216_Info *info, char *buffer) info->stats.writes, info->stats.miscs, info->stats.disconnects, info->stats.aborts, info->stats.bus_resets, info->stats.host_resets); + + return p - buffer; } int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) @@ -2670,7 +3039,9 @@ int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) scd->tagged_queue ? "en" : "dis", scd->current_tag); - p += sprintf(p, "\n Transfers : %d-bit ", + p += sprintf(p, "%s\n", dev->parity_enabled ? "parity" : ""); + + p += sprintf(p, " Transfers : %d-bit ", 8 << dev->wide_xfer); if (dev->sof) diff --git a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h index 7d11ef613dc2..6fa9cdd572a5 100644 --- a/drivers/acorn/scsi/fas216.h +++ b/drivers/acorn/scsi/fas216.h @@ -214,10 +214,22 @@ typedef enum { typedef struct { unsigned long magic_start; + spinlock_t host_lock; struct Scsi_Host *host; /* host */ Scsi_Cmnd *SCpnt; /* currently processing command */ Scsi_Cmnd *origSCpnt; /* original connecting command */ Scsi_Cmnd *reqSCpnt; /* request sense command */ + Scsi_Cmnd *rstSCpnt; /* reset command */ + Scsi_Cmnd *pending_SCpnt[8]; /* per-device pending commands */ + int next_pending; /* next pending device */ + + /* + * Error recovery + */ + wait_queue_head_t eh_wait; + struct timer_list eh_timer; + unsigned int rst_dev_status; + unsigned int rst_bus_status; /* driver information */ struct { @@ -281,6 +293,8 @@ typedef struct { /* per-device info */ struct fas216_device { unsigned char disconnect_ok:1; /* device can disconnect */ + unsigned char parity_enabled:1; /* parity checking enabled */ + unsigned char parity_check:1; /* need to check parity checking */ unsigned char period; /* sync xfer period in (*4ns) */ unsigned char stp; /* synchronous transfer period */ unsigned char sof; /* synchronous offset register */ diff --git a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c index 922deb68a7cf..b415da7bfff6 100644 --- a/drivers/acorn/scsi/oak.c +++ b/drivers/acorn/scsi/oak.c @@ -1,55 +1,14 @@ -#define AUTOSENSE -/*#define PSEUDO_DMA*/ - /* * Oak Generic NCR5380 driver * - * Copyright 1995, Russell King - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * Options : - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - */ - -/* - * $Log: oak.c,v $ - * Revision 1.3 1998/05/03 20:45:37 alan - * ARM SCSI update. This adds the eesox driver and massively updates the - * Cumana driver. The folks who bought cumana arent anal retentive all - * docs are secret weenies so now there are docs .. - * - * Revision 1.2 1998/03/08 05:49:48 davem - * Merge to 2.1.89 - * - * Revision 1.1 1998/02/23 02:45:27 davem - * Merge to 2.1.88 - * + * Copyright 1995-2002, Russell King */ #include #include #include #include +#include #include #include @@ -60,6 +19,9 @@ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" +#define AUTOSENSE +/*#define PSEUDO_DMA*/ + #define OAKSCSI_PUBLIC_RELEASE 1 #define NCR5380_read(reg) oakscsi_read(_instance, reg) @@ -71,14 +33,9 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define NCR5380_implementation_fields \ - int port, ctrl - -#define NCR5380_local_declare() \ - struct Scsi_Host *_instance - -#define NCR5380_setup(instance) \ - _instance = instance +#define NCR5380_implementation_fields int port, ctrl +#define NCR5380_local_declare() struct Scsi_Host *_instance +#define NCR5380_setup(instance) _instance = instance #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 @@ -88,106 +45,9 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, #undef START_DMA_INITIATOR_RECEIVE_REG #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) -static const card_ids oakscsi_cids[] = { - { MANU_OAK, PROD_OAK_SCSI }, - { 0xffff, 0xffff } -}; - -#define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0)) -#define OAK_IRQ(card) (IRQ_NONE) -/* - * Function : int oakscsi_detect(Scsi_Host_Template * tpnt) - * - * Purpose : initializes oak NCR5380 driver based on the - * command line / compile time port and irq definitions. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ -static struct expansion_card *ecs[4]; - -int oakscsi_detect(Scsi_Host_Template * tpnt) -{ - int count = 0; - struct Scsi_Host *instance; - - tpnt->proc_name = "oakscsi"; - - memset (ecs, 0, sizeof (ecs)); - - ecard_startfind (); - - while(1) { - if ((ecs[count] = ecard_find(0, oakscsi_cids)) == NULL) - break; - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if (!instance) - break; - instance->io_port = OAK_ADDRESS(ecs[count]); - instance->irq = OAK_IRQ(ecs[count]); - - NCR5380_init(instance, 0); - ecard_claim(ecs[count]); - - instance->n_io_port = 255; - if (!request_region (instance->io_port, instance->n_io_port, "Oak SCSI")) { - ecard_release(ecs[count]); - scsi_unregister(instance); - break; - } - - if (instance->irq != IRQ_NONE) - if (request_irq(instance->irq, oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - - if (instance->irq != IRQ_NONE) { - printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no); - printk("scsi%d: that the board had an interrupt!\n", instance->host_no); - } - - printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) - printk ("s disabled"); - else - printk (" %d", instance->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", instance->host_no); - NCR5380_print_options(instance); - printk("\n"); - - ++count; - } -#ifdef MODULE - if(count == 0) - printk("No oak scsi devices found\n"); -#endif - return count; -} - -int oakscsi_release (struct Scsi_Host *shpnt) +const char * oakscsi_info (struct Scsi_Host *spnt) { - int i; - - if (shpnt->irq != IRQ_NONE) - free_irq (shpnt->irq, NULL); - if (shpnt->io_port) - release_region (shpnt->io_port, shpnt->n_io_port); - - for (i = 0; i < 4; i++) - if (shpnt->io_port == OAK_ADDRESS(ecs[i])) - ecard_release (ecs[i]); - return 0; -} - -const char * oakscsi_info (struct Scsi_Host *spnt) { - return ""; + return ""; } #define STAT(p) inw(p + 144) @@ -255,37 +115,95 @@ printk("reading %p len %d\n", addr, len); #include "../../scsi/NCR5380.c" static Scsi_Host_Template oakscsi_template = { - .module = THIS_MODULE, - .proc_info = oakscsi_proc_info, - .name = "Oak 16-bit SCSI", - .detect = oakscsi_detect, - .release = oakscsi_release, - .info = oakscsi_info, - .queuecommand = oakscsi_queue_command, + .module = THIS_MODULE, + .proc_info = oakscsi_proc_info, + .name = "Oak 16-bit SCSI", + .info = oakscsi_info, + .queuecommand = oakscsi_queue_command, .eh_abort_handler = NCR5380_abort, .eh_device_reset_handler= NCR5380_device_reset, .eh_bus_reset_handler = NCR5380_bus_reset, .eh_host_reset_handler = NCR5380_host_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING + .can_queue = 16, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "oakscsi", }; -static int __init oakscsi_init(void) +static int __devinit +oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + struct Scsi_Host *host; + int ret = -ENOMEM; + + host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_MEMC, 0) + host->irq = IRQ_NONE; + host->n_io_port = 255; + + ret = -EBUSY; + if (!request_region (host->io_port, host->n_io_port, "Oak SCSI")) + goto unreg; + + NCR5380_init(host, 0); + + printk("scsi%d: at port 0x%08lx irqs disabled", + host->host_no, host->io_port); + printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", + tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE); + printk("\nscsi%d:", host->host_no); + NCR5380_print_options(host); + printk("\n"); + + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + release_region(host->io_port, host->n_io_port); + unreg: + scsi_unregister(host); + out: + return ret; +} + +static void __devexit oakscsi_remove(struct expansion_card *ec) { - scsi_register_host(&oakscsi_template); - if (oakscsi_template.present) - return 0; + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + + release_region(host->io_port, host->n_io_port); + scsi_unregister(host); +} + +static const struct ecard_id oakscsi_cids[] = { + { MANU_OAK, PROD_OAK_SCSI }, + { 0xffff, 0xffff } +}; - scsi_unregister_host(&oakscsi_template); - return -ENODEV; +static struct ecard_driver oakscsi_driver = { + .probe = oakscsi_probe, + .remove = __devexit_p(oakscsi_remove), + .id_table = oakscsi_cids, + .drv = { + .name = "oakscsi", + }, +}; + +static int __init oakscsi_init(void) +{ + return ecard_register_driver(&oakscsi_driver); } static void __exit oakscsi_exit(void) { - scsi_unregister_host(&oakscsi_template); + ecard_remove_driver(&oakscsi_driver); } module_init(oakscsi_init); diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c index 2f6fd8885a3d..ab5907151d68 100644 --- a/drivers/acorn/scsi/powertec.c +++ b/drivers/acorn/scsi/powertec.c @@ -1,23 +1,11 @@ /* * linux/drivers/acorn/scsi/powertec.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * This driver is based on experimentation. Hence, it may have made - * assumptions about the particular card that I have available, and - * may not be reliable! - * - * Changelog: - * 01-10-1997 RMK Created, READONLY version. - * 15-02-1998 RMK Added DMA support and hardware definitions. - * 15-04-1998 RMK Only do PIO if FAS216 will allow it. - * 02-05-1998 RMK Moved DMA sg list into per-interface structure. - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h - * 02-04-2000 RMK Updated for new error handling code. */ #include #include @@ -45,18 +33,9 @@ #include -/* Configuration */ -#define POWERTEC_XTALFREQ 40 -#define POWERTEC_ASYNC_PERIOD 200 -#define POWERTEC_SYNC_DEPTH 7 - -/* - * List of devices that the driver will recognise - */ -#define POWERTECSCSI_LIST { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI } - #define POWERTEC_FAS216_OFFSET 0xc00 #define POWERTEC_FAS216_SHIFT 4 +#define POWERTEC_FAS216_SIZE (16 << POWERTEC_FAS216_SHIFT) #define POWERTEC_INTR_STATUS 0x800 #define POWERTEC_INTR_BIT 0x80 @@ -71,33 +50,22 @@ #define POWERTEC_INTR_ENABLE 1 #define POWERTEC_INTR_DISABLE 0 -/* - * Version - */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 5 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.00 (13/11/2002 2.5.47)" /* - * Use term=0,1,0,0,0 to turn terminators on/off + * Use term=0,1,0,0,0 to turn terminators on/off. + * One entry per slot. */ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; #define NR_SG 256 -typedef struct { - FAS216_Info info; - - struct { - unsigned int term_port; - unsigned int terms; - } control; - - /* other info... */ - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} PowerTecScsi_Info; +struct powertec_info { + FAS216_Info info; + unsigned int term_port; + unsigned int term_ctl; + struct scatterlist sg[NR_SG]; +}; /* Prototype: void powertecscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on Powertec SCSI card @@ -124,12 +92,8 @@ powertecscsi_irqdisable(struct expansion_card *ec, int irqnr) } static const expansioncard_ops_t powertecscsi_ops = { - powertecscsi_irqenable, - powertecscsi_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = powertecscsi_irqenable, + .irqdisable = powertecscsi_irqdisable, }; /* Prototype: void powertecscsi_terminator_ctl(host, on_off) @@ -140,14 +104,10 @@ static const expansioncard_ops_t powertecscsi_ops = { static void powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; - - if (on_off) - info->control.terms = POWERTEC_TERM_ENABLE; - else - info->control.terms = 0; + struct powertec_info *info = (struct powertec_info *)host->hostdata; - outb(info->control.terms, info->control.term_port); + info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0; + outb(info->term_ctl, info->term_port); } /* Prototype: void powertecscsi_intr(irq, *dev_id, *regs) @@ -176,7 +136,7 @@ static fasdmatype_t powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; + struct powertec_info *info = (struct powertec_info *)host->hostdata; int dmach = host->dma_channel; if (dmach != NO_DMA && @@ -220,122 +180,6 @@ powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) disable_dma(host->dma_channel); } -/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises PowerTec SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -powertecscsi_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids powertecscsi_cids[] = - { POWERTECSCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "powertec"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - PowerTecScsi_Info *info; - - ecs[count] = ecard_find(0, powertecscsi_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (PowerTecScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (PowerTecScsi_Info *)host->hostdata; - - if (host->dma_channel != NO_DMA) - set_dma_speed(host->dma_channel, 180); - - info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL; - info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0; - powertecscsi_terminator_ctl(host, info->control.terms); - - info->info.scsi.io_port = - host->io_port + POWERTEC_FAS216_OFFSET; - info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = POWERTEC_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = powertecscsi_dma_setup; - info->info.dma.pseudo = NULL; - info->info.dma.stop = powertecscsi_dma_stop; - - ecs[count]->irqaddr = (unsigned char *) - ioaddr(host->io_port + POWERTEC_INTR_STATUS); - ecs[count]->irqmask = POWERTEC_INTR_BIT; - ecs[count]->irq_data = (void *) - (host->io_port + POWERTEC_INTR_CONTROL); - ecs[count]->ops = (expansioncard_ops_t *)&powertecscsi_ops; - - request_region(host->io_port + POWERTEC_FAS216_OFFSET, - 16 << POWERTEC_FAS216_SHIFT, "powertec2-fas"); - - if (host->irq != NO_IRQ && - request_irq(host->irq, powertecscsi_intr, - SA_INTERRUPT, "powertec", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; - info->info.scsi.irq = NO_IRQ; - } - - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "powertec")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } - - fas216_init(host); - ++count; - } - return count; -} - -/* Prototype: int powertecscsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - */ -int powertecscsi_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + POWERTEC_FAS216_OFFSET, - 16 << POWERTEC_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && - host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) - ecard_release(ecs[i]); - return 0; -} - /* Prototype: const char *powertecscsi_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -343,15 +187,14 @@ int powertecscsi_release(struct Scsi_Host *host) */ const char *powertecscsi_info(struct Scsi_Host *host) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; + struct powertec_info *info = (struct powertec_info *)host->hostdata; static char string[100], *p; p = string; p += sprintf(p, "%s ", host->hostt->name); p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->control.terms ? "n" : "ff"); + p += sprintf(p, "v%s terminators o%s", + VERSION, info->term_ctl ? "n" : "ff"); return string; } @@ -405,7 +248,7 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, { int pos, begin; struct Scsi_Host *host; - PowerTecScsi_Info *info; + struct powertec_info *info; Scsi_Device *scd; host = scsi_host_hn_get(host_no); @@ -415,16 +258,14 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, if (inout == 1) return powertecscsi_set_proc_info(host, buffer, length); - info = (PowerTecScsi_Info *)host->hostdata; + info = (struct powertec_info *)host->hostdata; begin = 0; - pos = sprintf(buffer, - "PowerTec SCSI driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", - info->control.terms ? "n" : "ff"); + info->term_ctl ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); @@ -453,35 +294,147 @@ static Scsi_Host_Template powertecscsi_template = { .module = THIS_MODULE, .proc_info = powertecscsi_proc_info, .name = "PowerTec SCSI", - .detect = powertecscsi_detect, - .release = powertecscsi_release, .info = powertecscsi_info, - .can_queue = 1, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, .command = fas216_command, .queuecommand = fas216_queue_command, .eh_host_reset_handler = fas216_eh_host_reset, .eh_bus_reset_handler = fas216_eh_bus_reset, .eh_device_reset_handler = fas216_eh_device_reset, .eh_abort_handler = fas216_eh_abort, + + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = "powertec", }; -static int __init powertecscsi_init(void) +static int __devinit +powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id) { - scsi_register_host(&powertecscsi_template); - if (powertecscsi_template.present) - return 0; + struct Scsi_Host *host; + struct powertec_info *info; + int ret = -ENOMEM; + + host = scsi_register(&powertecscsi_template, + sizeof (struct powertec_info)); + if (!host) + goto out; + + host->io_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); + host->irq = ec->irq; + host->dma_channel = ec->dma; + + if (!request_region(host->io_port + POWERTEC_FAS216_OFFSET, + POWERTEC_FAS216_SIZE, "powertec2-fas")) { + ret = -EBUSY; + goto out_free; + } + + ec->irqaddr = (unsigned char *) + ioaddr(host->io_port + POWERTEC_INTR_STATUS); + ec->irqmask = POWERTEC_INTR_BIT; + ec->irq_data = (void *)(host->io_port + POWERTEC_INTR_CONTROL); + ec->ops = (expansioncard_ops_t *)&powertecscsi_ops; + + ecard_set_drvdata(ec, host); + + info = (struct powertec_info *)host->hostdata; + info->term_port = host->io_port + POWERTEC_TERM_CONTROL; + powertecscsi_terminator_ctl(host, term[ec->slot_no]); + + info->info.scsi.io_port = host->io_port + POWERTEC_FAS216_OFFSET; + info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.dma.setup = powertecscsi_dma_setup; + info->info.dma.pseudo = NULL; + info->info.dma.stop = powertecscsi_dma_stop; + + ret = request_irq(host->irq, powertecscsi_intr, + SA_INTERRUPT, "powertec", host); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_region; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "powertec")) { + printk("scsi%d: DMA%d not free, using PIO\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + } + } + + fas216_init(host); - scsi_unregister_host(&powertecscsi_template); - return -ENODEV; + ret = scsi_add_host(host); + if (ret == 0) + goto out; + + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + out_region: + release_region(host->io_port + POWERTEC_FAS216_OFFSET, + POWERTEC_FAS216_SIZE); + out_free: + scsi_unregister(host); + + out: + return ret; +} + +static void __devexit powertecscsi_remove(struct expansion_card *ec) +{ + struct Scsi_Host *host = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + scsi_remove_host(host); + fas216_release(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + release_region(host->io_port + POWERTEC_FAS216_OFFSET, + POWERTEC_FAS216_SIZE); + scsi_unregister(host); +} + +static const struct ecard_id powertecscsi_cids[] = { + { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI }, + { 0xffff, 0xffff }, +}; + +static struct ecard_driver powertecscsi_driver = { + .probe = powertecscsi_probe, + .remove = __devexit_p(powertecscsi_remove), + .id_table = powertecscsi_cids, + .drv = { + .name = "powertecscsi", + }, +}; + +static int __init powertecscsi_init(void) +{ + return ecard_register_driver(&powertecscsi_driver); } static void __exit powertecscsi_exit(void) { - scsi_unregister_host(&powertecscsi_template); + ecard_remove_driver(&powertecscsi_driver); } module_init(powertecscsi_init); @@ -492,4 +445,3 @@ MODULE_DESCRIPTION("Powertec SCSI driver"); MODULE_PARM(term, "1-8i"); MODULE_PARM_DESC(term, "SCSI bus termination"); MODULE_LICENSE("GPL"); - diff --git a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c index 82e247e1fb16..b7e585490122 100644 --- a/drivers/acorn/scsi/queue.c +++ b/drivers/acorn/scsi/queue.c @@ -228,6 +228,27 @@ Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag) return SCpnt; } +/* + * Function: queue_remove_all_target(queue, target) + * Purpose : remove all SCSI commands from the queue for a specified target + * Params : queue - queue to remove command from + * target - target device id + * Returns : nothing + */ +void queue_remove_all_target(Queue_t *queue, int target) +{ + unsigned long flags; + struct list_head *l; + + spin_lock_irqsave(&queue->queue_lock, flags); + list_for_each(l, &queue->head) { + QE_t *q = list_entry(l, QE_t, list); + if (q->SCpnt->target == target) + __queue_remove(queue, l); + } + spin_unlock_irqrestore(&queue->queue_lock, flags); +} + /* * Function: int queue_probetgtlun (queue, target, lun) * Purpose : check to see if we have a command in the queue for the specified @@ -290,6 +311,7 @@ EXPORT_SYMBOL(queue_remove); EXPORT_SYMBOL(queue_remove_exclude); EXPORT_SYMBOL(queue_remove_tgtluntag); EXPORT_SYMBOL(queue_remove_cmd); +EXPORT_SYMBOL(queue_remove_all_target); EXPORT_SYMBOL(queue_probetgtlun); MODULE_AUTHOR("Russell King"); diff --git a/drivers/acorn/scsi/queue.h b/drivers/acorn/scsi/queue.h index 508b42ec7a1e..0c9dec4c1716 100644 --- a/drivers/acorn/scsi/queue.h +++ b/drivers/acorn/scsi/queue.h @@ -73,6 +73,15 @@ extern int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head); */ extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag); +/* + * Function: queue_remove_all_target(queue, target) + * Purpose : remove all SCSI commands from the queue for a specified target + * Params : queue - queue to remove command from + * target - target device id + * Returns : nothing + */ +extern void queue_remove_all_target(Queue_t *queue, int target); + /* * Function: int queue_probetgtlun (queue, target, lun) * Purpose : check to see if we have a command in the queue for the specified diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h index 7c719a206399..1c9ecdadecd9 100644 --- a/include/asm-arm/ecard.h +++ b/include/asm-arm/ecard.h @@ -53,6 +53,9 @@ #define MANU_SERPORT 0x003f #define PROD_SERPORT_DSPORT 0x00b9 +#define MANU_ARXE 0x0041 +#define PROD_ARXE_SCSI 0x00be + #define MANU_I3 0x0046 #define PROD_I3_ETHERLAN500 0x00d4 #define PROD_I3_ETHERLAN600 0x00ec @@ -95,11 +98,11 @@ typedef enum { /* Speed for ECARD_IOC space */ ECARD_SYNC = 3 } card_speed_t; -typedef struct ecard_id { /* Card ID structure */ +struct ecard_id { /* Card ID structure */ unsigned short manufacturer; unsigned short product; void *data; -} card_ids; +}; struct in_ecid { /* Packed card ID information */ unsigned short product; /* Product code */ @@ -177,16 +180,6 @@ struct in_chunk_dir { */ #define ecard_release(ec) ((ec)->claimed = 0) -/* - * Start finding cards from the top of the list - */ -extern void ecard_startfind (void); - -/* - * Find an expansion card with the correct cid, product and manufacturer code - */ -extern struct expansion_card *ecard_find (int cid, const card_ids *ids); - /* * Read a chunk from an expansion card * cd : where to put read data -- cgit v1.2.3 From 40a0ece90edf61f35064f822dc9658d29bb73f12 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Nov 2002 21:56:28 +0000 Subject: [ARM] Move ARMv4 wbi functions to separate file This allows the ARMv4 write buffer + icache entry handling instructions to be left out of a kernel which doesn't have separate icache entry handling instructions. --- arch/arm/mm/Makefile | 23 ++++++++--------- arch/arm/mm/tlb-v4wb.S | 57 +++-------------------------------------- arch/arm/mm/tlb-v4wbi.S | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 67 deletions(-) create mode 100644 arch/arm/mm/tlb-v4wbi.S diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 88ca1a91ef0a..8d4045d105ee 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -22,24 +22,21 @@ obj-$(CONFIG_DISCONTIGMEM) += discontig.o p-$(CONFIG_CPU_26) += proc-arm2_3.o # ARMv3 -p-$(CONFIG_CPU_ARM610) += proc-arm6_7.o tlb-v3.o copypage-v3.o -p-$(CONFIG_CPU_ARM710) += proc-arm6_7.o tlb-v3.o copypage-v3.o +p-$(CONFIG_CPU_ARM610) += proc-arm6_7.o tlb-v3.o copypage-v3.o +p-$(CONFIG_CPU_ARM710) += proc-arm6_7.o tlb-v3.o copypage-v3.o # ARMv4 -p-$(CONFIG_CPU_ARM720T) += proc-arm720.o tlb-v4.o copypage-v4wt.o abort-lv4t.o -p-$(CONFIG_CPU_ARM920T) += proc-arm920.o tlb-v4wb.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_ARM922T) += proc-arm922.o tlb-v4wb.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o tlb-v4wb.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_SA110) += proc-sa110.o tlb-v4wb.o copypage-v4wb.o abort-ev4.o minicache.o -p-$(CONFIG_CPU_SA1100) += proc-sa110.o tlb-v4wb.o copypage-v4mc.o abort-ev4.o minicache.o +p-$(CONFIG_CPU_ARM720T) += proc-arm720.o tlb-v4.o copypage-v4wt.o abort-lv4t.o +p-$(CONFIG_CPU_ARM920T) += proc-arm920.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_ARM922T) += proc-arm922.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_SA110) += proc-sa110.o tlb-v4wb.o copypage-v4wb.o abort-ev4.o minicache.o +p-$(CONFIG_CPU_SA1100) += proc-sa110.o tlb-v4wb.o copypage-v4mc.o abort-ev4.o minicache.o # ARMv5 -p-$(CONFIG_CPU_ARM926T) += proc-arm926.o tlb-v4wb.o copypage-v4wb.o abort-ev5tej.o -p-$(CONFIG_CPU_XSCALE) += proc-xscale.o tlb-v4wb.o copypage-xscale.o abort-xscale.o minicache.o +p-$(CONFIG_CPU_ARM926T) += proc-arm926.o tlb-v4wbi.o copypage-v4wb.o abort-ev5tej.o +p-$(CONFIG_CPU_XSCALE) += proc-xscale.o tlb-v4wbi.o copypage-xscale.o abort-xscale.o minicache.o obj-y += $(sort $(p-y)) include $(TOPDIR)/Rules.make - -# Special dependencies -$(obj)/$(p-y): include/asm-arm/constants.h diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S index 90ca6c7597a3..3444855fb646 100644 --- a/arch/arm/mm/tlb-v4wb.S +++ b/arch/arm/mm/tlb-v4wb.S @@ -7,10 +7,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * ARM architecture version 4 and version 5 TLB handling functions. - * These assume a split I/D TLBs, with a write buffer. + * ARM architecture version 4 TLB handling functions. + * These assume a split I/D TLBs w/o I TLB entry, with a write buffer. * - * Processors: ARM920 ARM922 ARM926 SA110 SA1100 SA1110 XScale + * Processors: SA110 SA1100 SA1110 */ #include #include @@ -67,50 +67,6 @@ ENTRY(v4wb_flush_kern_tlb_range) blo 1b mov pc, lr -/* - * These two are optimised for ARM920, ARM922, ARM926, Xscale - */ - -/* - * v4wb_flush_user_tlb_range(start, end, mm) - * - * Invalidate a range of TLB entries in the specified address space. - * - * - start - range start address - * - end - range end address - * - mm - mm_struct describing address space - */ - .align 5 -ENTRY(v4wbi_flush_user_tlb_range) - vma_vm_mm ip, r2 - act_mm r3 @ get current->active_mm - eors r3, ip, r3 @ == mm ? - movne pc, lr @ no, we dont do anything - mov r3, #0 - mcr p15, 0, r3, c7, c10, 4 @ drain WB - vma_vm_flags r2, r2 - bic r0, r0, #0x0ff - bic r0, r0, #0xf00 -1: tst r2, #VM_EXEC - mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry - mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry - add r0, r0, #PAGE_SZ - cmp r0, r1 - blo 1b - mov pc, lr - -ENTRY(v4wbi_flush_kern_tlb_range) - mov r3, #0 - mcr p15, 0, r3, c7, c10, 4 @ drain WB - bic r0, r0, #0x0ff - bic r0, r0, #0xf00 -1: mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry - mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry - add r0, r0, #PAGE_SZ - cmp r0, r1 - blo 1b - mov pc, lr - __INIT .type v4wb_tlb_fns, #object @@ -119,10 +75,3 @@ ENTRY(v4wb_tlb_fns) .long v4wb_flush_kern_tlb_range .long v4wb_tlb_flags .size v4wb_tlb_fns, . - v4wb_tlb_fns - - .type v4wbi_tlb_fns, #object -ENTRY(v4wbi_tlb_fns) - .long v4wbi_flush_user_tlb_range - .long v4wbi_flush_kern_tlb_range - .long v4wbi_tlb_flags - .size v4wbi_tlb_fns, . - v4wbi_tlb_fns diff --git a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S new file mode 100644 index 000000000000..ecbdcd0b981a --- /dev/null +++ b/arch/arm/mm/tlb-v4wbi.S @@ -0,0 +1,68 @@ +/* + * linux/arch/arm/mm/tlbv4wbi.S + * + * Copyright (C) 1997-2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ARM architecture version 4 and version 5 TLB handling functions. + * These assume a split I/D TLBs, with a write buffer. + * + * Processors: ARM920 ARM922 ARM926 XScale + */ +#include +#include +#include +#include +#include "proc-macros.S" + +/* + * v4wb_flush_user_tlb_range(start, end, mm) + * + * Invalidate a range of TLB entries in the specified address space. + * + * - start - range start address + * - end - range end address + * - mm - mm_struct describing address space + */ + .align 5 +ENTRY(v4wbi_flush_user_tlb_range) + vma_vm_mm ip, r2 + act_mm r3 @ get current->active_mm + eors r3, ip, r3 @ == mm ? + movne pc, lr @ no, we dont do anything + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + vma_vm_flags r2, r2 + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 +1: tst r2, #VM_EXEC + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mov pc, lr + +ENTRY(v4wbi_flush_kern_tlb_range) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 +1: mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mov pc, lr + + __INIT + + .type v4wbi_tlb_fns, #object +ENTRY(v4wbi_tlb_fns) + .long v4wbi_flush_user_tlb_range + .long v4wbi_flush_kern_tlb_range + .long v4wbi_tlb_flags + .size v4wbi_tlb_fns, . - v4wbi_tlb_fns -- cgit v1.2.3 From a21061828c8555eeb0c86370881105f94efa20ff Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Sat, 16 Nov 2002 22:13:58 -0800 Subject: [PATCH] drivers/pcmcia/i8???.c - function prototypes for request_irq were missing - after including , I got an error due to a conflict with the 'irq_count()' macro and the irq_count function. Rename to i385_count_irq --- drivers/pcmcia/i82092.c | 1 + drivers/pcmcia/i82365.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 28f30334a398..153c70fc982b 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index ba1e22985ba8..8c2cd91ad6c3 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -76,12 +77,12 @@ static const char *version = #define DEBUG(n, args...) do { } while (0) #endif -static void irq_count(int, void *, struct pt_regs *); +static void i365_count_irq(int, void *, struct pt_regs *); static inline int _check_irq(int irq, int flags) { - if (request_irq(irq, irq_count, flags, "x", irq_count) != 0) + if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0) return -1; - free_irq(irq, irq_count); + free_irq(irq, i365_count_irq); return 0; } @@ -533,7 +534,7 @@ static u_int __init set_bridge_opts(u_short s, u_short ns) static volatile u_int irq_hits; static u_short irq_sock; -static void irq_count(int irq, void *dev, struct pt_regs *regs) +static void i365_count_irq(int irq, void *dev, struct pt_regs *regs) { i365_get(irq_sock, I365_CSC); irq_hits++; @@ -543,13 +544,13 @@ static void irq_count(int irq, void *dev, struct pt_regs *regs) static u_int __init test_irq(u_short sock, int irq) { DEBUG(2, " testing ISA irq %d\n", irq); - if (request_irq(irq, irq_count, 0, "scan", irq_count) != 0) + if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0) return 1; irq_hits = 0; irq_sock = sock; __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/100); if (irq_hits) { - free_irq(irq, irq_count); + free_irq(irq, i365_count_irq); DEBUG(2, " spurious hit!\n"); return 1; } @@ -559,7 +560,7 @@ static u_int __init test_irq(u_short sock, int irq) i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ); udelay(1000); - free_irq(irq, irq_count); + free_irq(irq, i365_count_irq); /* mask all interrupts */ i365_set(sock, I365_CSCINT, 0); -- cgit v1.2.3 From d3131293a9b3e7328bf08bf3d27713af2bf928a8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Nov 2002 22:25:51 -0800 Subject: Initialize exception tables early - don't use an initcall, since they are needed for early arch initialization. Thanks to Manfred for pointing this out. --- init/main.c | 2 ++ kernel/module.c | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/init/main.c b/init/main.c index 39d3522d3750..f9230123ec87 100644 --- a/init/main.c +++ b/init/main.c @@ -63,6 +63,7 @@ extern void init_IRQ(void); extern void init_modules(void); extern void sock_init(void); extern void fork_init(unsigned long); +extern void extable_init(void); extern void mca_init(void); extern void sbus_init(void); extern void sysctl_init(void); @@ -394,6 +395,7 @@ asmlinkage void __init start_kernel(void) printk("Kernel command line: %s\n", saved_command_line); parse_options(command_line); trap_init(); + extable_init(); rcu_init(); init_IRQ(); sched_init(); diff --git a/kernel/module.c b/kernel/module.c index 920cc7b184af..82aa7ebe6694 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1188,7 +1188,7 @@ struct seq_operations modules_op = { .show = m_show }; -static int __init init(void) +void __init extable_init(void) { /* Add kernel symbols to symbol table */ kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); @@ -1199,12 +1199,8 @@ static int __init init(void) kernel_extable.num_entries = (__stop___ex_table -__start___ex_table); kernel_extable.entry = __start___ex_table; list_add(&kernel_extable.list, &extables); - return 0; } /* Obsolete lvalue for broken code which asks about usage */ int module_dummy_usage = 1; EXPORT_SYMBOL(module_dummy_usage); - -/* Call this at boot */ -__initcall(init); -- cgit v1.2.3