From 4129c3a87c3cf0bab97c2a538317d5f3b13cf3e7 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 4 Sep 2006 06:41:37 -0400 Subject: [PATCH] --- yaml --- r: 35414 b: refs/heads/master c: f9bcda7760e1373615c9f6d9ce24209b0ab97de1 h: refs/heads/master v: v3 --- [refs] | 2 +- .../feature-removal-schedule.txt | 7 + trunk/Documentation/kernel-parameters.txt | 2 + .../powerpc/booting-without-of.txt | 6 +- trunk/MAINTAINERS | 3 +- trunk/Makefile | 2 +- trunk/arch/arm/Makefile | 3 +- trunk/arch/arm/common/sa1111.c | 6 +- trunk/arch/arm/configs/csb337_defconfig | 37 +- trunk/arch/arm/kernel/Makefile | 3 +- trunk/arch/arm/kernel/isa.c | 63 +- trunk/arch/arm/mach-footbridge/dc21285.c | 1 - trunk/arch/arm/mach-integrator/pci_v3.c | 2 + trunk/arch/arm/mach-pxa/corgi_ssp.c | 20 +- trunk/arch/arm/mach-pxa/ssp.c | 35 +- trunk/arch/arm/mach-s3c2410/dma.c | 88 +- trunk/arch/arm/mach-sa1100/ssp.c | 46 +- trunk/arch/arm/mm/Kconfig | 13 +- trunk/arch/arm/mm/flush.c | 26 + trunk/arch/arm/vfp/vfp.h | 18 +- trunk/arch/arm/vfp/vfpdouble.c | 50 +- trunk/arch/arm/vfp/vfphw.S | 10 +- trunk/arch/arm/vfp/vfpmodule.c | 4 +- trunk/arch/arm/vfp/vfpsingle.c | 55 +- trunk/arch/i386/kernel/head.S | 14 +- trunk/arch/i386/kernel/hpet.c | 2 +- trunk/arch/i386/kernel/irq.c | 5 - trunk/arch/i386/kernel/setup.c | 32 - trunk/arch/i386/kernel/traps.c | 27 +- trunk/arch/i386/pci/common.c | 5 + trunk/arch/i386/pci/mmconfig.c | 34 +- trunk/arch/i386/pci/pci.h | 3 +- trunk/arch/ia64/Kconfig | 4 +- trunk/arch/ia64/kernel/topology.c | 6 +- trunk/arch/ia64/sn/kernel/xpc_channel.c | 4 +- trunk/arch/ia64/sn/kernel/xpc_main.c | 28 +- trunk/arch/ia64/sn/kernel/xpc_partition.c | 24 +- trunk/arch/powerpc/Kconfig | 20 +- trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts | 190 +++ trunk/arch/powerpc/boot/dts/mpc8349emds.dts | 328 +++++ ...4x_sys_defconfig => mpc834x_mds_defconfig} | 0 trunk/arch/powerpc/kernel/fpu.S | 5 + trunk/arch/powerpc/kernel/irq.c | 84 +- trunk/arch/powerpc/kernel/pci_64.c | 11 +- trunk/arch/powerpc/kernel/ppc_ksyms.c | 4 - trunk/arch/powerpc/kernel/prom_init.c | 10 +- trunk/arch/powerpc/kernel/prom_parse.c | 17 +- trunk/arch/powerpc/kernel/smp-tbsync.c | 5 +- trunk/arch/powerpc/kernel/time.c | 25 +- trunk/arch/powerpc/lib/memcpy_64.S | 11 +- trunk/arch/powerpc/mm/44x_mmu.c | 4 +- .../arch/powerpc/platforms/83xx/mpc834x_itx.c | 49 +- .../arch/powerpc/platforms/83xx/mpc834x_sys.c | 56 +- trunk/arch/powerpc/platforms/83xx/mpc83xx.h | 1 + trunk/arch/powerpc/platforms/83xx/pci.c | 9 + .../powerpc/platforms/86xx/mpc86xx_hpcn.c | 26 +- trunk/arch/powerpc/platforms/86xx/pci.c | 3 +- .../powerpc/platforms/embedded6xx/Kconfig | 1 + .../platforms/embedded6xx/mpc7448_hpc2.c | 2 +- .../powerpc/platforms/powermac/pfunc_base.c | 2 +- trunk/arch/powerpc/platforms/powermac/pic.c | 6 +- trunk/arch/powerpc/sysdev/Makefile | 4 +- trunk/arch/powerpc/sysdev/ipic.c | 303 ++-- trunk/arch/powerpc/sysdev/ipic.h | 23 +- trunk/arch/powerpc/sysdev/mpic.c | 223 ++- trunk/arch/ppc/kernel/smp-tbsync.c | 7 +- trunk/arch/ppc/syslib/Makefile | 2 +- trunk/arch/ppc/syslib/ipic.c | 646 +++++++++ trunk/arch/ppc/syslib/ipic.h | 47 + trunk/arch/s390/lib/uaccess.S | 33 +- trunk/arch/s390/lib/uaccess64.S | 35 +- trunk/arch/sparc64/mm/generic.c | 2 + trunk/arch/x86_64/defconfig | 66 +- trunk/arch/x86_64/ia32/ia32_binfmt.c | 57 +- trunk/arch/x86_64/kernel/e820.c | 35 +- trunk/arch/x86_64/kernel/entry.S | 3 + trunk/arch/x86_64/kernel/head.S | 1 + trunk/arch/x86_64/kernel/init_task.c | 5 + trunk/arch/x86_64/kernel/setup.c | 6 +- trunk/arch/x86_64/kernel/setup64.c | 3 +- trunk/arch/x86_64/kernel/traps.c | 30 +- trunk/arch/x86_64/pci/mmconfig.c | 34 +- trunk/arch/xtensa/kernel/ptrace.c | 2 +- trunk/drivers/ata/Kconfig | 334 ----- trunk/drivers/ata/Makefile | 41 - trunk/drivers/ata/ata_generic.c | 252 ---- trunk/drivers/ata/ata_piix.c | 434 ++---- trunk/drivers/ata/pata_ali.c | 679 --------- trunk/drivers/ata/pata_amd.c | 707 --------- trunk/drivers/ata/pata_artop.c | 518 ------- trunk/drivers/ata/pata_atiixp.c | 306 ---- trunk/drivers/ata/pata_cmd64x.c | 505 ------- trunk/drivers/ata/pata_cs5520.c | 336 ----- trunk/drivers/ata/pata_cs5530.c | 387 ----- trunk/drivers/ata/pata_cs5535.c | 291 ---- trunk/drivers/ata/pata_cypress.c | 227 --- trunk/drivers/ata/pata_efar.c | 342 ----- trunk/drivers/ata/pata_hpt366.c | 478 ------- trunk/drivers/ata/pata_hpt37x.c | 1257 ----------------- trunk/drivers/ata/pata_hpt3x2n.c | 597 -------- trunk/drivers/ata/pata_hpt3x3.c | 226 --- trunk/drivers/ata/pata_isapnp.c | 156 -- trunk/drivers/ata/pata_it8172.c | 288 ---- trunk/drivers/ata/pata_it821x.c | 847 ----------- trunk/drivers/ata/pata_jmicron.c | 266 ---- trunk/drivers/ata/pata_legacy.c | 949 ------------- trunk/drivers/ata/pata_mpiix.c | 313 ---- trunk/drivers/ata/pata_netcell.c | 175 --- trunk/drivers/ata/pata_ns87410.c | 236 ---- trunk/drivers/ata/pata_oldpiix.c | 339 ----- trunk/drivers/ata/pata_opti.c | 292 ---- trunk/drivers/ata/pata_optidma.c | 547 ------- trunk/drivers/ata/pata_pcmcia.c | 393 ------ trunk/drivers/ata/pata_pdc2027x.c | 869 ------------ trunk/drivers/ata/pata_pdc202xx_old.c | 423 ------ trunk/drivers/ata/pata_qdi.c | 403 ------ trunk/drivers/ata/pata_radisys.c | 335 ----- trunk/drivers/ata/pata_rz1000.c | 205 --- trunk/drivers/ata/pata_sc1200.c | 287 ---- trunk/drivers/ata/pata_serverworks.c | 587 -------- trunk/drivers/ata/pata_sil680.c | 381 ----- trunk/drivers/ata/pata_sis.c | 1030 -------------- trunk/drivers/ata/pata_sl82c105.c | 388 ----- trunk/drivers/ata/pata_triflex.c | 285 ---- trunk/drivers/ata/pata_via.c | 568 -------- trunk/drivers/block/floppy.c | 12 +- trunk/drivers/char/drm/radeon_state.c | 9 +- trunk/drivers/char/ipmi/ipmi_msghandler.c | 1 + trunk/drivers/char/synclink_gt.c | 14 +- trunk/drivers/char/watchdog/sbc8360.c | 4 +- trunk/drivers/ide/pci/sgiioc4.c | 60 +- trunk/drivers/ide/pci/via82cxxx.c | 3 +- .../infiniband/hw/mthca/mthca_allocator.c | 15 +- trunk/drivers/macintosh/via-pmu-backlight.c | 99 +- trunk/drivers/macintosh/via-pmu.c | 12 + trunk/drivers/md/raid1.c | 57 +- trunk/drivers/net/e100.c | 6 +- trunk/drivers/net/sunlance.c | 27 +- trunk/drivers/net/wireless/strip.c | 6 +- trunk/drivers/pci/quirks.c | 1 + trunk/drivers/s390/block/dasd.c | 192 ++- trunk/drivers/s390/block/dasd_genhd.c | 10 +- trunk/drivers/s390/cio/ccwgroup.c | 14 +- trunk/drivers/s390/cio/chsc.c | 10 +- trunk/drivers/s390/cio/device.c | 19 +- trunk/drivers/s390/cio/device_fsm.c | 20 +- trunk/drivers/s390/cio/device_pgid.c | 27 +- trunk/drivers/serial/8250_pci.c | 31 +- trunk/drivers/serial/serial_core.c | 3 + trunk/drivers/usb/gadget/ether.c | 45 +- trunk/drivers/usb/host/uhci-q.c | 4 +- trunk/drivers/usb/input/hid-core.c | 149 +- trunk/drivers/usb/net/pegasus.h | 3 + trunk/drivers/usb/net/rtl8150.c | 1 + trunk/drivers/usb/storage/unusual_devs.h | 24 +- trunk/drivers/video/aty/aty128fb.c | 18 +- trunk/drivers/video/aty/atyfb_base.c | 18 +- trunk/drivers/video/aty/radeon_backlight.c | 4 +- trunk/drivers/video/nvidia/nv_backlight.c | 18 +- trunk/drivers/video/riva/fbdev.c | 18 +- trunk/fs/cifs/CHANGES | 10 + trunk/fs/cifs/README | 2 +- trunk/fs/cifs/cifsencrypt.c | 3 +- trunk/fs/cifs/cifsfs.c | 6 +- trunk/fs/cifs/cifsfs.h | 2 +- trunk/fs/cifs/cifsglob.h | 18 +- trunk/fs/cifs/cifsproto.h | 4 + trunk/fs/cifs/cifssmb.c | 28 +- trunk/fs/cifs/connect.c | 32 +- trunk/fs/cifs/dir.c | 4 + trunk/fs/cifs/file.c | 97 +- trunk/fs/cifs/netmisc.c | 1 + trunk/fs/cifs/readdir.c | 2 +- trunk/fs/cifs/sess.c | 2 +- trunk/fs/cifs/smberr.h | 1 + trunk/fs/cifs/transport.c | 618 +++++--- trunk/fs/cifs/xattr.c | 6 +- trunk/fs/jbd/transaction.c | 2 +- trunk/fs/xfs/xfs_bmap.c | 2 +- trunk/include/asm-arm/arch-pxa/ssp.h | 4 +- trunk/include/asm-arm/arch-s3c2410/dma.h | 150 +- trunk/include/asm-arm/cacheflush.h | 18 +- trunk/include/asm-arm/hardware/ssp.h | 4 +- trunk/include/asm-arm/io.h | 7 + trunk/include/asm-arm/spinlock.h | 16 +- trunk/include/asm-i386/alternative.h | 20 - .../asm-i386/mach-default/mach_mpspec.h | 4 + trunk/include/asm-i386/rwlock.h | 28 +- trunk/include/asm-i386/spinlock.h | 17 +- trunk/include/asm-i386/unistd.h | 4 +- trunk/include/asm-i386/unwind.h | 1 + trunk/include/asm-ia64/sn/sn_sal.h | 6 - trunk/include/asm-ia64/sn/xp.h | 22 +- trunk/include/asm-ia64/sn/xpc.h | 4 +- trunk/include/asm-powerpc/io.h | 7 +- trunk/include/asm-powerpc/ipic.h | 12 +- trunk/include/asm-powerpc/mpc86xx.h | 3 - trunk/include/asm-powerpc/mpic.h | 125 ++ trunk/include/asm-powerpc/prom.h | 4 +- trunk/include/asm-powerpc/time.h | 4 - trunk/include/asm-x86_64/alternative.h | 21 +- trunk/include/asm-x86_64/processor.h | 6 + trunk/include/asm-x86_64/spinlock.h | 11 +- trunk/include/asm-x86_64/unistd.h | 11 +- trunk/include/asm-x86_64/unwind.h | 1 + trunk/include/linux/delayacct.h | 10 +- trunk/include/linux/libata.h | 2 +- trunk/include/linux/mmzone.h | 1 + trunk/include/linux/pci_ids.h | 4 + trunk/include/linux/sched.h | 1 - trunk/kernel/delayacct.c | 16 - trunk/kernel/exit.c | 3 +- trunk/kernel/fork.c | 6 +- trunk/kernel/irq/handle.c | 5 + trunk/mm/mempolicy.c | 10 +- trunk/mm/mempool.c | 9 +- trunk/mm/vmstat.c | 151 +- trunk/net/ipv4/ip_output.c | 1 + trunk/net/ipv4/tcp_cong.c | 2 +- trunk/net/ipv4/tcp_input.c | 9 +- trunk/net/ipv6/addrconf.c | 4 +- trunk/net/ipv6/exthdrs.c | 29 +- trunk/net/ipv6/route.c | 4 + trunk/net/netlink/af_netlink.c | 14 +- trunk/net/sctp/socket.c | 10 +- trunk/net/socket.c | 3 +- trunk/sound/oss/Kconfig | 30 +- trunk/sound/pci/ac97/ac97_codec.c | 4 +- 228 files changed, 4182 insertions(+), 20055 deletions(-) create mode 100644 trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts create mode 100644 trunk/arch/powerpc/boot/dts/mpc8349emds.dts rename trunk/arch/powerpc/configs/{mpc834x_sys_defconfig => mpc834x_mds_defconfig} (100%) create mode 100644 trunk/arch/ppc/syslib/ipic.c create mode 100644 trunk/arch/ppc/syslib/ipic.h delete mode 100644 trunk/drivers/ata/ata_generic.c delete mode 100644 trunk/drivers/ata/pata_ali.c delete mode 100644 trunk/drivers/ata/pata_amd.c delete mode 100644 trunk/drivers/ata/pata_artop.c delete mode 100644 trunk/drivers/ata/pata_atiixp.c delete mode 100644 trunk/drivers/ata/pata_cmd64x.c delete mode 100644 trunk/drivers/ata/pata_cs5520.c delete mode 100644 trunk/drivers/ata/pata_cs5530.c delete mode 100644 trunk/drivers/ata/pata_cs5535.c delete mode 100644 trunk/drivers/ata/pata_cypress.c delete mode 100644 trunk/drivers/ata/pata_efar.c delete mode 100644 trunk/drivers/ata/pata_hpt366.c delete mode 100644 trunk/drivers/ata/pata_hpt37x.c delete mode 100644 trunk/drivers/ata/pata_hpt3x2n.c delete mode 100644 trunk/drivers/ata/pata_hpt3x3.c delete mode 100644 trunk/drivers/ata/pata_isapnp.c delete mode 100644 trunk/drivers/ata/pata_it8172.c delete mode 100644 trunk/drivers/ata/pata_it821x.c delete mode 100644 trunk/drivers/ata/pata_jmicron.c delete mode 100644 trunk/drivers/ata/pata_legacy.c delete mode 100644 trunk/drivers/ata/pata_mpiix.c delete mode 100644 trunk/drivers/ata/pata_netcell.c delete mode 100644 trunk/drivers/ata/pata_ns87410.c delete mode 100644 trunk/drivers/ata/pata_oldpiix.c delete mode 100644 trunk/drivers/ata/pata_opti.c delete mode 100644 trunk/drivers/ata/pata_optidma.c delete mode 100644 trunk/drivers/ata/pata_pcmcia.c delete mode 100644 trunk/drivers/ata/pata_pdc2027x.c delete mode 100644 trunk/drivers/ata/pata_pdc202xx_old.c delete mode 100644 trunk/drivers/ata/pata_qdi.c delete mode 100644 trunk/drivers/ata/pata_radisys.c delete mode 100644 trunk/drivers/ata/pata_rz1000.c delete mode 100644 trunk/drivers/ata/pata_sc1200.c delete mode 100644 trunk/drivers/ata/pata_serverworks.c delete mode 100644 trunk/drivers/ata/pata_sil680.c delete mode 100644 trunk/drivers/ata/pata_sis.c delete mode 100644 trunk/drivers/ata/pata_sl82c105.c delete mode 100644 trunk/drivers/ata/pata_triflex.c delete mode 100644 trunk/drivers/ata/pata_via.c diff --git a/[refs] b/[refs] index 4a7d48461201..3623a01a3ce0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 85cd7251b9112e3dabeac9fd3b175601ca607241 +refs/heads/master: f9bcda7760e1373615c9f6d9ce24209b0ab97de1 diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 87851efb0228..d1cd5f93e028 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -120,6 +120,13 @@ Who: Adrian Bunk --------------------------- +What: drivers depending on OSS_OBSOLETE_DRIVER +When: options in 2.6.20, code in 2.6.22 +Why: OSS drivers with ALSA replacements +Who: Adrian Bunk + +--------------------------- + What: pci_module_init(driver) When: January 2007 Why: Is replaced by pci_register_driver(pci_driver). diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index b50595a0550f..7947cede8712 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1183,6 +1183,8 @@ running once the system is up. Mechanism 2. nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI Configuration + mmconf [IA-32,X86_64] Force MMCONFIG. This is useful + to override the builtin blacklist. nomsi [MSI] If the PCI_MSI kernel config parameter is enabled, this kernel boot option can be used to disable the use of MSI interrupts system-wide. diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index 8c48b8a27b9c..5c0ba235f5a5 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -1136,10 +1136,10 @@ Sense and level information should be encoded as follows: Devices connected to openPIC-compatible controllers should encode sense and polarity as follows: - 0 = high to low edge sensitive type enabled + 0 = low to high edge sensitive type enabled 1 = active low level sensitive type enabled - 2 = low to high edge sensitive type enabled - 3 = active high level sensitive type enabled + 2 = active high level sensitive type enabled + 3 = high to low edge sensitive type enabled ISA PIC interrupt controllers should adhere to the ISA PIC encodings listed below: diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 3bab239e82fe..25cd7073a20b 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3296,10 +3296,11 @@ S: Maintained XFS FILESYSTEM P: Silicon Graphics Inc +P: Tim Shimmin, David Chatterton M: xfs-masters@oss.sgi.com -M: nathans@sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs +T: git git://oss.sgi.com:8090/xfs/xfs-2.6 S: Supported X86 3-LEVEL PAGING (PAE) SUPPORT diff --git a/trunk/Makefile b/trunk/Makefile index 33559b566449..c9ed7b42873a 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 18 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME=Crazed Snow-Weasel # *DOCUMENTATION* diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 3345c6d0fd1e..92873cdee31f 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -47,7 +47,8 @@ comma = , # testing for a specific architecture or later rather impossible. arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) -arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4) +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) +arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 diff --git a/trunk/arch/arm/common/sa1111.c b/trunk/arch/arm/common/sa1111.c index a331c12cead9..29818bd3248f 100644 --- a/trunk/arch/arm/common/sa1111.c +++ b/trunk/arch/arm/common/sa1111.c @@ -618,7 +618,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) { struct sa1111 *sachip; unsigned long id; - unsigned int has_devs, val; + unsigned int has_devs; int i, ret = -ENODEV; sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL); @@ -669,6 +669,9 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) sa1111_wake(sachip); #ifdef CONFIG_ARCH_SA1100 + { + unsigned int val; + /* * The SDRAM configuration of the SA1110 and the SA1111 must * match. This is very important to ensure that SA1111 accesses @@ -692,6 +695,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) * Enable the SA1110 memory bus request and grant signals. */ sa1110_mb_enable(); + } #endif /* diff --git a/trunk/arch/arm/configs/csb337_defconfig b/trunk/arch/arm/configs/csb337_defconfig index 3594155a8137..cf3fa5cb26e4 100644 --- a/trunk/arch/arm/configs/csb337_defconfig +++ b/trunk/arch/arm/configs/csb337_defconfig @@ -621,9 +621,8 @@ CONFIG_AT91_WATCHDOG=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set +# CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_AT91_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -956,9 +955,41 @@ CONFIG_USB_AT91=y CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_BLOCK=y -# CONFIG_MMC_WBSD is not set CONFIG_MMC_AT91RM9200=y +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc1" + +# +# RTC interfaces +# +# CONFIG_RTC_INTF_SYSFS is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set + # # File systems # diff --git a/trunk/arch/arm/kernel/Makefile b/trunk/arch/arm/kernel/Makefile index f0c0cdb1c183..1320a0efca73 100644 --- a/trunk/arch/arm/kernel/Makefile +++ b/trunk/arch/arm/kernel/Makefile @@ -13,12 +13,11 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \ obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_ARCH_ACORN) += ecard.o -obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FIQ) += fiq.o obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o -obj-$(CONFIG_PCI) += bios32.o +obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o diff --git a/trunk/arch/arm/kernel/isa.c b/trunk/arch/arm/kernel/isa.c index 685c3e591a7e..54bbd9fe255c 100644 --- a/trunk/arch/arm/kernel/isa.c +++ b/trunk/arch/arm/kernel/isa.c @@ -3,21 +3,14 @@ * * Copyright (C) 1999 Phil Blundell * - * ISA shared memory and I/O port support - */ - -/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. + * + * ISA shared memory and I/O port support, and is required to support + * iopl, inb, outb and friends in userspace via glibc emulation. */ - -/* - * Nothing about this is actually ARM specific. One day we could move - * it into kernel/resource.c or some place like that. - */ - #include #include #include @@ -27,21 +20,49 @@ static unsigned int isa_membase, isa_portbase, isa_portshift; static ctl_table ctl_isa_vars[4] = { - {BUS_ISA_MEM_BASE, "membase", &isa_membase, - sizeof(isa_membase), 0444, NULL, &proc_dointvec}, - {BUS_ISA_PORT_BASE, "portbase", &isa_portbase, - sizeof(isa_portbase), 0444, NULL, &proc_dointvec}, - {BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift, - sizeof(isa_portshift), 0444, NULL, &proc_dointvec}, - {0} + { + .ctl_name = BUS_ISA_MEM_BASE, + .procname = "membase", + .data = &isa_membase, + .maxlen = sizeof(isa_membase), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { + .ctl_name = BUS_ISA_PORT_BASE, + .procname = "portbase", + .data = &isa_portbase, + .maxlen = sizeof(isa_portbase), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { + .ctl_name = BUS_ISA_PORT_SHIFT, + .procname = "portshift", + .data = &isa_portshift, + .maxlen = sizeof(isa_portshift), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, {0} }; static struct ctl_table_header *isa_sysctl_header; -static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars}, - {0}}; -static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa}, - {0}}; +static ctl_table ctl_isa[2] = { + { + .ctl_name = CTL_BUS_ISA, + .procname = "isa", + .mode = 0555, + .child = ctl_isa_vars, + }, {0} +}; + +static ctl_table ctl_bus[2] = { + { + .ctl_name = CTL_BUS, + .procname = "bus", + .mode = 0555, + .child = ctl_isa, + }, {0} +}; void __init register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift) diff --git a/trunk/arch/arm/mach-footbridge/dc21285.c b/trunk/arch/arm/mach-footbridge/dc21285.c index 607ed1f5b3f8..823e25d4547e 100644 --- a/trunk/arch/arm/mach-footbridge/dc21285.c +++ b/trunk/arch/arm/mach-footbridge/dc21285.c @@ -35,7 +35,6 @@ extern int setup_arm_irq(int, struct irqaction *); extern void pcibios_report_status(u_int status_mask, int warn); -extern void register_isa_ports(unsigned int, unsigned int, unsigned int); static unsigned long dc21285_base_address(struct pci_bus *bus, unsigned int devfn) diff --git a/trunk/arch/arm/mach-integrator/pci_v3.c b/trunk/arch/arm/mach-integrator/pci_v3.c index f9043592e299..4418f6d7572d 100644 --- a/trunk/arch/arm/mach-integrator/pci_v3.c +++ b/trunk/arch/arm/mach-integrator/pci_v3.c @@ -600,4 +600,6 @@ void __init pci_v3_postinit(void) printk(KERN_ERR "PCI: unable to grab local bus timeout " "interrupt: %d\n", ret); #endif + + register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0); } diff --git a/trunk/arch/arm/mach-pxa/corgi_ssp.c b/trunk/arch/arm/mach-pxa/corgi_ssp.c index f9421318cb7a..ff6b4ee037f5 100644 --- a/trunk/arch/arm/mach-pxa/corgi_ssp.c +++ b/trunk/arch/arm/mach-pxa/corgi_ssp.c @@ -47,14 +47,15 @@ static struct corgissp_machinfo *ssp_machinfo; */ unsigned long corgi_ssp_ads7846_putget(ulong data) { - unsigned long ret,flag; + unsigned long flag; + u32 ret = 0; spin_lock_irqsave(&corgi_ssp_lock, flag); if (ssp_machinfo->cs_ads7846 >= 0) GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ssp_write_word(&corgi_ssp_dev,data); - ret = ssp_read_word(&corgi_ssp_dev); + ssp_read_word(&corgi_ssp_dev, &ret); if (ssp_machinfo->cs_ads7846 >= 0) GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); @@ -88,7 +89,9 @@ void corgi_ssp_ads7846_put(ulong data) unsigned long corgi_ssp_ads7846_get(void) { - return ssp_read_word(&corgi_ssp_dev); + u32 ret = 0; + ssp_read_word(&corgi_ssp_dev, &ret); + return ret; } EXPORT_SYMBOL(corgi_ssp_ads7846_putget); @@ -104,6 +107,7 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get); unsigned long corgi_ssp_dac_put(ulong data) { unsigned long flag, sscr1 = SSCR1_SPH; + u32 tmp; spin_lock_irqsave(&corgi_ssp_lock, flag); @@ -118,7 +122,7 @@ unsigned long corgi_ssp_dac_put(ulong data) GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_write_word(&corgi_ssp_dev,data); /* Read null data back from device to prevent SSP overflow */ - ssp_read_word(&corgi_ssp_dev); + ssp_read_word(&corgi_ssp_dev, &tmp); if (ssp_machinfo->cs_lcdcon >= 0) GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); @@ -150,7 +154,7 @@ EXPORT_SYMBOL(corgi_ssp_blduty_set); int corgi_ssp_max1111_get(ulong data) { unsigned long flag; - int voltage,voltage1,voltage2; + long voltage = 0, voltage1 = 0, voltage2 = 0; spin_lock_irqsave(&corgi_ssp_lock, flag); if (ssp_machinfo->cs_max1111 >= 0) @@ -163,15 +167,15 @@ int corgi_ssp_max1111_get(ulong data) /* TB1/RB1 */ ssp_write_word(&corgi_ssp_dev,data); - ssp_read_word(&corgi_ssp_dev); /* null read */ + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */ /* TB12/RB2 */ ssp_write_word(&corgi_ssp_dev,0); - voltage1=ssp_read_word(&corgi_ssp_dev); + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* TB13/RB3*/ ssp_write_word(&corgi_ssp_dev,0); - voltage2=ssp_read_word(&corgi_ssp_dev); + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); diff --git a/trunk/arch/arm/mach-pxa/ssp.c b/trunk/arch/arm/mach-pxa/ssp.c index 93096befd017..1fddfeaa630d 100644 --- a/trunk/arch/arm/mach-pxa/ssp.c +++ b/trunk/arch/arm/mach-pxa/ssp.c @@ -40,6 +40,8 @@ #define PXA_SSP_PORTS 3 +#define TIMEOUT 100000 + struct ssp_info_ { int irq; u32 clock; @@ -92,13 +94,18 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) * The caller is expected to perform the necessary locking. * * Returns: - * %-ETIMEDOUT timeout occurred (for future) + * %-ETIMEDOUT timeout occurred * 0 success */ int ssp_write_word(struct ssp_dev *dev, u32 data) { - while (!(SSSR_P(dev->port) & SSSR_TNF)) + int timeout = TIMEOUT; + + while (!(SSSR_P(dev->port) & SSSR_TNF)) { + if (!--timeout) + return -ETIMEDOUT; cpu_relax(); + } SSDR_P(dev->port) = data; @@ -117,15 +124,21 @@ int ssp_write_word(struct ssp_dev *dev, u32 data) * The caller is expected to perform the necessary locking. * * Returns: - * %-ETIMEDOUT timeout occurred (for future) + * %-ETIMEDOUT timeout occurred * 32-bit data success */ -int ssp_read_word(struct ssp_dev *dev) +int ssp_read_word(struct ssp_dev *dev, u32 *data) { - while (!(SSSR_P(dev->port) & SSSR_RNE)) + int timeout = TIMEOUT; + + while (!(SSSR_P(dev->port) & SSSR_RNE)) { + if (!--timeout) + return -ETIMEDOUT; cpu_relax(); + } - return SSDR_P(dev->port); + *data = SSDR_P(dev->port); + return 0; } /** @@ -136,13 +149,21 @@ int ssp_read_word(struct ssp_dev *dev) * * The caller is expected to perform the necessary locking. */ -void ssp_flush(struct ssp_dev *dev) +int ssp_flush(struct ssp_dev *dev) { + int timeout = TIMEOUT * 2; + do { while (SSSR_P(dev->port) & SSSR_RNE) { + if (!--timeout) + return -ETIMEDOUT; (void) SSDR_P(dev->port); } + if (!--timeout) + return -ETIMEDOUT; } while (SSSR_P(dev->port) & SSSR_BSY); + + return 0; } /** diff --git a/trunk/arch/arm/mach-s3c2410/dma.c b/trunk/arch/arm/mach-s3c2410/dma.c index 25855452fe8c..cc92a7b2db88 100644 --- a/trunk/arch/arm/mach-s3c2410/dma.c +++ b/trunk/arch/arm/mach-s3c2410/dma.c @@ -60,7 +60,7 @@ static void __iomem *dma_base; static kmem_cache_t *dma_kmem; /* dma channel state information */ -s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; +struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; /* debugging functions */ @@ -74,7 +74,7 @@ s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) #else static inline void -dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val) +dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val) { pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg); writel(val, dma_regaddr(chan, reg)); @@ -102,7 +102,7 @@ struct s3c2410_dma_regstate { */ static void -dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) +dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) { regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC); regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC); @@ -112,7 +112,7 @@ dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) } static void -dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan, +dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) { printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n", @@ -122,7 +122,7 @@ dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan, } static void -dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan) +dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan) { struct s3c2410_dma_regstate state; @@ -136,7 +136,7 @@ dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan) } static void -dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan) +dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) { struct s3c2410_dma_regstate state; @@ -164,7 +164,7 @@ dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan) */ static void -s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val) +s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val) { if (stats == NULL) return; @@ -183,7 +183,7 @@ s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val) */ static int -s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line) +s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) { int timeout = chan->load_timeout; int took; @@ -230,8 +230,8 @@ s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line) */ static inline int -s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan, - s3c2410_dma_buf_t *buf) +s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, + struct s3c2410_dma_buf *buf) { unsigned long reload; @@ -304,7 +304,7 @@ s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan, */ static void -s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op) +s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op) { if (chan->op_fn != NULL) { (chan->op_fn)(chan, op); @@ -318,8 +318,8 @@ s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op) */ static inline void -s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf, - s3c2410_dma_buffresult_t result) +s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, + enum s3c2410_dma_buffresult result) { pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n", chan->callback_fn, buf, buf->id, buf->size, result); @@ -334,7 +334,7 @@ s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf, * start a dma channel going */ -static int s3c2410_dma_start(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) { unsigned long tmp; unsigned long flags; @@ -430,7 +430,7 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan) */ static int -s3c2410_dma_canload(s3c2410_dma_chan_t *chan) +s3c2410_dma_canload(struct s3c2410_dma_chan *chan) { if (chan->load_state == S3C2410_DMALOAD_NONE || chan->load_state == S3C2410_DMALOAD_1RUNNING) @@ -460,8 +460,8 @@ s3c2410_dma_canload(s3c2410_dma_chan_t *chan) int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; - s3c2410_dma_buf_t *buf; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_buf *buf; unsigned long flags; check_channel(channel); @@ -540,7 +540,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, EXPORT_SYMBOL(s3c2410_dma_enqueue); static inline void -s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) +s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf) { int magicok = (buf->magic == BUF_MAGIC); @@ -560,7 +560,7 @@ s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) */ static inline void -s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan) +s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) { pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n", chan->number, chan->load_state); @@ -601,8 +601,8 @@ s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan) static irqreturn_t s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) { - s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw; - s3c2410_dma_buf_t *buf; + struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw; + struct s3c2410_dma_buf *buf; buf = chan->curr; @@ -731,10 +731,10 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) * get control of an dma channel */ -int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client, +int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client, void *dev) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; unsigned long flags; int err; @@ -807,9 +807,9 @@ EXPORT_SYMBOL(s3c2410_dma_request); * allowed to go through. */ -int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) +int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; unsigned long flags; check_channel(channel); @@ -846,7 +846,7 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) EXPORT_SYMBOL(s3c2410_dma_free); -static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) { unsigned long tmp; unsigned long flags; @@ -880,7 +880,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) return 0; } -void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan) +void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) { unsigned long tmp; unsigned int timeout = 0x10000; @@ -901,9 +901,9 @@ void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan) * stop the channel, and remove all current and pending transfers */ -static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan) { - s3c2410_dma_buf_t *buf, *next; + struct s3c2410_dma_buf *buf, *next; unsigned long flags; pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number); @@ -958,7 +958,7 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan) } int -s3c2410_dma_started(s3c2410_dma_chan_t *chan) +s3c2410_dma_started(struct s3c2410_dma_chan *chan) { unsigned long flags; @@ -995,9 +995,9 @@ s3c2410_dma_started(s3c2410_dma_chan_t *chan) } int -s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op) +s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1046,7 +1046,7 @@ int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", __FUNCTION__, channel, xferunit, dcon); @@ -1086,7 +1086,7 @@ EXPORT_SYMBOL(s3c2410_dma_config); int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1106,7 +1106,7 @@ EXPORT_SYMBOL(s3c2410_dma_setflags); int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1121,7 +1121,7 @@ EXPORT_SYMBOL(s3c2410_dma_set_opfn); int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1149,11 +1149,11 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); */ int s3c2410_dma_devconfig(int channel, - s3c2410_dmasrc_t source, + enum s3c2410_dmasrc source, int hwcfg, unsigned long devaddr) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig); int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1222,7 +1222,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) { - s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev); + struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev); printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); @@ -1262,7 +1262,7 @@ static struct sysdev_class dma_sysclass = { static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) { - memset(p, 0, sizeof(s3c2410_dma_buf_t)); + memset(p, 0, sizeof(struct s3c2410_dma_buf)); } @@ -1270,7 +1270,7 @@ static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) static int __init s3c2410_init_dma(void) { - s3c2410_dma_chan_t *cp; + struct s3c2410_dma_chan *cp; int channel; int ret; @@ -1288,7 +1288,7 @@ static int __init s3c2410_init_dma(void) goto err; } - dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0, + dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0, SLAB_HWCACHE_ALIGN, s3c2410_dma_cache_ctor, NULL); @@ -1301,7 +1301,7 @@ static int __init s3c2410_init_dma(void) for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) { cp = &s3c2410_chans[channel]; - memset(cp, 0, sizeof(s3c2410_dma_chan_t)); + memset(cp, 0, sizeof(struct s3c2410_dma_chan)); /* dma channel irqs are in order.. */ cp->number = channel; diff --git a/trunk/arch/arm/mach-sa1100/ssp.c b/trunk/arch/arm/mach-sa1100/ssp.c index 1604dadf27fc..5eba5fbbb561 100644 --- a/trunk/arch/arm/mach-sa1100/ssp.c +++ b/trunk/arch/arm/mach-sa1100/ssp.c @@ -23,6 +23,8 @@ #include #include +#define TIMEOUT 100000 + static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int status = Ser4SSSR; @@ -47,18 +49,27 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) * The caller is expected to perform the necessary locking. * * Returns: - * %-ETIMEDOUT timeout occurred (for future) + * %-ETIMEDOUT timeout occurred * 0 success */ int ssp_write_word(u16 data) { - while (!(Ser4SSSR & SSSR_TNF)) + int timeout = TIMEOUT; + + while (!(Ser4SSSR & SSSR_TNF)) { + if (!--timeout) + return -ETIMEDOUT; cpu_relax(); + } Ser4SSDR = data; - while (!(Ser4SSSR & SSSR_BSY)) + timeout = TIMEOUT; + while (!(Ser4SSSR & SSSR_BSY)) { + if (!--timeout) + return -ETIMEDOUT; cpu_relax(); + } return 0; } @@ -75,15 +86,22 @@ int ssp_write_word(u16 data) * The caller is expected to perform the necessary locking. * * Returns: - * %-ETIMEDOUT timeout occurred (for future) + * %-ETIMEDOUT timeout occurred * 16-bit data success */ -int ssp_read_word(void) +int ssp_read_word(u16 *data) { - while (!(Ser4SSSR & SSSR_RNE)) + int timeout = TIMEOUT; + + while (!(Ser4SSSR & SSSR_RNE)) { + if (!--timeout) + return -ETIMEDOUT; cpu_relax(); + } + + *data = (u16)Ser4SSDR; - return Ser4SSDR; + return 0; } /** @@ -93,14 +111,26 @@ int ssp_read_word(void) * is empty. * * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred + * 0 success */ -void ssp_flush(void) +int ssp_flush(void) { + int timeout = TIMEOUT * 2; + do { while (Ser4SSSR & SSSR_RNE) { + if (!--timeout) + return -ETIMEDOUT; (void) Ser4SSDR; } + if (!--timeout) + return -ETIMEDOUT; } while (Ser4SSSR & SSSR_BSY); + + return 0; } /** diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index 5f80f184cd32..b4f220dd5eb8 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -46,7 +46,7 @@ config CPU_ARM710 config CPU_ARM720T bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X - select CPU_32v4 + select CPU_32v4T select CPU_ABRT_LV4T select CPU_CACHE_V4 select CPU_CACHE_VIVT @@ -64,7 +64,7 @@ config CPU_ARM920T bool "Support ARM920T processor" depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200 - select CPU_32v4 + select CPU_32v4T select CPU_ABRT_EV4T select CPU_CACHE_V4WT select CPU_CACHE_VIVT @@ -85,7 +85,7 @@ config CPU_ARM922T bool "Support ARM922T processor" if ARCH_INTEGRATOR depends on ARCH_LH7A40X || ARCH_INTEGRATOR default y if ARCH_LH7A40X - select CPU_32v4 + select CPU_32v4T select CPU_ABRT_EV4T select CPU_CACHE_V4WT select CPU_CACHE_VIVT @@ -104,7 +104,7 @@ config CPU_ARM925T bool "Support ARM925T processor" if ARCH_OMAP1 depends on ARCH_OMAP15XX default y if ARCH_OMAP15XX - select CPU_32v4 + select CPU_32v4T select CPU_ABRT_EV4T select CPU_CACHE_V4WT select CPU_CACHE_VIVT @@ -285,6 +285,11 @@ config CPU_32v4 select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP +config CPU_32v4T + bool + select TLS_REG_EMUL if SMP || !MMU + select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + config CPU_32v5 bool select TLS_REG_EMUL if SMP || !MMU diff --git a/trunk/arch/arm/mm/flush.c b/trunk/arch/arm/mm/flush.c index b103e56806bd..d438ce41cdd5 100644 --- a/trunk/arch/arm/mm/flush.c +++ b/trunk/arch/arm/mm/flush.c @@ -87,6 +87,32 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig if (cache_is_vipt_aliasing()) flush_pfn_alias(pfn, user_addr); } + +void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, + unsigned long uaddr, void *kaddr, + unsigned long len, int write) +{ + if (cache_is_vivt()) { + if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { + unsigned long addr = (unsigned long)kaddr; + __cpuc_coherent_kern_range(addr, addr + len); + } + return; + } + + if (cache_is_vipt_aliasing()) { + flush_pfn_alias(page_to_pfn(page), uaddr); + return; + } + + /* VIPT non-aliasing cache */ + if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) && + vma->vm_flags | VM_EXEC) { + unsigned long addr = (unsigned long)kaddr; + /* only flushing the kernel mapping on non-aliasing VIPT */ + __cpuc_coherent_kern_range(addr, addr + len); + } +} #else #define flush_pfn_alias(pfn,vaddr) do { } while (0) #endif diff --git a/trunk/arch/arm/vfp/vfp.h b/trunk/arch/arm/vfp/vfp.h index 4b97950984e9..96fdf30f6a3b 100644 --- a/trunk/arch/arm/vfp/vfp.h +++ b/trunk/arch/arm/vfp/vfp.h @@ -156,7 +156,7 @@ struct vfp_single { }; extern s32 vfp_get_float(unsigned int reg); -extern void vfp_put_float(unsigned int reg, s32 val); +extern void vfp_put_float(s32 val, unsigned int reg); /* * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa @@ -267,7 +267,7 @@ struct vfp_double { */ #define VFP_REG_ZERO 16 extern u64 vfp_get_double(unsigned int reg); -extern void vfp_put_double(unsigned int reg, u64 val); +extern void vfp_put_double(u64 val, unsigned int reg); #define VFP_DOUBLE_MANTISSA_BITS (52) #define VFP_DOUBLE_EXPONENT_BITS (11) @@ -341,15 +341,17 @@ static inline int vfp_double_type(struct vfp_double *s) u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); -/* - * System registers - */ -extern u32 vfp_get_sys(unsigned int reg); -extern void vfp_put_sys(unsigned int reg, u32 val); - u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); /* * A special flag to tell the normalisation code not to normalise. */ #define VFP_NAN_FLAG 0x100 + +/* + * A bit pattern used to indicate the initial (unset) value of the + * exception mask, in case nothing handles an instruction. This + * doesn't include the NAN flag, which get masked out before + * we check for an error. + */ +#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG) diff --git a/trunk/arch/arm/vfp/vfpdouble.c b/trunk/arch/arm/vfp/vfpdouble.c index 009038c8113e..add48e36c2dc 100644 --- a/trunk/arch/arm/vfp/vfpdouble.c +++ b/trunk/arch/arm/vfp/vfpdouble.c @@ -195,7 +195,7 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce s64 d = vfp_double_pack(vd); pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func, dd, d, exceptions); - vfp_put_double(dd, d); + vfp_put_double(d, dd); } return exceptions; } @@ -250,19 +250,19 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, */ static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr) { - vfp_put_double(dd, vfp_double_packed_abs(vfp_get_double(dm))); + vfp_put_double(vfp_double_packed_abs(vfp_get_double(dm)), dd); return 0; } static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr) { - vfp_put_double(dd, vfp_get_double(dm)); + vfp_put_double(vfp_get_double(dm), dd); return 0; } static u32 vfp_double_fneg(int dd, int unused, int dm, u32 fpscr) { - vfp_put_double(dd, vfp_double_packed_negate(vfp_get_double(dm))); + vfp_put_double(vfp_double_packed_negate(vfp_get_double(dm)), dd); return 0; } @@ -287,7 +287,7 @@ static u32 vfp_double_fsqrt(int dd, int unused, int dm, u32 fpscr) vdp = &vfp_double_default_qnan; ret = FPSCR_IOC; } - vfp_put_double(dd, vfp_double_pack(vdp)); + vfp_put_double(vfp_double_pack(vdp), dd); return ret; } @@ -465,7 +465,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr) */ if (tm & (VFP_INFINITY|VFP_NAN)) { vsd.exponent = 255; - if (tm & VFP_NAN) + if (tm == VFP_QNAN) vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; goto pack_nan; } else if (tm & VFP_ZERO) @@ -476,7 +476,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr) return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts"); pack_nan: - vfp_put_float(sd, vfp_single_pack(&vsd)); + vfp_put_float(vfp_single_pack(&vsd), sd); return exceptions; } @@ -573,7 +573,7 @@ static u32 vfp_double_ftoui(int sd, int unused, int dm, u32 fpscr) pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); - vfp_put_float(sd, d); + vfp_put_float(d, sd); return exceptions; } @@ -648,7 +648,7 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr) pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); - vfp_put_float(sd, (s32)d); + vfp_put_float((s32)d, sd); return exceptions; } @@ -1084,7 +1084,7 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr) vdn_nan: exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); pack: - vfp_put_double(dd, vfp_double_pack(&vdd)); + vfp_put_double(vfp_double_pack(&vdd), dd); return exceptions; vdm_nan: @@ -1104,7 +1104,7 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr) goto pack; invalid: - vfp_put_double(dd, vfp_double_pack(&vfp_double_default_qnan)); + vfp_put_double(vfp_double_pack(&vfp_double_default_qnan), dd); return FPSCR_IOC; } @@ -1127,7 +1127,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) { u32 op = inst & FOP_MASK; u32 exceptions = 0; - unsigned int dd = vfp_get_dd(inst); + unsigned int dest; unsigned int dn = vfp_get_dn(inst); unsigned int dm = vfp_get_dm(inst); unsigned int vecitr, veclen, vecstride; @@ -1136,11 +1136,21 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) veclen = fpscr & FPSCR_LENGTH_MASK; vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2; + /* + * fcvtds takes an sN register number as destination, not dN. + * It also always operates on scalars. + */ + if ((inst & FEXT_MASK) == FEXT_FCVT) { + veclen = 0; + dest = vfp_get_sd(inst); + } else + dest = vfp_get_dd(inst); + /* * If destination bank is zero, vector length is always '1'. * ARM DDI0100F C5.1.3, C5.3.2. */ - if (FREG_BANK(dd) == 0) + if (FREG_BANK(dest) == 0) veclen = 0; pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, @@ -1153,16 +1163,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { u32 except; - if (op == FOP_EXT) + if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) + pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n", + vecitr >> FPSCR_LENGTH_BIT, + dest, dn, dm); + else if (op == FOP_EXT) pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n", vecitr >> FPSCR_LENGTH_BIT, - dd, dn, dm); + dest, dn, dm); else pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n", vecitr >> FPSCR_LENGTH_BIT, - dd, dn, FOP_TO_IDX(op), dm); + dest, dn, FOP_TO_IDX(op), dm); - except = fop(dd, dn, dm, fpscr); + except = fop(dest, dn, dm, fpscr); pr_debug("VFP: itr%d: exceptions=%08x\n", vecitr >> FPSCR_LENGTH_BIT, except); @@ -1180,7 +1194,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) * we encounter an exception. We continue. */ - dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6); + dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6); dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6); if (FREG_BANK(dm) != 0) dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6); diff --git a/trunk/arch/arm/vfp/vfphw.S b/trunk/arch/arm/vfp/vfphw.S index eb683cd77163..e51e6679c402 100644 --- a/trunk/arch/arm/vfp/vfphw.S +++ b/trunk/arch/arm/vfp/vfphw.S @@ -178,12 +178,12 @@ vfp_get_float: .globl vfp_put_float vfp_put_float: - add pc, pc, r0, lsl #3 + add pc, pc, r1, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcr p10, 0, r1, c\dr, c0, 0 @ fmsr r0, s0 + mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0 mov pc, lr - mcr p10, 0, r1, c\dr, c0, 4 @ fmsr r0, s1 + mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1 mov pc, lr .endr @@ -203,9 +203,9 @@ vfp_get_double: .globl vfp_put_double vfp_put_double: - add pc, pc, r0, lsl #3 + add pc, pc, r2, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - fmdrr d\dr, r1, r2 + fmdrr d\dr, r0, r1 mov pc, lr .endr diff --git a/trunk/arch/arm/vfp/vfpmodule.c b/trunk/arch/arm/vfp/vfpmodule.c index 9d265d5e748c..4178f6cc3d37 100644 --- a/trunk/arch/arm/vfp/vfpmodule.c +++ b/trunk/arch/arm/vfp/vfpmodule.c @@ -131,7 +131,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ pr_debug("VFP: raising exceptions %08x\n", exceptions); - if (exceptions == (u32)-1) { + if (exceptions == VFP_EXCEPTION_ERROR) { vfp_panic("unhandled bounce"); vfp_raise_sigfpe(0, regs); return; @@ -170,7 +170,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ */ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs) { - u32 exceptions = (u32)-1; + u32 exceptions = VFP_EXCEPTION_ERROR; pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr); diff --git a/trunk/arch/arm/vfp/vfpsingle.c b/trunk/arch/arm/vfp/vfpsingle.c index dae2c2f46052..8f6c179cafbe 100644 --- a/trunk/arch/arm/vfp/vfpsingle.c +++ b/trunk/arch/arm/vfp/vfpsingle.c @@ -200,7 +200,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce s32 d = vfp_single_pack(vs); pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, sd, d, exceptions); - vfp_put_float(sd, d); + vfp_put_float(d, sd); } return exceptions; @@ -257,19 +257,19 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, */ static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr) { - vfp_put_float(sd, vfp_single_packed_abs(m)); + vfp_put_float(vfp_single_packed_abs(m), sd); return 0; } static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr) { - vfp_put_float(sd, m); + vfp_put_float(m, sd); return 0; } static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr) { - vfp_put_float(sd, vfp_single_packed_negate(m)); + vfp_put_float(vfp_single_packed_negate(m), sd); return 0; } @@ -333,7 +333,7 @@ static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr) vsp = &vfp_single_default_qnan; ret = FPSCR_IOC; } - vfp_put_float(sd, vfp_single_pack(vsp)); + vfp_put_float(vfp_single_pack(vsp), sd); return ret; } @@ -506,7 +506,7 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr) */ if (tm & (VFP_INFINITY|VFP_NAN)) { vdd.exponent = 2047; - if (tm & VFP_NAN) + if (tm == VFP_QNAN) vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; goto pack_nan; } else if (tm & VFP_ZERO) @@ -514,14 +514,10 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr) else vdd.exponent = vsm.exponent + (1023 - 127); - /* - * Technically, if bit 0 of dd is set, this is an invalid - * instruction. However, we ignore this for efficiency. - */ return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd"); pack_nan: - vfp_put_double(dd, vfp_double_pack(&vdd)); + vfp_put_double(vfp_double_pack(&vdd), dd); return exceptions; } @@ -617,7 +613,7 @@ static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr) pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); - vfp_put_float(sd, d); + vfp_put_float(d, sd); return exceptions; } @@ -696,7 +692,7 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr) pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); - vfp_put_float(sd, (s32)d); + vfp_put_float((s32)d, sd); return exceptions; } @@ -1131,7 +1127,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr) vsn_nan: exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); pack: - vfp_put_float(sd, vfp_single_pack(&vsd)); + vfp_put_float(vfp_single_pack(&vsd), sd); return exceptions; vsm_nan: @@ -1151,7 +1147,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr) goto pack; invalid: - vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan)); + vfp_put_float(vfp_single_pack(&vfp_single_default_qnan), sd); return FPSCR_IOC; } @@ -1174,7 +1170,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) { u32 op = inst & FOP_MASK; u32 exceptions = 0; - unsigned int sd = vfp_get_sd(inst); + unsigned int dest; unsigned int sn = vfp_get_sn(inst); unsigned int sm = vfp_get_sm(inst); unsigned int vecitr, veclen, vecstride; @@ -1183,11 +1179,23 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) veclen = fpscr & FPSCR_LENGTH_MASK; vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); + /* + * fcvtsd takes a dN register number as destination, not sN. + * Technically, if bit 0 of dd is set, this is an invalid + * instruction. However, we ignore this for efficiency. + * It also only operates on scalars. + */ + if ((inst & FEXT_MASK) == FEXT_FCVT) { + veclen = 0; + dest = vfp_get_dd(inst); + } else + dest = vfp_get_sd(inst); + /* * If destination bank is zero, vector length is always '1'. * ARM DDI0100F C5.1.3, C5.3.2. */ - if (FREG_BANK(sd) == 0) + if (FREG_BANK(dest) == 0) veclen = 0; pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, @@ -1201,15 +1209,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) s32 m = vfp_get_float(sm); u32 except; - if (op == FOP_EXT) + if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) + pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n", + vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m); + else if (op == FOP_EXT) pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n", - vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m); + vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m); else pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n", - vecitr >> FPSCR_LENGTH_BIT, sd, sn, + vecitr >> FPSCR_LENGTH_BIT, dest, sn, FOP_TO_IDX(op), sm, m); - except = fop(sd, sn, m, fpscr); + except = fop(dest, sn, m, fpscr); pr_debug("VFP: itr%d: exceptions=%08x\n", vecitr >> FPSCR_LENGTH_BIT, except); @@ -1227,7 +1238,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) * we encounter an exception. We continue. */ - sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7); + dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7); sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); if (FREG_BANK(sm) != 0) sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); diff --git a/trunk/arch/i386/kernel/head.S b/trunk/arch/i386/kernel/head.S index eb79aa2fa8bb..a6b8bd89aa27 100644 --- a/trunk/arch/i386/kernel/head.S +++ b/trunk/arch/i386/kernel/head.S @@ -317,20 +317,14 @@ is386: movl $2,%ecx # set MP movl %eax,%gs lldt %ax cld # gcc2 wants the direction flag cleared at all times + pushl %eax # fake return address #ifdef CONFIG_SMP movb ready, %cl movb $1, ready - cmpb $0,%cl - je 1f # the first CPU calls start_kernel - # all other CPUs call initialize_secondary - call initialize_secondary - jmp L6 -1: + cmpb $0,%cl # the first CPU calls start_kernel + jne initialize_secondary # all other CPUs call initialize_secondary #endif /* CONFIG_SMP */ - call start_kernel -L6: - jmp L6 # main should never return here, but - # just in case, we know what happens. + jmp start_kernel /* * We depend on ET to be correct. This checks for 287/387. diff --git a/trunk/arch/i386/kernel/hpet.c b/trunk/arch/i386/kernel/hpet.c index c6737c35815d..17647a530b2f 100644 --- a/trunk/arch/i386/kernel/hpet.c +++ b/trunk/arch/i386/kernel/hpet.c @@ -35,7 +35,7 @@ static int __init init_hpet_clocksource(void) void __iomem* hpet_base; u64 tmp; - if (!hpet_address) + if (!is_hpet_enabled()) return -ENODEV; /* calculate the hpet address: */ diff --git a/trunk/arch/i386/kernel/irq.c b/trunk/arch/i386/kernel/irq.c index 6cb529f60dcc..5fe547cd8f9f 100644 --- a/trunk/arch/i386/kernel/irq.c +++ b/trunk/arch/i386/kernel/irq.c @@ -82,10 +82,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs) } #endif - if (!irq_desc[irq].handle_irq) { - __do_IRQ(irq, regs); - goto out_exit; - } #ifdef CONFIG_4KSTACKS curctx = (union irq_ctx *) current_thread_info(); @@ -125,7 +121,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs) #endif __do_IRQ(irq, regs); -out_exit: irq_exit(); return 1; diff --git a/trunk/arch/i386/kernel/setup.c b/trunk/arch/i386/kernel/setup.c index f1682206d304..345ffb7d904d 100644 --- a/trunk/arch/i386/kernel/setup.c +++ b/trunk/arch/i386/kernel/setup.c @@ -956,38 +956,6 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) return 0; } - /* - * This function checks if the entire range is mapped with type. - * - * Note: this function only works correct if the e820 table is sorted and - * not-overlapping, which is the case - */ -int __init -e820_all_mapped(unsigned long s, unsigned long e, unsigned type) -{ - u64 start = s; - u64 end = e; - int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - if (type && ei->type != type) - continue; - /* is the region (part) in overlap with the current region ?*/ - if (ei->addr >= end || ei->addr + ei->size <= start) - continue; - /* if the region is at the beginning of we move - * start to the end of the region since it's ok until there - */ - if (ei->addr <= start) - start = ei->addr + ei->size; - /* if start is now at or beyond end, we're done, full - * coverage */ - if (start >= end) - return 1; /* we're done */ - } - return 0; -} - /* * Find the highest page frame number we have available */ diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index 82e0fd02af1c..7e9edafffd8a 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; +#ifdef CONFIG_STACK_UNWIND static int call_trace = 1; +#else +#define call_trace (-1) +#endif ATOMIC_NOTIFIER_HEAD(i386die_chain); int register_die_notifier(struct notifier_block *nb) @@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, if (unwind_init_blocked(&info, task) == 0) unw_ret = show_trace_unwind(&info, log_lvl); } - if (unw_ret > 0 && !arch_unw_user_mode(&info)) { -#ifdef CONFIG_STACK_UNWIND - print_symbol("DWARF2 unwinder stuck at %s\n", - UNW_PC(&info)); - if (call_trace == 1) { - printk("Leftover inexact backtrace:\n"); - if (UNW_SP(&info)) + if (unw_ret > 0) { + if (call_trace == 1 && !arch_unw_user_mode(&info)) { + print_symbol("DWARF2 unwinder stuck at %s\n", + UNW_PC(&info)); + if (UNW_SP(&info) >= PAGE_OFFSET) { + printk("Leftover inexact backtrace:\n"); stack = (void *)UNW_SP(&info); - } else if (call_trace > 1) + } else + printk("Full inexact backtrace again:\n"); + } else if (call_trace >= 1) return; else printk("Full inexact backtrace again:\n"); -#else + } else printk("Inexact backtrace:\n"); -#endif - } } if (task == current) { @@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s) } __setup("kstack=", kstack_setup); +#ifdef CONFIG_STACK_UNWIND static int __init call_trace_setup(char *s) { if (strcmp(s, "old") == 0) @@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s) return 1; } __setup("call_trace=", call_trace_setup); +#endif diff --git a/trunk/arch/i386/pci/common.c b/trunk/arch/i386/pci/common.c index 0a362e3aeac5..1220dd828ce3 100644 --- a/trunk/arch/i386/pci/common.c +++ b/trunk/arch/i386/pci/common.c @@ -237,6 +237,11 @@ char * __devinit pcibios_setup(char *str) pci_probe &= ~PCI_PROBE_MMCONF; return NULL; } + /* override DMI blacklist */ + else if (!strcmp(str, "mmconf")) { + pci_probe |= PCI_PROBE_MMCONF_FORCE; + return NULL; + } #endif else if (!strcmp(str, "noacpi")) { acpi_noirq_set(); diff --git a/trunk/arch/i386/pci/mmconfig.c b/trunk/arch/i386/pci/mmconfig.c index 972180f738d9..ef5a2faa7d82 100644 --- a/trunk/arch/i386/pci/mmconfig.c +++ b/trunk/arch/i386/pci/mmconfig.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "pci.h" @@ -187,9 +188,31 @@ static __init void unreachable_devices(void) } } +static int disable_mcfg(struct dmi_system_id *d) +{ + printk("PCI: %s detected. Disabling MCFG.\n", d->ident); + pci_probe &= ~PCI_PROBE_MMCONF; + return 0; +} + +static struct dmi_system_id __initdata dmi_bad_mcfg[] = { + /* Has broken MCFG table that makes the system hang when used */ + { + .callback = disable_mcfg, + .ident = "Intel D3C5105 SDV", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Intel"), + DMI_MATCH(DMI_BOARD_NAME, "D26928"), + }, + }, + {} +}; + void __init pci_mmcfg_init(void) { - if ((pci_probe & PCI_PROBE_MMCONF) == 0) + dmi_check_system(dmi_bad_mcfg); + + if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0) return; acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); @@ -198,15 +221,6 @@ void __init pci_mmcfg_init(void) (pci_mmcfg_config[0].base_address == 0)) return; - if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, - E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", - pci_mmcfg_config[0].base_address); - printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); - return; - } - printk(KERN_INFO "PCI: Using MMCONFIG\n"); raw_pci_ops = &pci_mmcfg; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; diff --git a/trunk/arch/i386/pci/pci.h b/trunk/arch/i386/pci/pci.h index bf4e79335388..49a849b3a241 100644 --- a/trunk/arch/i386/pci/pci.h +++ b/trunk/arch/i386/pci/pci.h @@ -16,7 +16,8 @@ #define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF2 0x0004 #define PCI_PROBE_MMCONF 0x0008 -#define PCI_PROBE_MASK 0x000f +#define PCI_PROBE_MMCONF_FORCE 0x0010 +#define PCI_PROBE_MASK 0x00ff #define PCI_NO_SORT 0x0100 #define PCI_BIOS_SORT 0x0200 diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 47de9ee6bcd6..674de8943478 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -258,7 +258,7 @@ config NR_CPUS int "Maximum number of CPUs (2-1024)" range 2 1024 depends on SMP - default "64" + default "1024" help You should set this to the number of CPUs in your system, but keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but @@ -354,7 +354,7 @@ config NUMA config NODES_SHIFT int "Max num nodes shift(3-10)" range 3 10 - default "8" + default "10" depends on NEED_MULTIPLE_NODES help This option specifies the maximum number of nodes in your SSI system. diff --git a/trunk/arch/ia64/kernel/topology.c b/trunk/arch/ia64/kernel/topology.c index d24fa393b182..f648c610b10c 100644 --- a/trunk/arch/ia64/kernel/topology.c +++ b/trunk/arch/ia64/kernel/topology.c @@ -67,10 +67,8 @@ static int __init topology_init(void) #endif sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL); - if (!sysfs_cpus) { - err = -ENOMEM; - goto out; - } + if (!sysfs_cpus) + panic("kzalloc in topology_init failed - NR_CPUS too big?"); for_each_present_cpu(i) { if((err = arch_register_cpu(i))) diff --git a/trunk/arch/ia64/sn/kernel/xpc_channel.c b/trunk/arch/ia64/sn/kernel/xpc_channel.c index c2f69f7942af..1f3540826e68 100644 --- a/trunk/arch/ia64/sn/kernel/xpc_channel.c +++ b/trunk/arch/ia64/sn/kernel/xpc_channel.c @@ -279,8 +279,8 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, return part->reason; } - bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst), - (u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL); + bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt, + (BTE_NORMAL | BTE_WACQUIRE), NULL); if (bte_ret == BTE_SUCCESS) { return xpcSuccess; } diff --git a/trunk/arch/ia64/sn/kernel/xpc_main.c b/trunk/arch/ia64/sn/kernel/xpc_main.c index 5e8e59efb347..4d026f9dd98b 100644 --- a/trunk/arch/ia64/sn/kernel/xpc_main.c +++ b/trunk/arch/ia64/sn/kernel/xpc_main.c @@ -1052,6 +1052,8 @@ xpc_do_exit(enum xpc_retval reason) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); } @@ -1212,24 +1214,20 @@ xpc_init(void) partid_t partid; struct xpc_partition *part; pid_t pid; + size_t buf_size; if (!ia64_platform_is("sn2")) { return -ENODEV; } - /* - * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng - * various portions of a partition's reserved page. Its size is based - * on the size of the reserved page header and part_nasids mask. So we - * need to ensure that the other items will fit as well. - */ - if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) { - dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n"); - return -EPERM; - } - DBUG_ON((u64) xpc_remote_copy_buffer != - L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer)); + + buf_size = max(XPC_RP_VARS_SIZE, + XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES); + xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size, + GFP_KERNEL, &xpc_remote_copy_buffer_base); + if (xpc_remote_copy_buffer == NULL) + return -ENOMEM; snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); @@ -1293,6 +1291,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } @@ -1311,6 +1311,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } @@ -1362,6 +1364,8 @@ xpc_init(void) if (xpc_sysctl) { unregister_sysctl_table(xpc_sysctl); } + + kfree(xpc_remote_copy_buffer_base); return -EBUSY; } diff --git a/trunk/arch/ia64/sn/kernel/xpc_partition.c b/trunk/arch/ia64/sn/kernel/xpc_partition.c index 2a89cfce4954..57c723f5cba4 100644 --- a/trunk/arch/ia64/sn/kernel/xpc_partition.c +++ b/trunk/arch/ia64/sn/kernel/xpc_partition.c @@ -71,19 +71,15 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; * Generic buffer used to store a local copy of portions of a remote * partition's reserved page (either its header and part_nasids mask, * or its vars). - * - * xpc_discovery runs only once and is a seperate thread that is - * very likely going to be processing in parallel with receiving - * interrupts. */ -char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE + - XP_NASID_MASK_BYTES]; +char *xpc_remote_copy_buffer; +void *xpc_remote_copy_buffer_base; /* * Guarantee that the kmalloc'd memory is cacheline aligned. */ -static void * +void * xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) { /* see if kmalloc will give us cachline aligned memory by default */ @@ -148,7 +144,7 @@ xpc_get_rsvd_page_pa(int nasid) } } - bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len, + bte_res = xp_bte_copy(rp_pa, buf, buf_len, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bte_res != BTE_SUCCESS) { dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res); @@ -447,7 +443,7 @@ xpc_check_remote_hb(void) /* pull the remote_hb cache line */ bres = xp_bte_copy(part->remote_vars_pa, - ia64_tpa((u64) remote_vars), + (u64) remote_vars, XPC_RP_VARS_SIZE, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { @@ -498,8 +494,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, /* pull over the reserved page header and part_nasids mask */ - - bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp), + bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp, XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { @@ -554,11 +549,8 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars) return xpcVarsNotSet; } - /* pull over the cross partition variables */ - - bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars), - XPC_RP_VARS_SIZE, + bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE, (BTE_NOTIFY | BTE_WACQUIRE), NULL); if (bres != BTE_SUCCESS) { return xpc_map_bte_errors(bres); @@ -1239,7 +1231,7 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask) part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa); - bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask), + bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask, xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL); return xpc_map_bte_errors(bte_res); diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index abb325eb8f75..4d4b6fb156e1 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -354,6 +354,7 @@ endchoice config PPC_PSERIES depends on PPC_MULTIPLATFORM && PPC64 bool "IBM pSeries & new (POWER5-based) iSeries" + select MPIC select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING @@ -363,6 +364,7 @@ config PPC_PSERIES config PPC_CHRP bool "Common Hardware Reference Platform (CHRP) based machines" depends on PPC_MULTIPLATFORM && PPC32 + select MPIC select PPC_I8259 select PPC_INDIRECT_PCI select PPC_RTAS @@ -373,6 +375,7 @@ config PPC_CHRP config PPC_PMAC bool "Apple PowerMac based machines" depends on PPC_MULTIPLATFORM + select MPIC select PPC_INDIRECT_PCI if PPC32 select PPC_MPC106 if PPC32 default y @@ -380,6 +383,7 @@ config PPC_PMAC config PPC_PMAC64 bool depends on PPC_PMAC && POWER4 + select MPIC select U3_DART select MPIC_BROKEN_U3 select GENERIC_TBSYNC @@ -389,6 +393,7 @@ config PPC_PMAC64 config PPC_PREP bool "PowerPC Reference Platform (PReP) based machines" depends on PPC_MULTIPLATFORM && PPC32 && BROKEN + select MPIC select PPC_I8259 select PPC_INDIRECT_PCI select PPC_UDBG_16550 @@ -397,6 +402,7 @@ config PPC_PREP config PPC_MAPLE depends on PPC_MULTIPLATFORM && PPC64 bool "Maple 970FX Evaluation Board" + select MPIC select U3_DART select MPIC_BROKEN_U3 select GENERIC_TBSYNC @@ -439,12 +445,6 @@ config U3_DART depends on PPC_MULTIPLATFORM && PPC64 default n -config MPIC - depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \ - || MPC7448HPC2 - bool - default y - config PPC_RTAS bool default n @@ -812,6 +812,14 @@ config GENERIC_ISA_DMA depends on PPC64 || POWER4 || 6xx && !CPM2 default y +config MPIC + bool + default n + +config MPIC_WEIRD + bool + default n + config PPC_I8259 bool default n diff --git a/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts b/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts new file mode 100644 index 000000000000..d7b985e6bd2f --- /dev/null +++ b/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts @@ -0,0 +1,190 @@ +/* + * MPC7448HPC2 (Taiga) board Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * 2006 Roy Zang . + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "mpc7448hpc2"; + compatible = "mpc74xx"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells =<0>; + linux,phandle = <200>; + + PowerPC,7448@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K bytes + i-cache-size = <8000>; // L1, 32K bytes + timebase-frequency = <0>; // 33 MHz, from uboot + clock-frequency = <0>; // From U-Boot + bus-frequency = <0>; // From U-Boot + 32-bit; + linux,phandle = <201>; + linux,boot-cpu; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 20000000 // DDR2 512M at 0 + >; + }; + + tsi108@c0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "tsi-bridge"; + ranges = <00000000 c0000000 00010000>; + reg = ; + bus-frequency = <0>; + + i2c@7000 { + interrupt-parent = <7400>; + interrupts = ; + reg = <7000 400>; + device_type = "i2c"; + compatible = "tsi-i2c"; + }; + + mdio@6000 { + device_type = "mdio"; + compatible = "tsi-ethernet"; + + ethernet-phy@6000 { + linux,phandle = <6000>; + interrupt-parent = <7400>; + interrupts = <2 1>; + reg = <6000 50>; + phy-id = <8>; + device_type = "ethernet-phy"; + }; + + ethernet-phy@6400 { + linux,phandle = <6400>; + interrupt-parent = <7400>; + interrupts = <2 1>; + reg = <6000 50>; + phy-id = <9>; + device_type = "ethernet-phy"; + }; + + }; + + ethernet@6200 { + #size-cells = <0>; + device_type = "network"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; + reg = <6000 200>; + address = [ 00 06 D2 00 00 01 ]; + interrupts = <10 2>; + interrupt-parent = <7400>; + phy-handle = <6000>; + }; + + ethernet@6600 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; + reg = <6400 200>; + address = [ 00 06 D2 00 00 02 ]; + interrupts = <11 2>; + interrupt-parent = <7400>; + phy-handle = <6400>; + }; + + serial@7808 { + device_type = "serial"; + compatible = "ns16550"; + reg = <7808 200>; + clock-frequency = <3f6b5a00>; + interrupts = ; + interrupt-parent = <7400>; + }; + + serial@7c08 { + device_type = "serial"; + compatible = "ns16550"; + reg = <7c08 200>; + clock-frequency = <3f6b5a00>; + interrupts = ; + interrupt-parent = <7400>; + }; + + pic@7400 { + linux,phandle = <7400>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <7400 400>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + pci@1000 { + compatible = "tsi10x"; + device_type = "pci"; + linux,phandle = <1000>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <1000 1000>; + bus-range = <0 0>; + ranges = <02000000 0 e0000000 e0000000 0 1A000000 + 01000000 0 00000000 fa000000 0 00010000>; + clock-frequency = <7f28154>; + interrupt-parent = <7400>; + interrupts = <17 2>; + interrupt-map-mask = ; + interrupt-map = < + + /* IDSEL 0x11 */ + 0800 0 0 1 7400 24 0 + 0800 0 0 2 7400 25 0 + 0800 0 0 3 7400 26 0 + 0800 0 0 4 7400 27 0 + + /* IDSEL 0x12 */ + 1000 0 0 1 7400 25 0 + 1000 0 0 2 7400 26 0 + 1000 0 0 3 7400 27 0 + 1000 0 0 4 7400 24 0 + + /* IDSEL 0x13 */ + 1800 0 0 1 7400 26 0 + 1800 0 0 2 7400 27 0 + 1800 0 0 3 7400 24 0 + 1800 0 0 4 7400 25 0 + + /* IDSEL 0x14 */ + 2000 0 0 1 7400 27 0 + 2000 0 0 2 7400 24 0 + 2000 0 0 3 7400 25 0 + 2000 0 0 4 7400 26 0 + >; + }; + }; + +}; diff --git a/trunk/arch/powerpc/boot/dts/mpc8349emds.dts b/trunk/arch/powerpc/boot/dts/mpc8349emds.dts new file mode 100644 index 000000000000..12f5dbf3055f --- /dev/null +++ b/trunk/arch/powerpc/boot/dts/mpc8349emds.dts @@ -0,0 +1,328 @@ +/* + * MPC8349E MDS Device Tree Source + * + * Copyright 2005, 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/ { + model = "MPC8349EMDS"; + compatible = "MPC834xMDS"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8349@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // from bootloader + bus-frequency = <0>; // from bootloader + clock-frequency = <0>; // from bootloader + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 10000000>; // 256MB at 0 + }; + + soc8349@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = ; + bus-frequency = <0>; + + wdt@200 { + device_type = "watchdog"; + compatible = "mpc83xx_wdt"; + reg = <200 100>; + }; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = ; + interrupt-parent = <700>; + dfsrr; + }; + + i2c@3100 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3100 100>; + interrupts = ; + interrupt-parent = <700>; + dfsrr; + }; + + spi@7000 { + device_type = "spi"; + compatible = "mpc83xx_spi"; + reg = <7000 1000>; + interrupts = <10 8>; + interrupt-parent = <700>; + mode = <0>; + }; + + /* phy type (ULPI or SERIAL) are only types supportted for MPH */ + /* port = 0 or 1 */ + usb@22000 { + device_type = "usb"; + compatible = "fsl-usb2-mph"; + reg = <22000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <27 2>; + phy_type = "ulpi"; + port1; + }; + /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */ + usb@23000 { + device_type = "usb"; + compatible = "fsl-usb2-dr"; + reg = <23000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <26 2>; + phy_type = "ulpi"; + }; + + mdio@24520 { + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <700>; + interrupts = <11 2>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <700>; + interrupts = <12 2>; + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + address = [ 00 00 00 00 00 00 ]; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <20 8 21 8 22 8>; + interrupt-parent = <700>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + address = [ 00 00 00 00 00 00 ]; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <23 8 24 8 25 8>; + interrupt-parent = <700>; + phy-handle = <2452001>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <9 8>; + interrupt-parent = <700>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; + clock-frequency = <0>; + interrupts = ; + interrupt-parent = <700>; + }; + + pci@8500 { + interrupt-map-mask = ; + interrupt-map = < + + /* IDSEL 0x11 */ + 8800 0 0 1 700 14 8 + 8800 0 0 2 700 15 8 + 8800 0 0 3 700 16 8 + 8800 0 0 4 700 17 8 + + /* IDSEL 0x12 */ + 9000 0 0 1 700 16 8 + 9000 0 0 2 700 17 8 + 9000 0 0 3 700 14 8 + 9000 0 0 4 700 15 8 + + /* IDSEL 0x13 */ + 9800 0 0 1 700 17 8 + 9800 0 0 2 700 14 8 + 9800 0 0 3 700 15 8 + 9800 0 0 4 700 16 8 + + /* IDSEL 0x15 */ + a800 0 0 1 700 14 8 + a800 0 0 2 700 15 8 + a800 0 0 3 700 16 8 + a800 0 0 4 700 17 8 + + /* IDSEL 0x16 */ + b000 0 0 1 700 17 8 + b000 0 0 2 700 14 8 + b000 0 0 3 700 15 8 + b000 0 0 4 700 16 8 + + /* IDSEL 0x17 */ + b800 0 0 1 700 16 8 + b800 0 0 2 700 17 8 + b800 0 0 3 700 14 8 + b800 0 0 4 700 15 8 + + /* IDSEL 0x18 */ + b000 0 0 1 700 15 8 + b000 0 0 2 700 16 8 + b000 0 0 3 700 17 8 + b000 0 0 4 700 14 8>; + interrupt-parent = <700>; + interrupts = <42 8>; + bus-range = <0 0>; + ranges = <02000000 0 a0000000 a0000000 0 10000000 + 42000000 0 80000000 80000000 0 10000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8500 100>; + compatible = "83xx"; + device_type = "pci"; + }; + + pci@8600 { + interrupt-map-mask = ; + interrupt-map = < + + /* IDSEL 0x11 */ + 8800 0 0 1 700 14 8 + 8800 0 0 2 700 15 8 + 8800 0 0 3 700 16 8 + 8800 0 0 4 700 17 8 + + /* IDSEL 0x12 */ + 9000 0 0 1 700 16 8 + 9000 0 0 2 700 17 8 + 9000 0 0 3 700 14 8 + 9000 0 0 4 700 15 8 + + /* IDSEL 0x13 */ + 9800 0 0 1 700 17 8 + 9800 0 0 2 700 14 8 + 9800 0 0 3 700 15 8 + 9800 0 0 4 700 16 8 + + /* IDSEL 0x15 */ + a800 0 0 1 700 14 8 + a800 0 0 2 700 15 8 + a800 0 0 3 700 16 8 + a800 0 0 4 700 17 8 + + /* IDSEL 0x16 */ + b000 0 0 1 700 17 8 + b000 0 0 2 700 14 8 + b000 0 0 3 700 15 8 + b000 0 0 4 700 16 8 + + /* IDSEL 0x17 */ + b800 0 0 1 700 16 8 + b800 0 0 2 700 17 8 + b800 0 0 3 700 14 8 + b800 0 0 4 700 15 8 + + /* IDSEL 0x18 */ + b000 0 0 1 700 15 8 + b000 0 0 2 700 16 8 + b000 0 0 3 700 17 8 + b000 0 0 4 700 14 8>; + interrupt-parent = <700>; + interrupts = <42 8>; + bus-range = <0 0>; + ranges = <02000000 0 b0000000 b0000000 0 10000000 + 42000000 0 90000000 90000000 0 10000000 + 01000000 0 00000000 e2100000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8600 100>; + compatible = "83xx"; + device_type = "pci"; + }; + + /* May need to remove if on a part without crypto engine */ + crypto@30000 { + device_type = "crypto"; + model = "SEC2"; + compatible = "talitos"; + reg = <30000 10000>; + interrupts = ; + interrupt-parent = <700>; + num-channels = <4>; + channel-fifo-len = <18>; + exec-units-mask = <0000007e>; + /* desc mask is for rev2.0, + * we need runtime fixup for >2.0 */ + descriptor-types-mask = <01010ebf>; + }; + + /* IPIC + * interrupts cell = + * sense values match linux IORESOURCE_IRQ_* defines: + * sense == 8: Level, low assertion + * sense == 2: Edge, high-to-low change + */ + pic@700 { + linux,phandle = <700>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <700 100>; + built-in; + device_type = "ipic"; + }; + }; +}; diff --git a/trunk/arch/powerpc/configs/mpc834x_sys_defconfig b/trunk/arch/powerpc/configs/mpc834x_mds_defconfig similarity index 100% rename from trunk/arch/powerpc/configs/mpc834x_sys_defconfig rename to trunk/arch/powerpc/configs/mpc834x_mds_defconfig diff --git a/trunk/arch/powerpc/kernel/fpu.S b/trunk/arch/powerpc/kernel/fpu.S index 7e2c9fe44ac1..821e152e093c 100644 --- a/trunk/arch/powerpc/kernel/fpu.S +++ b/trunk/arch/powerpc/kernel/fpu.S @@ -2,6 +2,11 @@ * FPU support code, moved here from head.S so that it can be used * by chips which use other head-whatever.S files. * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Copyright (C) 1996 Cort Dougan + * Copyright (C) 1996 Paul Mackerras. + * Copyright (C) 1997 Dan Malek (dmalek@jlc.net). + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 7ee685433319..12c5971d6565 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -322,7 +322,8 @@ EXPORT_SYMBOL(do_softirq); static LIST_HEAD(irq_hosts); static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED; - +static DEFINE_PER_CPU(unsigned int, irq_radix_reader); +static unsigned int irq_radix_writer; struct irq_map_entry irq_map[NR_IRQS]; static unsigned int irq_virq_count = NR_IRQS; static struct irq_host *irq_default_host; @@ -455,6 +456,58 @@ void irq_set_virq_count(unsigned int count) irq_virq_count = count; } +/* radix tree not lockless safe ! we use a brlock-type mecanism + * for now, until we can use a lockless radix tree + */ +static void irq_radix_wrlock(unsigned long *flags) +{ + unsigned int cpu, ok; + + spin_lock_irqsave(&irq_big_lock, *flags); + irq_radix_writer = 1; + smp_mb(); + do { + barrier(); + ok = 1; + for_each_possible_cpu(cpu) { + if (per_cpu(irq_radix_reader, cpu)) { + ok = 0; + break; + } + } + if (!ok) + cpu_relax(); + } while(!ok); +} + +static void irq_radix_wrunlock(unsigned long flags) +{ + smp_wmb(); + irq_radix_writer = 0; + spin_unlock_irqrestore(&irq_big_lock, flags); +} + +static void irq_radix_rdlock(unsigned long *flags) +{ + local_irq_save(*flags); + __get_cpu_var(irq_radix_reader) = 1; + smp_mb(); + if (likely(irq_radix_writer == 0)) + return; + __get_cpu_var(irq_radix_reader) = 0; + smp_wmb(); + spin_lock(&irq_big_lock); + __get_cpu_var(irq_radix_reader) = 1; + spin_unlock(&irq_big_lock); +} + +static void irq_radix_rdunlock(unsigned long flags) +{ + __get_cpu_var(irq_radix_reader) = 0; + local_irq_restore(flags); +} + + unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) { @@ -604,13 +657,9 @@ void irq_dispose_mapping(unsigned int virq) /* Check if radix tree allocated yet */ if (host->revmap_data.tree.gfp_mask == 0) break; - /* XXX radix tree not safe ! remove lock whem it becomes safe - * and use some RCU sync to make sure everything is ok before we - * can re-use that map entry - */ - spin_lock_irqsave(&irq_big_lock, flags); + irq_radix_wrlock(&flags); radix_tree_delete(&host->revmap_data.tree, hwirq); - spin_unlock_irqrestore(&irq_big_lock, flags); + irq_radix_wrunlock(flags); break; } @@ -677,25 +726,24 @@ unsigned int irq_radix_revmap(struct irq_host *host, if (tree->gfp_mask == 0) return irq_find_mapping(host, hwirq); - /* XXX Current radix trees are NOT SMP safe !!! Remove that lock - * when that is fixed (when Nick's patch gets in - */ - spin_lock_irqsave(&irq_big_lock, flags); - /* Now try to resolve */ + irq_radix_rdlock(&flags); ptr = radix_tree_lookup(tree, hwirq); + irq_radix_rdunlock(flags); + /* Found it, return */ if (ptr) { virq = ptr - irq_map; - goto bail; + return virq; } /* If not there, try to insert it */ virq = irq_find_mapping(host, hwirq); - if (virq != NO_IRQ) + if (virq != NO_IRQ) { + irq_radix_wrlock(&flags); radix_tree_insert(tree, hwirq, &irq_map[virq]); - bail: - spin_unlock_irqrestore(&irq_big_lock, flags); + irq_radix_wrunlock(flags); + } return virq; } @@ -806,12 +854,12 @@ static int irq_late_init(void) struct irq_host *h; unsigned long flags; - spin_lock_irqsave(&irq_big_lock, flags); + irq_radix_wrlock(&flags); list_for_each_entry(h, &irq_hosts, link) { if (h->revmap_type == IRQ_HOST_MAP_TREE) INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC); } - spin_unlock_irqrestore(&irq_big_lock, flags); + irq_radix_wrunlock(flags); return 0; } diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index 2fce7738e9e2..138134c8c17d 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -1289,6 +1289,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev) DBG("Try to map irq for %s...\n", pci_name(pci_dev)); +#ifdef DEBUG + memset(&oirq, 0xff, sizeof(oirq)); +#endif /* Try to get a mapping from the device-tree */ if (of_irq_map_pci(pci_dev, &oirq)) { u8 line, pin; @@ -1314,8 +1317,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev) if (virq != NO_IRQ) set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); } else { - DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", - oirq.size, oirq.specifier[0], oirq.controller->full_name); + DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.specifier[1], + oirq.controller->full_name); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -1324,6 +1328,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev) DBG(" -> failed to map !\n"); return -1; } + + DBG(" -> mapped to linux irq %d\n", virq); + pci_dev->irq = virq; pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq); diff --git a/trunk/arch/powerpc/kernel/ppc_ksyms.c b/trunk/arch/powerpc/kernel/ppc_ksyms.c index f6a05f090b25..39d3bfcabcd2 100644 --- a/trunk/arch/powerpc/kernel/ppc_ksyms.c +++ b/trunk/arch/powerpc/kernel/ppc_ksyms.c @@ -126,10 +126,6 @@ EXPORT_SYMBOL(pci_bus_mem_base_phys); EXPORT_SYMBOL(pci_bus_to_hose); #endif /* CONFIG_PCI */ -#ifdef CONFIG_NOT_COHERENT_CACHE -EXPORT_SYMBOL(flush_dcache_all); -#endif - EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(kernel_thread); diff --git a/trunk/arch/powerpc/kernel/prom_init.c b/trunk/arch/powerpc/kernel/prom_init.c index 462bced40c12..4394e545f9f7 100644 --- a/trunk/arch/powerpc/kernel/prom_init.c +++ b/trunk/arch/powerpc/kernel/prom_init.c @@ -646,13 +646,13 @@ static unsigned char ibm_architecture_vec[] = { 5 - 1, /* 5 option vectors */ /* option vector 1: processor architectures supported */ - 3 - 1, /* length */ + 3 - 2, /* length */ 0, /* don't ignore, don't halt */ OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 | OV1_PPC_2_04 | OV1_PPC_2_05, /* option vector 2: Open Firmware options supported */ - 34 - 1, /* length */ + 34 - 2, /* length */ OV2_REAL_MODE, 0, 0, W(0xffffffff), /* real_base */ @@ -666,16 +666,16 @@ static unsigned char ibm_architecture_vec[] = { 48, /* max log_2(hash table size) */ /* option vector 3: processor options supported */ - 3 - 1, /* length */ + 3 - 2, /* length */ 0, /* don't ignore, don't halt */ OV3_FP | OV3_VMX, /* option vector 4: IBM PAPR implementation */ - 2 - 1, /* length */ + 2 - 2, /* length */ 0, /* don't halt */ /* option vector 5: PAPR/OF options */ - 3 - 1, /* length */ + 3 - 2, /* length */ 0, /* don't ignore, don't halt */ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES, }; diff --git a/trunk/arch/powerpc/kernel/prom_parse.c b/trunk/arch/powerpc/kernel/prom_parse.c index 11052c212ad5..a10825a5dfe6 100644 --- a/trunk/arch/powerpc/kernel/prom_parse.c +++ b/trunk/arch/powerpc/kernel/prom_parse.c @@ -639,14 +639,17 @@ void of_irq_map_init(unsigned int flags) } -int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, - struct of_irq *out_irq) +int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize, + u32 *addr, struct of_irq *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; u32 *tmp, *imap, *imask; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; + DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", + parent->full_name, intspec[0], intspec[1], ointsize); + ipar = of_node_get(parent); /* First get the #interrupt-cells property of the current cursor @@ -670,6 +673,9 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); + if (ointsize != intsize) + return -EINVAL; + /* Look for this #address-cells. We have to implement the old linux * trick of looking for the parent here as some device-trees rely on it */ @@ -875,12 +881,15 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq } intsize = *tmp; + DBG(" intsize=%d intlen=%d\n", intsize, intlen); + /* Check index */ if ((index + 1) * intsize > intlen) return -EINVAL; /* Get new specifier and map it */ - res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq); + res = of_irq_map_raw(p, intspec + index * intsize, intsize, + addr, out_irq); of_node_put(p); return res; } @@ -965,7 +974,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) laddr[0] = (pdev->bus->number << 16) | (pdev->devfn << 8); laddr[1] = laddr[2] = 0; - return of_irq_map_raw(ppnode, &lspec, laddr, out_irq); + return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); } EXPORT_SYMBOL_GPL(of_irq_map_pci); #endif /* CONFIG_PCI */ diff --git a/trunk/arch/powerpc/kernel/smp-tbsync.c b/trunk/arch/powerpc/kernel/smp-tbsync.c index f19e2e0e61e7..de59c6c31a5b 100644 --- a/trunk/arch/powerpc/kernel/smp-tbsync.c +++ b/trunk/arch/powerpc/kernel/smp-tbsync.c @@ -45,8 +45,9 @@ void __devinit smp_generic_take_timebase(void) { int cmd; u64 tb; + unsigned long flags; - local_irq_disable(); + local_irq_save(flags); while (!running) barrier(); rmb(); @@ -70,7 +71,7 @@ void __devinit smp_generic_take_timebase(void) set_tb(tb >> 32, tb & 0xfffffffful); enter_contest(tbsync->mark, -1); } - local_irq_enable(); + local_irq_restore(flags); } static int __devinit start_contest(int cmd, long offset, int num) diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index 18e59e43d2b3..a124499e65d9 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -125,15 +125,8 @@ static long timezone_offset; unsigned long ppc_proc_freq; unsigned long ppc_tb_freq; -u64 tb_last_jiffy __cacheline_aligned_in_smp; -unsigned long tb_last_stamp; - -/* - * Note that on ppc32 this only stores the bottom 32 bits of - * the timebase value, but that's enough to tell when a jiffy - * has passed. - */ -DEFINE_PER_CPU(unsigned long, last_jiffy); +static u64 tb_last_jiffy __cacheline_aligned_in_smp; +static DEFINE_PER_CPU(u64, last_jiffy); #ifdef CONFIG_VIRT_CPU_ACCOUNTING /* @@ -458,7 +451,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin_irqsave(&xtime_lock, flags); sec = xtime.tv_sec; - nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp); + nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy); } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); usec = nsec / 1000; while (usec >= 1000000) { @@ -700,7 +693,6 @@ void timer_interrupt(struct pt_regs * regs) tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { tb_last_jiffy = tb_next_jiffy; - tb_last_stamp = per_cpu(last_jiffy, cpu); do_timer(regs); timer_recalc_offset(tb_last_jiffy); timer_check_rtc(); @@ -749,7 +741,7 @@ void __init smp_space_timers(unsigned int max_cpus) int i; unsigned long half = tb_ticks_per_jiffy / 2; unsigned long offset = tb_ticks_per_jiffy / max_cpus; - unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); + u64 previous_tb = per_cpu(last_jiffy, boot_cpuid); /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ previous_tb -= tb_ticks_per_jiffy; @@ -830,7 +822,7 @@ int do_settimeofday(struct timespec *tv) * and therefore the (jiffies - wall_jiffies) computation * has been removed. */ - tb_delta = tb_ticks_since(tb_last_stamp); + tb_delta = tb_ticks_since(tb_last_jiffy); tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */ new_nsec -= SCALE_XSEC(tb_delta, 1000000000); @@ -950,8 +942,7 @@ void __init time_init(void) if (__USE_RTC()) { /* 601 processor: dec counts down by 128 every 128ns */ ppc_tb_freq = 1000000000; - tb_last_stamp = get_rtcl(); - tb_last_jiffy = tb_last_stamp; + tb_last_jiffy = get_rtcl(); } else { /* Normal PowerPC with timebase register */ ppc_md.calibrate_decr(); @@ -959,7 +950,7 @@ void __init time_init(void) ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); - tb_last_stamp = tb_last_jiffy = get_tb(); + tb_last_jiffy = get_tb(); } tb_ticks_per_jiffy = ppc_tb_freq / HZ; @@ -1036,7 +1027,7 @@ void __init time_init(void) do_gtod.varp = &do_gtod.vars[0]; do_gtod.var_idx = 0; do_gtod.varp->tb_orig_stamp = tb_last_jiffy; - __get_cpu_var(last_jiffy) = tb_last_stamp; + __get_cpu_var(last_jiffy) = tb_last_jiffy; do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; do_gtod.varp->tb_to_xs = tb_to_xs; diff --git a/trunk/arch/powerpc/lib/memcpy_64.S b/trunk/arch/powerpc/lib/memcpy_64.S index fd66acfd3e3e..7173ba98f427 100644 --- a/trunk/arch/powerpc/lib/memcpy_64.S +++ b/trunk/arch/powerpc/lib/memcpy_64.S @@ -11,6 +11,7 @@ .align 7 _GLOBAL(memcpy) + std r3,48(r1) /* save destination pointer for return value */ mtcrf 0x01,r5 cmpldi cr1,r5,16 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry @@ -38,7 +39,7 @@ _GLOBAL(memcpy) stdu r9,16(r3) bdnz 1b 3: std r8,8(r3) - beqlr + beq 3f addi r3,r3,16 ld r9,8(r4) .Ldo_tail: @@ -53,7 +54,8 @@ _GLOBAL(memcpy) 2: bf cr7*4+3,3f rotldi r9,r9,8 stb r9,0(r3) -3: blr +3: ld r3,48(r1) /* return dest pointer */ + blr .Lsrc_unaligned: srdi r6,r5,3 @@ -115,7 +117,7 @@ _GLOBAL(memcpy) 5: srd r12,r9,r11 or r12,r8,r12 std r12,24(r3) - beqlr + beq 4f cmpwi cr1,r5,8 addi r3,r3,32 sld r9,r9,r10 @@ -167,4 +169,5 @@ _GLOBAL(memcpy) 3: bf cr7*4+3,4f lbz r0,0(r4) stb r0,0(r3) -4: blr +4: ld r3,48(r1) /* return dest pointer */ + blr diff --git a/trunk/arch/powerpc/mm/44x_mmu.c b/trunk/arch/powerpc/mm/44x_mmu.c index 376829ed2211..0a0a0487b334 100644 --- a/trunk/arch/powerpc/mm/44x_mmu.c +++ b/trunk/arch/powerpc/mm/44x_mmu.c @@ -103,7 +103,7 @@ unsigned long __init mmu_mapin_ram(void) /* Determine number of entries necessary to cover lowmem */ pinned_tlbs = (unsigned int) - (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT); + (_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT); /* Write upper watermark to save location */ tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs; @@ -111,7 +111,7 @@ unsigned long __init mmu_mapin_ram(void) /* If necessary, set additional pinned TLBs */ if (pinned_tlbs > 1) for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) { - unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE; + unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE; ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr); } diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c index b46305645d38..cf3967a66fb5 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -46,26 +46,6 @@ unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; #endif -#ifdef CONFIG_PCI -static int -mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) -{ - static char pci_irq_table[][4] = - /* - * PCI IDSEL/INTPIN->INTLINE - * A B C D - */ - { - {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */ - {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */ - {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */ - }; - - const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4; - return PCI_IRQ_TABLE_LOOKUP; -} -#endif /* CONFIG_PCI */ - /* ************************************************************************ * * Setup the architecture @@ -92,8 +72,6 @@ static void __init mpc834x_itx_setup_arch(void) for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); - ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = mpc83xx_map_irq; ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif @@ -106,25 +84,13 @@ static void __init mpc834x_itx_setup_arch(void) void __init mpc834x_itx_init_IRQ(void) { - u8 senses[8] = { - 0, /* EXT 0 */ - IRQ_SENSE_LEVEL, /* EXT 1 */ - IRQ_SENSE_LEVEL, /* EXT 2 */ - 0, /* EXT 3 */ -#ifdef CONFIG_PCI - IRQ_SENSE_LEVEL, /* EXT 4 */ - IRQ_SENSE_LEVEL, /* EXT 5 */ - IRQ_SENSE_LEVEL, /* EXT 6 */ - IRQ_SENSE_LEVEL, /* EXT 7 */ -#else - 0, /* EXT 4 */ - 0, /* EXT 5 */ - 0, /* EXT 6 */ - 0, /* EXT 7 */ -#endif - }; + struct device_node *np; + + np = of_find_node_by_type(NULL, "ipic"); + if (!np) + return; - ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + ipic_init(np, 0); /* Initialize the default interrupt mapping priorities, * in case the boot rom changed something on us. @@ -153,4 +119,7 @@ define_machine(mpc834x_itx) { .time_init = mpc83xx_time_init, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, +#ifdef CONFIG_PCI + .pcibios_fixup = mpc83xx_pcibios_fixup, +#endif }; diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_sys.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_sys.c index 3e1c16eb4a63..32df239d1c48 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -43,33 +43,6 @@ unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; #endif -#ifdef CONFIG_PCI -static int -mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) -{ - static char pci_irq_table[][4] = - /* - * PCI IDSEL/INTPIN->INTLINE - * A B C D - */ - { - {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ - {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ - {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ - {0, 0, 0, 0}, - {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ - {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ - {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ - {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ - {0, 0, 0, 0}, /* idsel 0x19 */ - {0, 0, 0, 0}, /* idsel 0x20 */ - }; - - const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; - return PCI_IRQ_TABLE_LOOKUP; -} -#endif /* CONFIG_PCI */ - /* ************************************************************************ * * Setup the architecture @@ -96,8 +69,6 @@ static void __init mpc834x_sys_setup_arch(void) for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); - ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = mpc83xx_map_irq; ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif @@ -110,25 +81,13 @@ static void __init mpc834x_sys_setup_arch(void) void __init mpc834x_sys_init_IRQ(void) { - u8 senses[8] = { - 0, /* EXT 0 */ - IRQ_SENSE_LEVEL, /* EXT 1 */ - IRQ_SENSE_LEVEL, /* EXT 2 */ - 0, /* EXT 3 */ -#ifdef CONFIG_PCI - IRQ_SENSE_LEVEL, /* EXT 4 */ - IRQ_SENSE_LEVEL, /* EXT 5 */ - IRQ_SENSE_LEVEL, /* EXT 6 */ - IRQ_SENSE_LEVEL, /* EXT 7 */ -#else - 0, /* EXT 4 */ - 0, /* EXT 5 */ - 0, /* EXT 6 */ - 0, /* EXT 7 */ -#endif - }; + struct device_node *np; + + np = of_find_node_by_type(NULL, "ipic"); + if (!np) + return; - ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + ipic_init(np, 0); /* Initialize the default interrupt mapping priorities, * in case the boot rom changed something on us. @@ -178,4 +137,7 @@ define_machine(mpc834x_sys) { .time_init = mpc83xx_time_init, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, +#ifdef CONFIG_PCI + .pcibios_fixup = mpc83xx_pcibios_fixup, +#endif }; diff --git a/trunk/arch/powerpc/platforms/83xx/mpc83xx.h b/trunk/arch/powerpc/platforms/83xx/mpc83xx.h index 01cae106912b..2c82bca9bfbb 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/trunk/arch/powerpc/platforms/83xx/mpc83xx.h @@ -11,6 +11,7 @@ extern int add_bridge(struct device_node *dev); extern int mpc83xx_exclude_device(u_char bus, u_char devfn); +extern void mpc83xx_pcibios_fixup(void); extern void mpc83xx_restart(char *cmd); extern long mpc83xx_time_init(void); diff --git a/trunk/arch/powerpc/platforms/83xx/pci.c b/trunk/arch/powerpc/platforms/83xx/pci.c index 3b5e563c279f..5d84a9ccd103 100644 --- a/trunk/arch/powerpc/platforms/83xx/pci.c +++ b/trunk/arch/powerpc/platforms/83xx/pci.c @@ -45,6 +45,15 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn) return PCIBIOS_SUCCESSFUL; } +void __init mpc83xx_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + /* map all the PCI irqs */ + for_each_pci_dev(dev) + pci_read_irq_line(dev); +} + int __init add_bridge(struct device_node *dev) { int len; diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 146da3001c67..0b1b52168bb7 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -52,6 +52,7 @@ unsigned long pci_dram_offset = 0; #endif +#ifdef CONFIG_PCI static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) { @@ -60,40 +61,43 @@ static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc, generic_handle_irq(cascade_irq, regs); desc->chip->eoi(irq); } +#endif /* CONFIG_PCI */ void __init mpc86xx_hpcn_init_irq(void) { struct mpic *mpic1; - struct device_node *np, *cascade_node = NULL; + struct device_node *np; + struct resource res; +#ifdef CONFIG_PCI + struct device_node *cascade_node = NULL; int cascade_irq; - phys_addr_t openpic_paddr; +#endif + /* Determine PIC address. */ np = of_find_node_by_type(NULL, "open-pic"); if (np == NULL) return; - - /* Determine the Physical Address of the OpenPIC regs */ - openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET; + of_address_to_resource(np, 0, &res); /* Alloc mpic structure and per isu has 16 INT entries. */ - mpic1 = mpic_alloc(np, openpic_paddr, + mpic1 = mpic_alloc(np, res.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 16, NR_IRQS - 4, " MPIC "); BUG_ON(mpic1 == NULL); - mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10000); + mpic_assign_isu(mpic1, 0, res.start + 0x10000); /* 48 Internal Interrupts */ - mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10200); - mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10400); - mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10600); + mpic_assign_isu(mpic1, 1, res.start + 0x10200); + mpic_assign_isu(mpic1, 2, res.start + 0x10400); + mpic_assign_isu(mpic1, 3, res.start + 0x10600); /* 16 External interrupts * Moving them from [0 - 15] to [64 - 79] */ - mpic_assign_isu(mpic1, 4, openpic_paddr + 0x10000); + mpic_assign_isu(mpic1, 4, res.start + 0x10000); mpic_init(mpic1); diff --git a/trunk/arch/powerpc/platforms/86xx/pci.c b/trunk/arch/powerpc/platforms/86xx/pci.c index bc5139043112..a8c8f0a44055 100644 --- a/trunk/arch/powerpc/platforms/86xx/pci.c +++ b/trunk/arch/powerpc/platforms/86xx/pci.c @@ -188,7 +188,8 @@ int __init add_bridge(struct device_node *dev) printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " "Firmware bus number: %d->%d\n", - rsrc.start, hose->first_busno, hose->last_busno); + (unsigned long) rsrc.start, + hose->first_busno, hose->last_busno); DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", hose, hose->cfg_addr, hose->cfg_data); diff --git a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig index ba07a9a7c039..234a861870a8 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig @@ -80,6 +80,7 @@ config MPC7448HPC2 select DEFAULT_UIMAGE select PPC_UDBG_16550 select MPIC + select MPIC_WEIRD help Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) platform diff --git a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index ed00ed2455dd..5d393eb94935 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -215,7 +215,7 @@ static void __init mpc7448_hpc2_init_IRQ(void) mpic = mpic_alloc(tsi_pic, mpic_paddr, MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | - MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108), + MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, 0, /* num_sources used */ 0, /* num_sources used */ "Tsi108_PIC"); diff --git a/trunk/arch/powerpc/platforms/powermac/pfunc_base.c b/trunk/arch/powerpc/platforms/powermac/pfunc_base.c index 6d66359ec8c8..aacfa59595d1 100644 --- a/trunk/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/trunk/arch/powerpc/platforms/powermac/pfunc_base.c @@ -256,7 +256,7 @@ static struct pmf_handlers macio_mmio_handlers = { .write_reg32 = macio_do_write_reg32, .read_reg32 = macio_do_read_reg32, .write_reg8 = macio_do_write_reg8, - .read_reg32 = macio_do_read_reg8, + .read_reg8 = macio_do_read_reg8, .read_reg32_msrx = macio_do_read_reg32_msrx, .read_reg8_msrx = macio_do_read_reg8_msrx, .write_reg32_slm = macio_do_write_reg32_slm, diff --git a/trunk/arch/powerpc/platforms/powermac/pic.c b/trunk/arch/powerpc/platforms/powermac/pic.c index 060789e31c67..39f7ddb554ea 100644 --- a/trunk/arch/powerpc/platforms/powermac/pic.c +++ b/trunk/arch/powerpc/platforms/powermac/pic.c @@ -87,8 +87,8 @@ static void __pmac_retrigger(unsigned int irq_nr) static void pmac_mask_and_ack_irq(unsigned int virq) { unsigned int src = irq_map[virq].hwirq; - unsigned long bit = 1UL << (virq & 0x1f); - int i = virq >> 5; + unsigned long bit = 1UL << (src & 0x1f); + int i = src >> 5; unsigned long flags; spin_lock_irqsave(&pmac_pic_lock, flags); @@ -175,7 +175,7 @@ static void pmac_mask_irq(unsigned int virq) spin_lock_irqsave(&pmac_pic_lock, flags); __clear_bit(src, ppc_cached_irq_mask); - __pmac_set_irq_mask(src, 0); + __pmac_set_irq_mask(src, 1); spin_unlock_irqrestore(&pmac_pic_lock, flags); } diff --git a/trunk/arch/powerpc/sysdev/Makefile b/trunk/arch/powerpc/sysdev/Makefile index cebfae242602..e5e999ea891a 100644 --- a/trunk/arch/powerpc/sysdev/Makefile +++ b/trunk/arch/powerpc/sysdev/Makefile @@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE) += dcr.o obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o -obj-$(CONFIG_PPC_83xx) += ipic.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_PPC_TODC) += todc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o - endif +obj-$(CONFIG_PPC_83xx) += ipic.o +endif diff --git a/trunk/arch/powerpc/sysdev/ipic.c b/trunk/arch/powerpc/sysdev/ipic.c index 46801f5ec03f..70e707785d49 100644 --- a/trunk/arch/powerpc/sysdev/ipic.c +++ b/trunk/arch/powerpc/sysdev/ipic.c @@ -19,15 +19,18 @@ #include #include #include +#include +#include +#include #include #include +#include #include -#include #include "ipic.h" -static struct ipic p_ipic; static struct ipic * primary_ipic; +static DEFINE_SPINLOCK(ipic_lock); static struct ipic_info ipic_info[] = { [9] = { @@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 out_be32(base + (reg >> 2), value); } -static inline struct ipic * ipic_from_irq(unsigned int irq) +static inline struct ipic * ipic_from_irq(unsigned int virq) { return primary_ipic; } -static void ipic_enable_irq(unsigned int irq) +#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) + +static void ipic_unmask_irq(unsigned int virq) { - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); + unsigned long flags; u32 temp; + spin_lock_irqsave(&ipic_lock, flags); + temp = ipic_read(ipic->regs, ipic_info[src].mask); temp |= (1 << (31 - ipic_info[src].bit)); ipic_write(ipic->regs, ipic_info[src].mask, temp); + + spin_unlock_irqrestore(&ipic_lock, flags); } -static void ipic_disable_irq(unsigned int irq) +static void ipic_mask_irq(unsigned int virq) { - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); + unsigned long flags; u32 temp; + spin_lock_irqsave(&ipic_lock, flags); + temp = ipic_read(ipic->regs, ipic_info[src].mask); temp &= ~(1 << (31 - ipic_info[src].bit)); ipic_write(ipic->regs, ipic_info[src].mask, temp); + + spin_unlock_irqrestore(&ipic_lock, flags); } -static void ipic_disable_irq_and_ack(unsigned int irq) +static void ipic_ack_irq(unsigned int virq) { - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); + unsigned long flags; u32 temp; - ipic_disable_irq(irq); + spin_lock_irqsave(&ipic_lock, flags); temp = ipic_read(ipic->regs, ipic_info[src].pend); temp |= (1 << (31 - ipic_info[src].bit)); ipic_write(ipic->regs, ipic_info[src].pend, temp); + + spin_unlock_irqrestore(&ipic_lock, flags); } -static void ipic_end_irq(unsigned int irq) +static void ipic_mask_irq_and_ack(unsigned int virq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - ipic_enable_irq(irq); + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); + unsigned long flags; + u32 temp; + + spin_lock_irqsave(&ipic_lock, flags); + + temp = ipic_read(ipic->regs, ipic_info[src].mask); + temp &= ~(1 << (31 - ipic_info[src].bit)); + ipic_write(ipic->regs, ipic_info[src].mask, temp); + + temp = ipic_read(ipic->regs, ipic_info[src].pend); + temp |= (1 << (31 - ipic_info[src].bit)); + ipic_write(ipic->regs, ipic_info[src].pend, temp); + + spin_unlock_irqrestore(&ipic_lock, flags); } -struct hw_interrupt_type ipic = { - .typename = " IPIC ", - .enable = ipic_enable_irq, - .disable = ipic_disable_irq, - .ack = ipic_disable_irq_and_ack, - .end = ipic_end_irq, +static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) +{ + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); + struct irq_desc *desc = get_irq_desc(virq); + unsigned int vold, vnew, edibit; + + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + /* ipic supports only low assertion and high-to-low change senses + */ + if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { + printk(KERN_ERR "ipic: sense type 0x%x not supported\n", + flow_type); + return -EINVAL; + } + + desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); + desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; + if (flow_type & IRQ_TYPE_LEVEL_LOW) { + desc->status |= IRQ_LEVEL; + set_irq_handler(virq, handle_level_irq); + } else { + set_irq_handler(virq, handle_edge_irq); + } + + /* only EXT IRQ senses are programmable on ipic + * internal IRQ senses are LEVEL_LOW + */ + if (src == IPIC_IRQ_EXT0) + edibit = 15; + else + if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) + edibit = (14 - (src - IPIC_IRQ_EXT1)); + else + return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; + + vold = ipic_read(ipic->regs, IPIC_SECNR); + if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { + vnew = vold | (1 << edibit); + } else { + vnew = vold & ~(1 << edibit); + } + if (vold != vnew) + ipic_write(ipic->regs, IPIC_SECNR, vnew); + return 0; +} + +static struct irq_chip ipic_irq_chip = { + .typename = " IPIC ", + .unmask = ipic_unmask_irq, + .mask = ipic_mask_irq, + .mask_ack = ipic_mask_irq_and_ack, + .ack = ipic_ack_irq, + .set_type = ipic_set_irq_type, +}; + +static int ipic_host_match(struct irq_host *h, struct device_node *node) +{ + struct ipic *ipic = h->host_data; + + /* Exact match, unless ipic node is NULL */ + return ipic->of_node == NULL || ipic->of_node == node; +} + +static int ipic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct ipic *ipic = h->host_data; + struct irq_chip *chip; + + /* Default chip */ + chip = &ipic->hc_irq; + + set_irq_chip_data(virq, ipic); + set_irq_chip_and_handler(virq, chip, handle_level_irq); + + /* Set default irq type */ + set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; +} + +static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) + +{ + /* interrupt sense values coming from the device tree equal either + * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) + */ + *out_hwirq = intspec[0]; + if (intsize > 1) + *out_flags = intspec[1]; + else + *out_flags = IRQ_TYPE_NONE; + return 0; +} + +static struct irq_host_ops ipic_host_ops = { + .match = ipic_host_match, + .map = ipic_host_map, + .xlate = ipic_host_xlate, }; -void __init ipic_init(phys_addr_t phys_addr, - unsigned int flags, - unsigned int irq_offset, - unsigned char *senses, - unsigned int senses_count) +void __init ipic_init(struct device_node *node, + unsigned int flags) { - u32 i, temp = 0; + struct ipic *ipic; + struct resource res; + u32 temp = 0, ret; + + ipic = alloc_bootmem(sizeof(struct ipic)); + if (ipic == NULL) + return; + + memset(ipic, 0, sizeof(struct ipic)); + ipic->of_node = node ? of_node_get(node) : NULL; + + ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, + NR_IPIC_INTS, + &ipic_host_ops, 0); + if (ipic->irqhost == NULL) { + of_node_put(node); + return; + } + + ret = of_address_to_resource(node, 0, &res); + if (ret) + return; - primary_ipic = &p_ipic; - primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); + ipic->regs = ioremap(res.start, res.end - res.start + 1); - primary_ipic->irq_offset = irq_offset; + ipic->irqhost->host_data = ipic; + ipic->hc_irq = ipic_irq_chip; - ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); + /* init hw */ + ipic_write(ipic->regs, IPIC_SICNR, 0x0); /* default priority scheme is grouped. If spread mode is required * configure SICFR accordingly */ @@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr, if (flags & IPIC_SPREADMODE_MIX_B) temp |= SICFR_MPSB; - ipic_write(primary_ipic->regs, IPIC_SICNR, temp); + ipic_write(ipic->regs, IPIC_SICNR, temp); /* handle MCP route */ temp = 0; if (flags & IPIC_DISABLE_MCP_OUT) temp = SERCR_MCPR; - ipic_write(primary_ipic->regs, IPIC_SERCR, temp); + ipic_write(ipic->regs, IPIC_SERCR, temp); /* handle routing of IRQ0 to MCP */ - temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); + temp = ipic_read(ipic->regs, IPIC_SEMSR); if (flags & IPIC_IRQ0_MCP) temp |= SEMSR_SIRQ0; else temp &= ~SEMSR_SIRQ0; - ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); + ipic_write(ipic->regs, IPIC_SEMSR, temp); - for (i = 0 ; i < NR_IPIC_INTS ; i++) { - irq_desc[i+irq_offset].chip = &ipic; - irq_desc[i+irq_offset].status = IRQ_LEVEL; - } + primary_ipic = ipic; + irq_set_default_host(primary_ipic->irqhost); - temp = 0; - for (i = 0 ; i < senses_count ; i++) { - if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { - temp |= 1 << (15 - i); - if (i != 0) - irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; - else - irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; - } - } - ipic_write(primary_ipic->regs, IPIC_SECNR, temp); - - printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, - senses_count, primary_ipic->regs); + printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, + primary_ipic->regs); } -int ipic_set_priority(unsigned int irq, unsigned int priority) +int ipic_set_priority(unsigned int virq, unsigned int priority) { - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); u32 temp; if (priority > 7) @@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority) return 0; } -void ipic_set_highest_priority(unsigned int irq) +void ipic_set_highest_priority(unsigned int virq) { - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; + struct ipic *ipic = ipic_from_irq(virq); + unsigned int src = ipic_irq_to_hw(virq); u32 temp; temp = ipic_read(ipic->regs, IPIC_SICFR); @@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq) void ipic_set_default_priority(void) { - ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); - ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); - ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); - ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); - ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); - ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); - ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); - ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); - - ipic_set_priority(MPC83xx_IRQ_UART1, 0); - ipic_set_priority(MPC83xx_IRQ_UART2, 1); - ipic_set_priority(MPC83xx_IRQ_SEC2, 2); - ipic_set_priority(MPC83xx_IRQ_IIC1, 5); - ipic_set_priority(MPC83xx_IRQ_IIC2, 6); - ipic_set_priority(MPC83xx_IRQ_SPI, 7); - ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); - ipic_set_priority(MPC83xx_IRQ_PIT, 1); - ipic_set_priority(MPC83xx_IRQ_PCI1, 2); - ipic_set_priority(MPC83xx_IRQ_PCI2, 3); - ipic_set_priority(MPC83xx_IRQ_EXT0, 4); - ipic_set_priority(MPC83xx_IRQ_EXT1, 5); - ipic_set_priority(MPC83xx_IRQ_EXT2, 6); - ipic_set_priority(MPC83xx_IRQ_EXT3, 7); - ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); - ipic_set_priority(MPC83xx_IRQ_MU, 1); - ipic_set_priority(MPC83xx_IRQ_SBA, 2); - ipic_set_priority(MPC83xx_IRQ_DMA, 3); - ipic_set_priority(MPC83xx_IRQ_EXT4, 4); - ipic_set_priority(MPC83xx_IRQ_EXT5, 5); - ipic_set_priority(MPC83xx_IRQ_EXT6, 6); - ipic_set_priority(MPC83xx_IRQ_EXT7, 7); + ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT); + ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT); + ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT); + ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT); } void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) @@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask) ipic_write(primary_ipic->regs, IPIC_SERMR, mask); } -/* Return an interrupt vector or -1 if no interrupt is pending. */ -int ipic_get_irq(struct pt_regs *regs) +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int ipic_get_irq(struct pt_regs *regs) { int irq; - irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; + BUG_ON(primary_ipic == NULL); + +#define IPIC_SIVCR_VECTOR_MASK 0x7f + irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; if (irq == 0) /* 0 --> no irq is pending */ - irq = -1; + return NO_IRQ; - return irq; + return irq_linear_revmap(primary_ipic->irqhost, irq); } static struct sysdev_class ipic_sysclass = { diff --git a/trunk/arch/powerpc/sysdev/ipic.h b/trunk/arch/powerpc/sysdev/ipic.h index a60c9d18bb7f..c28e589877eb 100644 --- a/trunk/arch/powerpc/sysdev/ipic.h +++ b/trunk/arch/powerpc/sysdev/ipic.h @@ -15,7 +15,18 @@ #include -#define MPC83xx_IPIC_SIZE (0x00100) +#define NR_IPIC_INTS 128 + +/* External IRQS */ +#define IPIC_IRQ_EXT0 48 +#define IPIC_IRQ_EXT1 17 +#define IPIC_IRQ_EXT7 23 + +/* Default Priority Registers */ +#define IPIC_SIPRR_A_DEFAULT 0x05309770 +#define IPIC_SIPRR_D_DEFAULT 0x05309770 +#define IPIC_SMPRR_A_DEFAULT 0x05309770 +#define IPIC_SMPRR_B_DEFAULT 0x05309770 /* System Global Interrupt Configuration Register */ #define SICFR_IPSA 0x00010000 @@ -31,7 +42,15 @@ struct ipic { volatile u32 __iomem *regs; - unsigned int irq_offset; + + /* The remapper for this IPIC */ + struct irq_host *irqhost; + + /* The "linux" controller struct */ + struct irq_chip hc_irq; + + /* The device node of the interrupt controller */ + struct device_node *of_node; }; struct ipic_info { diff --git a/trunk/arch/powerpc/sysdev/mpic.c b/trunk/arch/powerpc/sysdev/mpic.c index 6e0281afa6c3..b604926401f5 100644 --- a/trunk/arch/powerpc/sysdev/mpic.c +++ b/trunk/arch/powerpc/sysdev/mpic.c @@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock); #endif #endif +#ifdef CONFIG_MPIC_WEIRD +static u32 mpic_infos[][MPIC_IDX_END] = { + [0] = { /* Original OpenPIC compatible MPIC */ + MPIC_GREG_BASE, + MPIC_GREG_FEATURE_0, + MPIC_GREG_GLOBAL_CONF_0, + MPIC_GREG_VENDOR_ID, + MPIC_GREG_IPI_VECTOR_PRI_0, + MPIC_GREG_IPI_STRIDE, + MPIC_GREG_SPURIOUS, + MPIC_GREG_TIMER_FREQ, + + MPIC_TIMER_BASE, + MPIC_TIMER_STRIDE, + MPIC_TIMER_CURRENT_CNT, + MPIC_TIMER_BASE_CNT, + MPIC_TIMER_VECTOR_PRI, + MPIC_TIMER_DESTINATION, + + MPIC_CPU_BASE, + MPIC_CPU_STRIDE, + MPIC_CPU_IPI_DISPATCH_0, + MPIC_CPU_IPI_DISPATCH_STRIDE, + MPIC_CPU_CURRENT_TASK_PRI, + MPIC_CPU_WHOAMI, + MPIC_CPU_INTACK, + MPIC_CPU_EOI, + + MPIC_IRQ_BASE, + MPIC_IRQ_STRIDE, + MPIC_IRQ_VECTOR_PRI, + MPIC_VECPRI_VECTOR_MASK, + MPIC_VECPRI_POLARITY_POSITIVE, + MPIC_VECPRI_POLARITY_NEGATIVE, + MPIC_VECPRI_SENSE_LEVEL, + MPIC_VECPRI_SENSE_EDGE, + MPIC_VECPRI_POLARITY_MASK, + MPIC_VECPRI_SENSE_MASK, + MPIC_IRQ_DESTINATION + }, + [1] = { /* Tsi108/109 PIC */ + TSI108_GREG_BASE, + TSI108_GREG_FEATURE_0, + TSI108_GREG_GLOBAL_CONF_0, + TSI108_GREG_VENDOR_ID, + TSI108_GREG_IPI_VECTOR_PRI_0, + TSI108_GREG_IPI_STRIDE, + TSI108_GREG_SPURIOUS, + TSI108_GREG_TIMER_FREQ, + + TSI108_TIMER_BASE, + TSI108_TIMER_STRIDE, + TSI108_TIMER_CURRENT_CNT, + TSI108_TIMER_BASE_CNT, + TSI108_TIMER_VECTOR_PRI, + TSI108_TIMER_DESTINATION, + + TSI108_CPU_BASE, + TSI108_CPU_STRIDE, + TSI108_CPU_IPI_DISPATCH_0, + TSI108_CPU_IPI_DISPATCH_STRIDE, + TSI108_CPU_CURRENT_TASK_PRI, + TSI108_CPU_WHOAMI, + TSI108_CPU_INTACK, + TSI108_CPU_EOI, + + TSI108_IRQ_BASE, + TSI108_IRQ_STRIDE, + TSI108_IRQ_VECTOR_PRI, + TSI108_VECPRI_VECTOR_MASK, + TSI108_VECPRI_POLARITY_POSITIVE, + TSI108_VECPRI_POLARITY_NEGATIVE, + TSI108_VECPRI_SENSE_LEVEL, + TSI108_VECPRI_SENSE_EDGE, + TSI108_VECPRI_POLARITY_MASK, + TSI108_VECPRI_SENSE_MASK, + TSI108_IRQ_DESTINATION + }, +}; + +#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name] + +#else /* CONFIG_MPIC_WEIRD */ + +#define MPIC_INFO(name) MPIC_##name + +#endif /* CONFIG_MPIC_WEIRD */ + /* * Register accessor functions */ @@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) { unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; - unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); + unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + + (ipi * MPIC_INFO(GREG_IPI_STRIDE)); if (mpic->flags & MPIC_BROKEN_IPI) be = !be; @@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) { - unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); + unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + + (ipi * MPIC_INFO(GREG_IPI_STRIDE)); _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); } @@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne unsigned int idx = src_no & mpic->isu_mask; return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], - reg + (idx * MPIC_IRQ_STRIDE)); + reg + (idx * MPIC_INFO(IRQ_STRIDE))); } static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, @@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, unsigned int idx = src_no & mpic->isu_mask; _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], - reg + (idx * MPIC_IRQ_STRIDE), value); + reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); } #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) @@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) { u32 r; - mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK); - r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0); + mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK); + r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0)); if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); @@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq) /* Send an EOI */ static inline void mpic_eoi(struct mpic *mpic) { - mpic_cpu_write(MPIC_CPU_EOI, 0); - (void)mpic_cpu_read(MPIC_CPU_WHOAMI); + mpic_cpu_write(MPIC_INFO(CPU_EOI), 0); + (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI)); } #ifdef CONFIG_SMP @@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq) DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); - mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, - mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & + mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), + mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & ~MPIC_VECPRI_MASK); /* make sure mask gets to controller before we return to user */ do { @@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq) printk(KERN_ERR "mpic_enable_irq timeout\n"); break; } - } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); + } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK); } static void mpic_mask_irq(unsigned int irq) @@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq) DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); - mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, - mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | + mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), + mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) | MPIC_VECPRI_MASK); /* make sure mask gets to controller before we return to user */ @@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq) printk(KERN_ERR "mpic_enable_irq timeout\n"); break; } - } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); + } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK)); } static void mpic_end_irq(unsigned int irq) @@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) cpus_and(tmp, cpumask, cpu_online_map); - mpic_irq_write(src, MPIC_IRQ_DESTINATION, + mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), mpic_physmask(cpus_addr(tmp)[0])); } -static unsigned int mpic_type_to_vecpri(unsigned int type) +static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) { /* Now convert sense value */ switch(type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_RISING: - return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE; + return MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE); case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_BOTH: - return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE; + return MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE); case IRQ_TYPE_LEVEL_HIGH: - return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE; + return MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE); case IRQ_TYPE_LEVEL_LOW: default: - return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE; + return MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE); } } @@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) vecpri = MPIC_VECPRI_POLARITY_POSITIVE | MPIC_VECPRI_SENSE_EDGE; else - vecpri = mpic_type_to_vecpri(flow_type); + vecpri = mpic_type_to_vecpri(mpic, flow_type); - vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); - vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK); + vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); + vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) | + MPIC_INFO(VECPRI_SENSE_MASK)); vnew |= vecpri; if (vold != vnew) - mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew); + mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew); return 0; } @@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->irq_count = irq_count; mpic->num_sources = 0; /* so far */ +#ifdef CONFIG_MPIC_WEIRD + mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; +#endif + /* Map the global registers */ - mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); - mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2); + mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); + mpic->tmregs = mpic->gregs + + ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); BUG_ON(mpic->gregs == NULL); /* Reset */ if (flags & MPIC_WANTS_RESET) { - mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, - mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) + mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), + mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | MPIC_GREG_GCONF_RESET); - while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) + while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) & MPIC_GREG_GCONF_RESET) mb(); } @@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, * MPICs, num sources as well. On ISU MPICs, sources are counted * as ISUs are added */ - reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0); + reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; if (isu_size == 0) @@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE + - i * MPIC_CPU_STRIDE, 0x1000); + mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + + i * MPIC_INFO(CPU_STRIDE), 0x1000); BUG_ON(mpic->cpuregs[i] == NULL); } /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE, - MPIC_IRQ_STRIDE * mpic->isu_size); + mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), + MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); BUG_ON(mpic->isus[0] == NULL); } mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); @@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, BUG_ON(isu_num >= MPIC_MAX_ISU); - mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size); + mpic->isus[isu_num] = ioremap(phys_addr, + MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); if ((isu_first + mpic->isu_size) > mpic->num_sources) mpic->num_sources = isu_first + mpic->isu_size; } @@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic) printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); /* Set current processor priority to max */ - mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); + mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); /* Initialize timers: just disable them all */ for (i = 0; i < 4; i++) { mpic_write(mpic->tmregs, - i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0); + i * MPIC_INFO(TIMER_STRIDE) + + MPIC_INFO(TIMER_DESTINATION), 0); mpic_write(mpic->tmregs, - i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI, + i * MPIC_INFO(TIMER_STRIDE) + + MPIC_INFO(TIMER_VECTOR_PRI), MPIC_VECPRI_MASK | (MPIC_VEC_TIMER_0 + i)); } @@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic) (8 << MPIC_VECPRI_PRIORITY_SHIFT); /* init hw */ - mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); - mpic_irq_write(i, MPIC_IRQ_DESTINATION, + mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); + mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << hard_smp_processor_id()); } /* Init spurrious vector */ - mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS); + mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); - /* Disable 8259 passthrough */ - mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, - mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) - | MPIC_GREG_GCONF_8259_PTHROU_DIS); + /* Disable 8259 passthrough, if supported */ + if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) + mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), + mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) + | MPIC_GREG_GCONF_8259_PTHROU_DIS); /* Set current processor priority to 0 */ - mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); + mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); } void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) @@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) mpic_ipi_write(src - MPIC_VEC_IPI_0, reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } else { - reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) + reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & ~MPIC_VECPRI_PRIORITY_MASK; - mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, + mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } spin_unlock_irqrestore(&mpic_lock, flags); @@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq) if (is_ipi) reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); else - reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); + reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); spin_unlock_irqrestore(&mpic_lock, flags); return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; } @@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void) */ if (distribute_irqs) { for (i = 0; i < mpic->num_sources ; i++) - mpic_irq_write(i, MPIC_IRQ_DESTINATION, - mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk); + mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), + mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk); } /* Set current processor priority to 0 */ - mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); + mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); spin_unlock_irqrestore(&mpic_lock, flags); #endif /* CONFIG_SMP */ @@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void) { struct mpic *mpic = mpic_primary; - return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI); + return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI)); } void mpic_cpu_set_priority(int prio) @@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio) struct mpic *mpic = mpic_primary; prio &= MPIC_CPU_TASKPRI_MASK; - mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio); + mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio); } /* @@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary) /* let the mpic know we don't want intrs. */ for (i = 0; i < mpic->num_sources ; i++) - mpic_irq_write(i, MPIC_IRQ_DESTINATION, - mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk); + mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), + mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk); /* Set current processor priority to max */ - mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); + mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); spin_unlock_irqrestore(&mpic_lock, flags); } @@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); #endif - mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10, + mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) + + ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); } @@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) { u32 src; - src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; + src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK); #ifdef DEBUG_LOW DBG("%s: get_one_irq(): %d\n", mpic->name, src); #endif diff --git a/trunk/arch/ppc/kernel/smp-tbsync.c b/trunk/arch/ppc/kernel/smp-tbsync.c index 1576758debaf..d0cf3f86931d 100644 --- a/trunk/arch/ppc/kernel/smp-tbsync.c +++ b/trunk/arch/ppc/kernel/smp-tbsync.c @@ -47,8 +47,9 @@ void __devinit smp_generic_take_timebase( void ) { int cmd, tbl, tbu; + unsigned long flags; - local_irq_disable(); + local_irq_save(flags); while( !running ) ; rmb(); @@ -64,7 +65,7 @@ smp_generic_take_timebase( void ) tbu = tbsync->tbu; tbsync->ack = 0; if( cmd == kExit ) - return; + break; if( cmd == kSetAndTest ) { while( tbsync->handshake ) @@ -77,7 +78,7 @@ smp_generic_take_timebase( void ) } enter_contest( tbsync->mark, -1 ); } - local_irq_enable(); + local_irq_restore(flags); } static int __devinit diff --git a/trunk/arch/ppc/syslib/Makefile b/trunk/arch/ppc/syslib/Makefile index 2497bbc07e76..dca23f2ef851 100644 --- a/trunk/arch/ppc/syslib/Makefile +++ b/trunk/arch/ppc/syslib/Makefile @@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o endif obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \ - mpc83xx_sys.o mpc83xx_devices.o + mpc83xx_sys.o mpc83xx_devices.o ipic.o ifeq ($(CONFIG_83xx),y) obj-$(CONFIG_PCI) += pci_auto.o endif diff --git a/trunk/arch/ppc/syslib/ipic.c b/trunk/arch/ppc/syslib/ipic.c new file mode 100644 index 000000000000..46801f5ec03f --- /dev/null +++ b/trunk/arch/ppc/syslib/ipic.c @@ -0,0 +1,646 @@ +/* + * include/asm-ppc/ipic.c + * + * IPIC routines implementations. + * + * Copyright 2005 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipic.h" + +static struct ipic p_ipic; +static struct ipic * primary_ipic; + +static struct ipic_info ipic_info[] = { + [9] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 24, + .prio_mask = 0, + }, + [10] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 25, + .prio_mask = 1, + }, + [11] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 26, + .prio_mask = 2, + }, + [14] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 29, + .prio_mask = 5, + }, + [15] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 30, + .prio_mask = 6, + }, + [16] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_D, + .force = IPIC_SIFCR_H, + .bit = 31, + .prio_mask = 7, + }, + [17] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_A, + .force = IPIC_SEFCR, + .bit = 1, + .prio_mask = 5, + }, + [18] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_A, + .force = IPIC_SEFCR, + .bit = 2, + .prio_mask = 6, + }, + [19] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_A, + .force = IPIC_SEFCR, + .bit = 3, + .prio_mask = 7, + }, + [20] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_B, + .force = IPIC_SEFCR, + .bit = 4, + .prio_mask = 4, + }, + [21] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_B, + .force = IPIC_SEFCR, + .bit = 5, + .prio_mask = 5, + }, + [22] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_B, + .force = IPIC_SEFCR, + .bit = 6, + .prio_mask = 6, + }, + [23] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_B, + .force = IPIC_SEFCR, + .bit = 7, + .prio_mask = 7, + }, + [32] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 0, + .prio_mask = 0, + }, + [33] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 1, + .prio_mask = 1, + }, + [34] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 2, + .prio_mask = 2, + }, + [35] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 3, + .prio_mask = 3, + }, + [36] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 4, + .prio_mask = 4, + }, + [37] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 5, + .prio_mask = 5, + }, + [38] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 6, + .prio_mask = 6, + }, + [39] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_H, + .prio = IPIC_SIPRR_A, + .force = IPIC_SIFCR_H, + .bit = 7, + .prio_mask = 7, + }, + [48] = { + .pend = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .prio = IPIC_SMPRR_A, + .force = IPIC_SEFCR, + .bit = 0, + .prio_mask = 4, + }, + [64] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_A, + .force = IPIC_SIFCR_L, + .bit = 0, + .prio_mask = 0, + }, + [65] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_A, + .force = IPIC_SIFCR_L, + .bit = 1, + .prio_mask = 1, + }, + [66] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_A, + .force = IPIC_SIFCR_L, + .bit = 2, + .prio_mask = 2, + }, + [67] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_A, + .force = IPIC_SIFCR_L, + .bit = 3, + .prio_mask = 3, + }, + [68] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_B, + .force = IPIC_SIFCR_L, + .bit = 4, + .prio_mask = 0, + }, + [69] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_B, + .force = IPIC_SIFCR_L, + .bit = 5, + .prio_mask = 1, + }, + [70] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_B, + .force = IPIC_SIFCR_L, + .bit = 6, + .prio_mask = 2, + }, + [71] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = IPIC_SMPRR_B, + .force = IPIC_SIFCR_L, + .bit = 7, + .prio_mask = 3, + }, + [72] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 8, + }, + [73] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 9, + }, + [74] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 10, + }, + [75] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 11, + }, + [76] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 12, + }, + [77] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 13, + }, + [78] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 14, + }, + [79] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 15, + }, + [80] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 16, + }, + [84] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 20, + }, + [85] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 21, + }, + [90] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 26, + }, + [91] = { + .pend = IPIC_SIPNR_H, + .mask = IPIC_SIMSR_L, + .prio = 0, + .force = IPIC_SIFCR_L, + .bit = 27, + }, +}; + +static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) +{ + return in_be32(base + (reg >> 2)); +} + +static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) +{ + out_be32(base + (reg >> 2), value); +} + +static inline struct ipic * ipic_from_irq(unsigned int irq) +{ + return primary_ipic; +} + +static void ipic_enable_irq(unsigned int irq) +{ + struct ipic *ipic = ipic_from_irq(irq); + unsigned int src = irq - ipic->irq_offset; + u32 temp; + + temp = ipic_read(ipic->regs, ipic_info[src].mask); + temp |= (1 << (31 - ipic_info[src].bit)); + ipic_write(ipic->regs, ipic_info[src].mask, temp); +} + +static void ipic_disable_irq(unsigned int irq) +{ + struct ipic *ipic = ipic_from_irq(irq); + unsigned int src = irq - ipic->irq_offset; + u32 temp; + + temp = ipic_read(ipic->regs, ipic_info[src].mask); + temp &= ~(1 << (31 - ipic_info[src].bit)); + ipic_write(ipic->regs, ipic_info[src].mask, temp); +} + +static void ipic_disable_irq_and_ack(unsigned int irq) +{ + struct ipic *ipic = ipic_from_irq(irq); + unsigned int src = irq - ipic->irq_offset; + u32 temp; + + ipic_disable_irq(irq); + + temp = ipic_read(ipic->regs, ipic_info[src].pend); + temp |= (1 << (31 - ipic_info[src].bit)); + ipic_write(ipic->regs, ipic_info[src].pend, temp); +} + +static void ipic_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + ipic_enable_irq(irq); +} + +struct hw_interrupt_type ipic = { + .typename = " IPIC ", + .enable = ipic_enable_irq, + .disable = ipic_disable_irq, + .ack = ipic_disable_irq_and_ack, + .end = ipic_end_irq, +}; + +void __init ipic_init(phys_addr_t phys_addr, + unsigned int flags, + unsigned int irq_offset, + unsigned char *senses, + unsigned int senses_count) +{ + u32 i, temp = 0; + + primary_ipic = &p_ipic; + primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); + + primary_ipic->irq_offset = irq_offset; + + ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); + + /* default priority scheme is grouped. If spread mode is required + * configure SICFR accordingly */ + if (flags & IPIC_SPREADMODE_GRP_A) + temp |= SICFR_IPSA; + if (flags & IPIC_SPREADMODE_GRP_D) + temp |= SICFR_IPSD; + if (flags & IPIC_SPREADMODE_MIX_A) + temp |= SICFR_MPSA; + if (flags & IPIC_SPREADMODE_MIX_B) + temp |= SICFR_MPSB; + + ipic_write(primary_ipic->regs, IPIC_SICNR, temp); + + /* handle MCP route */ + temp = 0; + if (flags & IPIC_DISABLE_MCP_OUT) + temp = SERCR_MCPR; + ipic_write(primary_ipic->regs, IPIC_SERCR, temp); + + /* handle routing of IRQ0 to MCP */ + temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); + + if (flags & IPIC_IRQ0_MCP) + temp |= SEMSR_SIRQ0; + else + temp &= ~SEMSR_SIRQ0; + + ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); + + for (i = 0 ; i < NR_IPIC_INTS ; i++) { + irq_desc[i+irq_offset].chip = &ipic; + irq_desc[i+irq_offset].status = IRQ_LEVEL; + } + + temp = 0; + for (i = 0 ; i < senses_count ; i++) { + if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { + temp |= 1 << (15 - i); + if (i != 0) + irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; + else + irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; + } + } + ipic_write(primary_ipic->regs, IPIC_SECNR, temp); + + printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, + senses_count, primary_ipic->regs); +} + +int ipic_set_priority(unsigned int irq, unsigned int priority) +{ + struct ipic *ipic = ipic_from_irq(irq); + unsigned int src = irq - ipic->irq_offset; + u32 temp; + + if (priority > 7) + return -EINVAL; + if (src > 127) + return -EINVAL; + if (ipic_info[src].prio == 0) + return -EINVAL; + + temp = ipic_read(ipic->regs, ipic_info[src].prio); + + if (priority < 4) { + temp &= ~(0x7 << (20 + (3 - priority) * 3)); + temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); + } else { + temp &= ~(0x7 << (4 + (7 - priority) * 3)); + temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); + } + + ipic_write(ipic->regs, ipic_info[src].prio, temp); + + return 0; +} + +void ipic_set_highest_priority(unsigned int irq) +{ + struct ipic *ipic = ipic_from_irq(irq); + unsigned int src = irq - ipic->irq_offset; + u32 temp; + + temp = ipic_read(ipic->regs, IPIC_SICFR); + + /* clear and set HPI */ + temp &= 0x7f000000; + temp |= (src & 0x7f) << 24; + + ipic_write(ipic->regs, IPIC_SICFR, temp); +} + +void ipic_set_default_priority(void) +{ + ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); + ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); + ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); + ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); + ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); + ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); + ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); + ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); + + ipic_set_priority(MPC83xx_IRQ_UART1, 0); + ipic_set_priority(MPC83xx_IRQ_UART2, 1); + ipic_set_priority(MPC83xx_IRQ_SEC2, 2); + ipic_set_priority(MPC83xx_IRQ_IIC1, 5); + ipic_set_priority(MPC83xx_IRQ_IIC2, 6); + ipic_set_priority(MPC83xx_IRQ_SPI, 7); + ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); + ipic_set_priority(MPC83xx_IRQ_PIT, 1); + ipic_set_priority(MPC83xx_IRQ_PCI1, 2); + ipic_set_priority(MPC83xx_IRQ_PCI2, 3); + ipic_set_priority(MPC83xx_IRQ_EXT0, 4); + ipic_set_priority(MPC83xx_IRQ_EXT1, 5); + ipic_set_priority(MPC83xx_IRQ_EXT2, 6); + ipic_set_priority(MPC83xx_IRQ_EXT3, 7); + ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); + ipic_set_priority(MPC83xx_IRQ_MU, 1); + ipic_set_priority(MPC83xx_IRQ_SBA, 2); + ipic_set_priority(MPC83xx_IRQ_DMA, 3); + ipic_set_priority(MPC83xx_IRQ_EXT4, 4); + ipic_set_priority(MPC83xx_IRQ_EXT5, 5); + ipic_set_priority(MPC83xx_IRQ_EXT6, 6); + ipic_set_priority(MPC83xx_IRQ_EXT7, 7); +} + +void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) +{ + struct ipic *ipic = primary_ipic; + u32 temp; + + temp = ipic_read(ipic->regs, IPIC_SERMR); + temp |= (1 << (31 - mcp_irq)); + ipic_write(ipic->regs, IPIC_SERMR, temp); +} + +void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) +{ + struct ipic *ipic = primary_ipic; + u32 temp; + + temp = ipic_read(ipic->regs, IPIC_SERMR); + temp &= (1 << (31 - mcp_irq)); + ipic_write(ipic->regs, IPIC_SERMR, temp); +} + +u32 ipic_get_mcp_status(void) +{ + return ipic_read(primary_ipic->regs, IPIC_SERMR); +} + +void ipic_clear_mcp_status(u32 mask) +{ + ipic_write(primary_ipic->regs, IPIC_SERMR, mask); +} + +/* Return an interrupt vector or -1 if no interrupt is pending. */ +int ipic_get_irq(struct pt_regs *regs) +{ + int irq; + + irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; + + if (irq == 0) /* 0 --> no irq is pending */ + irq = -1; + + return irq; +} + +static struct sysdev_class ipic_sysclass = { + set_kset_name("ipic"), +}; + +static struct sys_device device_ipic = { + .id = 0, + .cls = &ipic_sysclass, +}; + +static int __init init_ipic_sysfs(void) +{ + int rc; + + if (!primary_ipic->regs) + return -ENODEV; + printk(KERN_DEBUG "Registering ipic with sysfs...\n"); + + rc = sysdev_class_register(&ipic_sysclass); + if (rc) { + printk(KERN_ERR "Failed registering ipic sys class\n"); + return -ENODEV; + } + rc = sysdev_register(&device_ipic); + if (rc) { + printk(KERN_ERR "Failed registering ipic sys device\n"); + return -ENODEV; + } + return 0; +} + +subsys_initcall(init_ipic_sysfs); diff --git a/trunk/arch/ppc/syslib/ipic.h b/trunk/arch/ppc/syslib/ipic.h new file mode 100644 index 000000000000..a60c9d18bb7f --- /dev/null +++ b/trunk/arch/ppc/syslib/ipic.h @@ -0,0 +1,47 @@ +/* + * IPIC private definitions and structure. + * + * Maintainer: Kumar Gala + * + * Copyright 2005 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef __IPIC_H__ +#define __IPIC_H__ + +#include + +#define MPC83xx_IPIC_SIZE (0x00100) + +/* System Global Interrupt Configuration Register */ +#define SICFR_IPSA 0x00010000 +#define SICFR_IPSD 0x00080000 +#define SICFR_MPSA 0x00200000 +#define SICFR_MPSB 0x00400000 + +/* System External Interrupt Mask Register */ +#define SEMSR_SIRQ0 0x00008000 + +/* System Error Control Register */ +#define SERCR_MCPR 0x00000001 + +struct ipic { + volatile u32 __iomem *regs; + unsigned int irq_offset; +}; + +struct ipic_info { + u8 pend; /* pending register offset from base */ + u8 mask; /* mask register offset from base */ + u8 prio; /* priority register offset from base */ + u8 force; /* force register offset from base */ + u8 bit; /* register bit position (as per doc) + bit mask = 1 << (31 - bit) */ + u8 prio_mask; /* priority mask value */ +}; + +#endif /* __IPIC_H__ */ diff --git a/trunk/arch/s390/lib/uaccess.S b/trunk/arch/s390/lib/uaccess.S index 5d59e2625048..837275284d9f 100644 --- a/trunk/arch/s390/lib/uaccess.S +++ b/trunk/arch/s390/lib/uaccess.S @@ -88,30 +88,31 @@ __copy_to_user_asm: .globl __copy_in_user_asm # %r2 = from, %r3 = n, %r4 = to __copy_in_user_asm: + ahi %r3,-1 + jo 6f sacf 256 - bras 1,1f - mvc 0(1,%r4),0(%r2) -0: mvc 0(256,%r4),0(%r2) - la %r2,256(%r2) - la %r4,256(%r4) -1: ahi %r3,-256 - jnm 0b -2: ex %r3,0(%r1) - sacf 0 - slr %r2,%r2 - br 14 -3: mvc 0(1,%r4),0(%r2) + bras %r1,4f +0: ahi %r3,257 +1: mvc 0(1,%r4),0(%r2) la %r2,1(%r2) la %r4,1(%r4) ahi %r3,-1 + jnz 1b +2: lr %r2,%r3 + br %r14 +3: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +4: ahi %r3,-256 jnm 3b -4: lr %r2,%r3 +5: ex %r3,4(%r1) sacf 0 +6: slr %r2,%r2 br %r14 .section __ex_table,"a" - .long 0b,3b - .long 2b,3b - .long 3b,4b + .long 1b,2b + .long 3b,0b + .long 5b,0b .previous .align 4 diff --git a/trunk/arch/s390/lib/uaccess64.S b/trunk/arch/s390/lib/uaccess64.S index 19b41a33c230..1f755be22f92 100644 --- a/trunk/arch/s390/lib/uaccess64.S +++ b/trunk/arch/s390/lib/uaccess64.S @@ -88,30 +88,31 @@ __copy_to_user_asm: .globl __copy_in_user_asm # %r2 = from, %r3 = n, %r4 = to __copy_in_user_asm: + aghi %r3,-1 + jo 6f sacf 256 - bras 1,1f - mvc 0(1,%r4),0(%r2) -0: mvc 0(256,%r4),0(%r2) - la %r2,256(%r2) - la %r4,256(%r4) -1: aghi %r3,-256 - jnm 0b -2: ex %r3,0(%r1) - sacf 0 - slgr %r2,%r2 - br 14 -3: mvc 0(1,%r4),0(%r2) + bras %r1,4f +0: aghi %r3,257 +1: mvc 0(1,%r4),0(%r2) la %r2,1(%r2) la %r4,1(%r4) aghi %r3,-1 + jnz 1b +2: lgr %r2,%r3 + br %r14 +3: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +4: aghi %r3,-256 jnm 3b -4: lgr %r2,%r3 +5: ex %r3,4(%r1) sacf 0 - br %r14 +6: slgr %r2,%r2 + br 14 .section __ex_table,"a" - .quad 0b,3b - .quad 2b,3b - .quad 3b,4b + .quad 1b,2b + .quad 3b,0b + .quad 5b,0b .previous .align 4 diff --git a/trunk/arch/sparc64/mm/generic.c b/trunk/arch/sparc64/mm/generic.c index 8cb06205d265..af9d81db0b38 100644 --- a/trunk/arch/sparc64/mm/generic.c +++ b/trunk/arch/sparc64/mm/generic.c @@ -69,6 +69,8 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, } else offset += PAGE_SIZE; + if (pte_write(entry)) + entry = pte_mkdirty(entry); do { BUG_ON(!pte_none(*pte)); set_pte_at(mm, address, pte, entry); diff --git a/trunk/arch/x86_64/defconfig b/trunk/arch/x86_64/defconfig index 840d5d93d5cc..5fb970715941 100644 --- a/trunk/arch/x86_64/defconfig +++ b/trunk/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc2 -# Tue Jul 18 17:13:20 2006 +# Linux kernel version: 2.6.18-rc4 +# Thu Aug 24 21:05:55 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -201,7 +201,7 @@ CONFIG_ACPI_THERMAL=y CONFIG_ACPI_NUMA=y # CONFIG_ACPI_ASUS is not set # CONFIG_ACPI_IBM is not set -CONFIG_ACPI_TOSHIBA=y +# CONFIG_ACPI_TOSHIBA is not set CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_EC=y @@ -216,7 +216,7 @@ CONFIG_ACPI_CONTAINER=y # CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y -# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_DEBUG=y CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y @@ -495,8 +495,9 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y # CONFIG_CHR_DEV_SCH is not set # @@ -512,7 +513,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=y # # SCSI low-level drivers @@ -538,7 +539,7 @@ CONFIG_MEGARAID_MAILBOX=y CONFIG_MEGARAID_SAS=y CONFIG_SCSI_SATA=y CONFIG_SCSI_SATA_AHCI=y -# CONFIG_SCSI_SATA_SVW is not set +CONFIG_SCSI_SATA_SVW=y CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set CONFIG_SCSI_SATA_NV=y @@ -589,7 +590,7 @@ CONFIG_BLK_DEV_DM=y CONFIG_FUSION=y CONFIG_FUSION_SPI=y # CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set +CONFIG_FUSION_SAS=y CONFIG_FUSION_MAX_SGE=128 # CONFIG_FUSION_CTL is not set @@ -675,7 +676,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set +CONFIG_B44=y CONFIG_FORCEDETH=y # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set @@ -712,7 +713,7 @@ CONFIG_E1000=y # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y -# CONFIG_BNX2 is not set +CONFIG_BNX2=y # # Ethernet (10000 Mbit) @@ -842,44 +843,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Watchdog Cards # -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -CONFIG_SOFT_WATCHDOG=y -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_ALIM1535_WDT is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_IBMASR is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_I6300ESB_WDT is not set -# CONFIG_I8XX_TCO is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_SBC8360_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_W83627HF_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_W83977F_WDT is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_SBC_EPX_C3_WATCHDOG is not set - -# -# PCI-based Watchdog Cards -# -# CONFIG_PCIPCWATCHDOG is not set -# CONFIG_WDTPCI is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set +# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_INTEL=y CONFIG_HW_RANDOM_AMD=y @@ -1056,6 +1020,7 @@ CONFIG_VGACON_SOFT_SCROLLBACK=y CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256 CONFIG_VIDEO_SELECT=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -1301,7 +1266,7 @@ CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -1494,4 +1459,5 @@ CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y CONFIG_PLIST=y diff --git a/trunk/arch/x86_64/ia32/ia32_binfmt.c b/trunk/arch/x86_64/ia32/ia32_binfmt.c index a9dc0f3b5b51..2fd5a67fd435 100644 --- a/trunk/arch/x86_64/ia32/ia32_binfmt.c +++ b/trunk/arch/x86_64/ia32/ia32_binfmt.c @@ -73,39 +73,44 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; * Dumping its extra ELF program headers includes all the other information * a debugger needs to easily find how the vsyscall DSO was being used. */ -#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum) +#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \ + (VSYSCALL32_EHDR->e_phnum) : 0) #define ELF_CORE_WRITE_EXTRA_PHDRS \ do { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff); \ - int i; \ - Elf32_Off ofs = 0; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - struct elf32_phdr phdr = vsyscall_phdrs[i]; \ - if (phdr.p_type == PT_LOAD) { \ - BUG_ON(ofs != 0); \ - ofs = phdr.p_offset = offset; \ - phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ - phdr.p_filesz = phdr.p_memsz; \ - offset += phdr.p_filesz; \ + if (find_vma(current->mm, VSYSCALL32_BASE)) { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff);\ + int i; \ + Elf32_Off ofs = 0; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + struct elf32_phdr phdr = vsyscall_phdrs[i]; \ + if (phdr.p_type == PT_LOAD) { \ + BUG_ON(ofs != 0); \ + ofs = phdr.p_offset = offset; \ + phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ + phdr.p_filesz = phdr.p_memsz; \ + offset += phdr.p_filesz; \ + } \ + else \ + phdr.p_offset += ofs; \ + phdr.p_paddr = 0; /* match other core phdrs */ \ + DUMP_WRITE(&phdr, sizeof(phdr)); \ } \ - else \ - phdr.p_offset += ofs; \ - phdr.p_paddr = 0; /* match other core phdrs */ \ - DUMP_WRITE(&phdr, sizeof(phdr)); \ } \ } while (0) #define ELF_CORE_WRITE_EXTRA_DATA \ do { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff); \ - int i; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - if (vsyscall_phdrs[i].p_type == PT_LOAD) \ - DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \ - PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ + if (find_vma(current->mm, VSYSCALL32_BASE)) { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + if (vsyscall_phdrs[i].p_type == PT_LOAD) \ + DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\ + PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ + } \ } \ } while (0) diff --git a/trunk/arch/x86_64/kernel/e820.c b/trunk/arch/x86_64/kernel/e820.c index e56c2adf57a4..764bf23c7103 100644 --- a/trunk/arch/x86_64/kernel/e820.c +++ b/trunk/arch/x86_64/kernel/e820.c @@ -71,7 +71,11 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) #endif /* kernel code + 640k memory hole (later should not be needed, but be paranoid for now) */ - if (last >= 640*1024 && addr < __pa_symbol(&_end)) { + if (last >= 640*1024 && addr < 1024*1024) { + *addrp = 1024*1024; + return 1; + } + if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { *addrp = __pa_symbol(&_end); return 1; } @@ -104,35 +108,6 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type) return 0; } -/* - * This function checks if the entire range is mapped with type. - * - * Note: this function only works correct if the e820 table is sorted and - * not-overlapping, which is the case - */ -int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type) -{ - int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - if (type && ei->type != type) - continue; - /* is the region (part) in overlap with the current region ?*/ - if (ei->addr >= end || ei->addr + ei->size <= start) - continue; - - /* if the region is at the beginning of we move - * start to the end of the region since it's ok until there - */ - if (ei->addr <= start) - start = ei->addr + ei->size; - /* if start is now at or beyond end, we're done, full coverage */ - if (start >= end) - return 1; /* we're done */ - } - return 0; -} - /* * Find a free area in a specific range. */ diff --git a/trunk/arch/x86_64/kernel/entry.S b/trunk/arch/x86_64/kernel/entry.S index 6f810424df44..aa8d8939abc1 100644 --- a/trunk/arch/x86_64/kernel/entry.S +++ b/trunk/arch/x86_64/kernel/entry.S @@ -973,6 +973,8 @@ ENTRY(kernel_thread) ENDPROC(kernel_thread) child_rip: + pushq $0 # fake return address + CFI_STARTPROC /* * Here we are in the child and the registers are set as they were * at kernel_thread() invocation in the parent. @@ -983,6 +985,7 @@ child_rip: # exit xorl %edi, %edi call do_exit + CFI_ENDPROC ENDPROC(child_rip) /* diff --git a/trunk/arch/x86_64/kernel/head.S b/trunk/arch/x86_64/kernel/head.S index 6df05e6034fa..c9739ca81d06 100644 --- a/trunk/arch/x86_64/kernel/head.S +++ b/trunk/arch/x86_64/kernel/head.S @@ -191,6 +191,7 @@ startup_64: * jump */ movq initial_code(%rip),%rax + pushq $0 # fake return address jmp *%rax /* SMP bootup changes these two */ diff --git a/trunk/arch/x86_64/kernel/init_task.c b/trunk/arch/x86_64/kernel/init_task.c index ce31d904d601..3dc5854ba21e 100644 --- a/trunk/arch/x86_64/kernel/init_task.c +++ b/trunk/arch/x86_64/kernel/init_task.c @@ -46,4 +46,9 @@ EXPORT_SYMBOL(init_task); */ DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; +/* Copies of the original ist values from the tss are only accessed during + * debugging, no special alignment required. + */ +DEFINE_PER_CPU(struct orig_ist, orig_ist); + #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c index 8a099ff1f8bc..34afad704824 100644 --- a/trunk/arch/x86_64/kernel/setup.c +++ b/trunk/arch/x86_64/kernel/setup.c @@ -521,8 +521,6 @@ static void discover_ebda(void) void __init setup_arch(char **cmdline_p) { - unsigned long kernel_end; - ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); screen_info = SCREEN_INFO; edid_info = EDID_INFO; @@ -596,8 +594,8 @@ void __init setup_arch(char **cmdline_p) (table_end - table_start) << PAGE_SHIFT); /* reserve kernel */ - kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE); - reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY); + reserve_bootmem_generic(__pa_symbol(&_text), + __pa_symbol(&_end) - __pa_symbol(&_text)); /* * reserve physical page 0 - it's a special BIOS page on many boxes, diff --git a/trunk/arch/x86_64/kernel/setup64.c b/trunk/arch/x86_64/kernel/setup64.c index 6fe58a634b5f..417de564456e 100644 --- a/trunk/arch/x86_64/kernel/setup64.c +++ b/trunk/arch/x86_64/kernel/setup64.c @@ -189,6 +189,7 @@ void __cpuinit cpu_init (void) { int cpu = stack_smp_processor_id(); struct tss_struct *t = &per_cpu(init_tss, cpu); + struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); unsigned long v; char *estacks = NULL; struct task_struct *me; @@ -256,7 +257,7 @@ void __cpuinit cpu_init (void) estacks += EXCEPTION_STKSZ; break; } - t->ist[v] = (unsigned long)estacks; + orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks; } t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap); diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index 14052f089814..b1249774d1e8 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -107,7 +107,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) } static int kstack_depth_to_print = 12; +#ifdef CONFIG_STACK_UNWIND static int call_trace = 1; +#else +#define call_trace (-1) +#endif #ifdef CONFIG_KALLSYMS # include @@ -174,7 +178,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, break; #endif default: - end = per_cpu(init_tss, cpu).ist[k]; + end = per_cpu(orig_ist, cpu).ist[k]; break; } /* @@ -274,21 +278,21 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s if (unwind_init_blocked(&info, tsk) == 0) unw_ret = show_trace_unwind(&info, NULL); } - if (unw_ret > 0 && !arch_unw_user_mode(&info)) { -#ifdef CONFIG_STACK_UNWIND - unsigned long rip = info.regs.rip; - print_symbol("DWARF2 unwinder stuck at %s\n", rip); - if (call_trace == 1) { - printk("Leftover inexact backtrace:\n"); - stack = (unsigned long *)info.regs.rsp; - } else if (call_trace > 1) + if (unw_ret > 0) { + if (call_trace == 1 && !arch_unw_user_mode(&info)) { + print_symbol("DWARF2 unwinder stuck at %s\n", + UNW_PC(&info)); + if ((long)UNW_SP(&info) < 0) { + printk("Leftover inexact backtrace:\n"); + stack = (unsigned long *)UNW_SP(&info); + } else + printk("Full inexact backtrace again:\n"); + } else if (call_trace >= 1) return; else printk("Full inexact backtrace again:\n"); -#else + } else printk("Inexact backtrace:\n"); -#endif - } } /* @@ -1120,6 +1124,7 @@ static int __init kstack_setup(char *s) } __setup("kstack=", kstack_setup); +#ifdef CONFIG_STACK_UNWIND static int __init call_trace_setup(char *s) { if (strcmp(s, "old") == 0) @@ -1133,3 +1138,4 @@ static int __init call_trace_setup(char *s) return 1; } __setup("call_trace=", call_trace_setup); +#endif diff --git a/trunk/arch/x86_64/pci/mmconfig.c b/trunk/arch/x86_64/pci/mmconfig.c index 3c55c76c6fd5..2d48a7941d48 100644 --- a/trunk/arch/x86_64/pci/mmconfig.c +++ b/trunk/arch/x86_64/pci/mmconfig.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "pci.h" @@ -164,11 +165,33 @@ static __init void unreachable_devices(void) } } +static int disable_mcfg(struct dmi_system_id *d) +{ + printk("PCI: %s detected. Disabling MCFG.\n", d->ident); + pci_probe &= ~PCI_PROBE_MMCONF; + return 0; +} + +static struct dmi_system_id __initdata dmi_bad_mcfg[] = { + /* Has broken MCFG table that makes the system hang when used */ + { + .callback = disable_mcfg, + .ident = "Intel D3C5105 SDV", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Intel"), + DMI_MATCH(DMI_BOARD_NAME, "D26928"), + }, + }, + {} +}; + void __init pci_mmcfg_init(void) { int i; - if ((pci_probe & PCI_PROBE_MMCONF) == 0) + dmi_check_system(dmi_bad_mcfg); + + if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0) return; acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); @@ -177,15 +200,6 @@ void __init pci_mmcfg_init(void) (pci_mmcfg_config[0].base_address == 0)) return; - if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, - E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", - pci_mmcfg_config[0].base_address); - printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); - return; - } - /* RED-PEN i386 doesn't do _nocache right now */ pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); if (pci_mmcfg_virt == NULL) { diff --git a/trunk/arch/xtensa/kernel/ptrace.c b/trunk/arch/xtensa/kernel/ptrace.c index 5064d9383963..9aea23cc0dc5 100644 --- a/trunk/arch/xtensa/kernel/ptrace.c +++ b/trunk/arch/xtensa/kernel/ptrace.c @@ -212,7 +212,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) */ case PTRACE_KILL: ret = 0; - if (child->state == EXIT_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; child->ptrace &= ~PT_SINGLESTEP; diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index cbda988692e7..13027d56b7f6 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -145,340 +145,6 @@ config SATA_INTEL_COMBINED depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX) default y -config PATA_ALI - tristate "ALi PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the ALi ATA interfaces - found on the many ALi chipsets. - - If unsure, say N. - -config PATA_AMD - tristate "AMD/NVidia PATA support (Experimental)" - depends on PCI - help - This option enables support for the AMD and NVidia PATA - interfaces found on the chipsets for Athlon/Athlon64. - - If unsure, say N. - -config PATA_ARTOP - tristate "ARTOP 6210/6260 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for ARTOP PATA controllers. - - If unsure, say N. - -config PATA_ATIIXP - tristate "ATI PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the ATI ATA interfaces - found on the many ATI chipsets. - - If unsure, say N. - -config PATA_CMD64X - tristate "CMD64x PATA support (Very Experimental)" - depends on PCI&& EXPERIMENTAL - help - This option enables support for the CMD64x series chips - except for the CMD640. - - If unsure, say N. - -config PATA_CS5520 - tristate "CS5510/5520 PATA support" - depends on PCI - help - This option enables support for the Cyrix 5510/5520 - companion chip used with the MediaGX/Geode processor family. - - If unsure, say N. - -config PATA_CS5530 - tristate "CS5530 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the Cyrix/NatSemi/AMD CS5530 - companion chip used with the MediaGX/Geode processor family. - - If unsure, say N. - -config PATA_CS5535 - tristate "CS5535 PATA support (Experimental)" - depends on PCI && X86 && !X86_64 && EXPERIMENTAL - help - This option enables support for the NatSemi/AMD CS5535 - companion chip used with the Geode processor family. - - If unsure, say N. - -config PATA_CYPRESS - tristate "Cypress CY82C693 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the Cypress/Contaq CY82C693 - chipset found in some Alpha systems - - If unsure, say N. - -config PATA_EFAR - tristate "EFAR SLC90E66 support" - depends on PCI - help - This option enables support for the EFAR SLC90E66 - IDE controller found on some older machines. - - If unsure, say N. - -config ATA_GENERIC - tristate "Generic ATA support" - depends on PCI - help - This option enables support for generic BIOS configured - ATA controllers via the new ATA layer - - If unsure, say N. - -config PATA_HPT366 - tristate "HPT 366/368 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the HPT 366 and 368 - PATA controllers via the new ATA layer. - - If unsure, say N. - -config PATA_HPT37X - tristate "HPT 370/370A/371/372/374/302 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the majority of the later HPT - PATA controllers via the new ATA layer. - - If unsure, say N. - -config PATA_HPT3X2N - tristate "HPT 372N/302N PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the N variant HPT PATA - controllers via the new ATA layer - - If unsure, say N. - -config PATA_HPT3X3 - tristate "HPT 343/363 PATA support (Experimental)" - depends on PCI - help - This option enables support for the HPT 343/363 - PATA controllers via the new ATA layer - - If unsure, say N. - -config PATA_ISAPNP - tristate "ISA Plug and Play PATA support (Very Experimental)" - depends on EXPERIMENTAL && ISAPNP - help - This option enables support for ISA plug & play ATA - controllers such as those found on old soundcards. - - If unsure, say N. - -config PATA_IT8172 - tristate "IT8172 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the ITE 8172 PATA controller - via the new ATA layer. - - If unsure, say N. - -config PATA_IT821X - tristate "IT821x PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the ITE 8211 and 8212 - PATA controllers via the new ATA layer, including RAID - mode. - - If unsure, say N. - -config PATA_LEGACY - tristate "Legacy ISA PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for ISA/VLB bus legacy PATA - ports and allows them to be accessed via the new ATA layer. - - If unsure, say N. - -config PATA_TRIFLEX - tristate "Compaq Triflex PATA support" - depends on PCI - help - Enable support for the Compaq 'Triflex' IDE controller as found - on many Compaq Pentium-Pro systems, via the new ATA layer. - - If unsure, say N. - -config PATA_MPIIX - tristate "Intel PATA MPIIX support" - depends on PCI - help - This option enables support for MPIIX PATA support. - - If unsure, say N. - -config PATA_OLDPIIX - tristate "Intel PATA old PIIX support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for old(?) PIIX PATA support. - - If unsure, say N. - -config PATA_NETCELL - tristate "NETCELL Revolution RAID support" - depends on PCI - help - This option enables support for the Netcell Revolution RAID - PATA controller. - - If unsure, say N. - -config PATA_NS87410 - tristate "Nat Semi NS87410 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the National Semiconductor - NS87410 PCI-IDE controller. - - If unsure, say N. - -config PATA_OPTI - tristate "OPTI621/6215 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables full PIO support for the early Opti ATA - controllers found on some old motherboards. - - If unsure, say N. - -config PATA_OPTIDMA - tristate "OPTI FireStar PATA support (Veyr Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables DMA/PIO support for the later OPTi - controllers found on some old motherboards and in some - latops - - If unsure, say N. - -config PATA_PCMCIA - tristate "PCMCIA PATA support" - depends on PCMCIA - help - This option enables support for PCMCIA ATA interfaces, including - compact flash card adapters via the new ATA layer. - - If unsure, say N. - -config PATA_PDC_OLD - tristate "Older Promise PATA controller support (Very Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the Promise 20246, 20262, 20263, - 20265 and 20267 adapters. - - If unsure, say N. - -config PATA_QDI - tristate "QDI VLB PATA support" - help - Support for QDI 6500 and 6580 PATA controllers on VESA local bus. - -config PATA_RADISYS - tristate "RADISYS 82600 PATA support (Very experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the RADISYS 82600 - PATA controllers via the new ATA layer - - If unsure, say N. - -config PATA_RZ1000 - tristate "PC Tech RZ1000 PATA support" - depends on PCI - help - This option enables basic support for the PC Tech RZ1000/1 - PATA controllers via the new ATA layer - - If unsure, say N. - -config PATA_SC1200 - tristate "SC1200 PATA support (Raving Lunatic)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the NatSemi/AMD SC1200 SoC - companion chip used with the Geode processor family. - - If unsure, say N. - -config PATA_SERVERWORKS - tristate "SERVERWORKS OSB4/CSB5/CSB6/HT1000 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for the Serverworks OSB4/CSB5/CSB6 and - HT1000 PATA controllers, via the new ATA layer. - - If unsure, say N. - -config PATA_PDC2027X - tristate "Promise PATA 2027x support" - depends on PCI - help - This option enables support for Promise PATA pdc20268 to pdc20277 host adapters. - - If unsure, say N. - -config PATA_SIL680 - tristate "CMD / Silicon Image 680 PATA support" - depends on PCI - help - This option enables support for CMD / Silicon Image 680 PATA. - - If unsure, say N. - -config PATA_SIS - tristate "SiS PATA support (Experimental)" - depends on PCI && EXPERIMENTAL - help - This option enables support for SiS PATA controllers - - If unsure, say N. - -config PATA_VIA - tristate "VIA PATA support" - depends on PCI - help - This option enables support for the VIA PATA interfaces - found on the many VIA chipsets. - - If unsure, say N. - -config PATA_WINBOND - tristate "Winbond SL82C105 PATA support" - depends on PCI - help - This option enables support for SL82C105 PATA devices found in the - Netwinder and some other systems - - If unsure, say N. - endif endmenu diff --git a/trunk/drivers/ata/Makefile b/trunk/drivers/ata/Makefile index b183a04aeaf7..e260e3fe65c8 100644 --- a/trunk/drivers/ata/Makefile +++ b/trunk/drivers/ata/Makefile @@ -17,46 +17,5 @@ obj-$(CONFIG_SATA_ULI) += sata_uli.o obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_PDC_ADMA) += pdc_adma.o -obj-$(CONFIG_PATA_ALI) += pata_ali.o -obj-$(CONFIG_PATA_AMD) += pata_amd.o -obj-$(CONFIG_PATA_ARTOP) += pata_artop.o -obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o -obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o -obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o -obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o -obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o -obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o -obj-$(CONFIG_PATA_EFAR) += pata_efar.o -obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o -obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o -obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o -obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o -obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o -obj-$(CONFIG_PATA_IT8172) += pata_it8172.o -obj-$(CONFIG_PATA_IT821X) += pata_it821x.o -obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o -obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o -obj-$(CONFIG_PATA_OPTI) += pata_opti.o -obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o -obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o -obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o -obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o -obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o -obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o -obj-$(CONFIG_PATA_QDI) += pata_qdi.o -obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o -obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o -obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o -obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o -obj-$(CONFIG_PATA_SIL680) += pata_sil680.o -obj-$(CONFIG_PATA_VIA) += pata_via.o -obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o -obj-$(CONFIG_PATA_SIS) += pata_sis.o -obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o -# Should be last but one libata driver -obj-$(CONFIG_ATA_GENERIC) += ata_generic.o -# Should be last libata driver -obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o - libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o diff --git a/trunk/drivers/ata/ata_generic.c b/trunk/drivers/ata/ata_generic.c deleted file mode 100644 index 1d1c30a2fcd0..000000000000 --- a/trunk/drivers/ata/ata_generic.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * ata_generic.c - Generic PATA/SATA controller driver. - * Copyright 2005 Red Hat Inc , all rights reserved. - * - * Elements from ide/pci/generic.c - * Copyright (C) 2001-2002 Andre Hedrick - * Portions (C) Copyright 2002 Red Hat Inc - * - * May be copied or modified under the terms of the GNU General Public License - * - * Driver for PCI IDE interfaces implementing the standard bus mastering - * interface functionality. This assumes the BIOS did the drive set up and - * tuning for us. By default we do not grab all IDE class devices as they - * may have other drivers or need fixups to avoid problems. Instead we keep - * a default list of stuff without documentation/driver that appears to - * work. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "ata_generic" -#define DRV_VERSION "0.2.6" - -/* - * A generic parallel ATA driver using libata - */ - -/** - * generic_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int generic_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - - -/** - * generic_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * @classes: - * - * LOCKING: - * None (inherited from caller). - */ - - -static void generic_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, generic_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * generic_set_mode - mode setting - * @ap: interface to set up - * - * Use a non standard set_mode function. We don't want to be tuned. - * The BIOS configured everything. Our job is not to fiddle. We - * read the dma enabled bits from the PCI configuration of the device - * and respect them. - */ - -static void generic_set_mode(struct ata_port *ap) -{ - int dma_enabled = 0; - int i; - - /* Bits 5 and 6 indicate if DMA is active on master/slave */ - if (ap->ioaddr.bmdma_addr) - dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->dma_mode = XFER_MW_DMA_0; - /* We do need the right mode information for DMA or PIO - and this comes from the current configuration flags */ - if (dma_enabled & (1 << (5 + i))) { - dev->xfer_mode = XFER_MW_DMA_0; - dev->xfer_shift = ATA_SHIFT_MWDMA; - dev->flags &= ~ATA_DFLAG_PIO; - } else { - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } - } - } -} - -static struct scsi_host_template generic_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations generic_port_ops = { - .set_mode = generic_set_mode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .data_xfer = ata_pio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = generic_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int all_generic_ide; /* Set to claim all devices */ - -/** - * ata_generic_init - attach generic IDE - * @dev: PCI device found - * @id: match entry - * - * Called each time a matching IDE interface is found. We check if the - * interface is one we wish to claim and if so we perform any chip - * specific hacks then let the ATA layer do the heavy lifting. - */ - -static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - u16 command; - static struct ata_port_info info = { - .sht = &generic_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &generic_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - /* Don't use the generic entry unless instructed to do so */ - if (id->driver_data == 1 && all_generic_ide == 0) - return -ENODEV; - - /* Devices that need care */ - if (dev->vendor == PCI_VENDOR_ID_UMC && - dev->device == PCI_DEVICE_ID_UMC_UM8886A && - (!(PCI_FUNC(dev->devfn) & 1))) - return -ENODEV; - - if (dev->vendor == PCI_VENDOR_ID_OPTI && - dev->device == PCI_DEVICE_ID_OPTI_82C558 && - (!(PCI_FUNC(dev->devfn) & 1))) - return -ENODEV; - - /* Don't re-enable devices in generic mode or we will break some - motherboards with disabled and unused IDE controllers */ - pci_read_config_word(dev, PCI_COMMAND, &command); - if (!(command & PCI_COMMAND_IO)) - return -ENODEV; - - if (dev->vendor == PCI_VENDOR_ID_AL) - ata_pci_clear_simplex(dev); - - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id ata_generic[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), }, - { PCI_DEVICE(PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), }, - { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F), }, - { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A), }, - { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF), }, - { PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), }, - { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, - { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), }, - { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, - { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, - /* Must come last. If you add entries adjust this table appropriately */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, - { 0, }, -}; - -static struct pci_driver ata_generic_pci_driver = { - .name = DRV_NAME, - .id_table = ata_generic, - .probe = ata_generic_init_one, - .remove = ata_pci_remove_one -}; - -static int __init ata_generic_init(void) -{ - return pci_module_init(&ata_generic_pci_driver); -} - - -static void __exit ata_generic_exit(void) -{ - pci_unregister_driver(&ata_generic_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for generic ATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, ata_generic); -MODULE_VERSION(DRV_VERSION); - -module_init(ata_generic_init); -module_exit(ata_generic_exit); - -module_param(all_generic_ide, int, 0); diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 1a4c03d5de9f..22b2dba90b9a 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -93,7 +93,7 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.00ac6" +#define DRV_VERSION "2.00" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -116,17 +116,14 @@ enum { PIIX_80C_SEC = (1 << 7) | (1 << 6), /* controller IDs */ - piix_pata_33 = 0, /* PIIX3 or 4 at 33Mhz */ - ich_pata_33 = 1, /* ICH up to UDMA 33 only */ - ich_pata_66 = 2, /* ICH up to 66 Mhz */ - ich_pata_100 = 3, /* ICH up to UDMA 100 */ - ich_pata_133 = 4, /* ICH up to UDMA 133 */ - ich5_sata = 5, - esb_sata = 6, - ich6_sata = 7, - ich6_sata_ahci = 8, - ich6m_sata_ahci = 9, - ich8_sata_ahci = 10, + piix4_pata = 0, + ich5_pata = 1, + ich5_sata = 2, + esb_sata = 3, + ich6_sata = 4, + ich6_sata_ahci = 5, + ich6m_sata_ahci = 6, + ich8_sata_ahci = 7, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -155,54 +152,19 @@ struct piix_host_priv { static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void piix_host_stop(struct ata_host *host); -static void piix_pata_error_handler(struct ata_port *ap); -static void ich_pata_error_handler(struct ata_port *ap); -static void piix_sata_error_handler(struct ata_port *ap); static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); -static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev); +static void piix_pata_error_handler(struct ata_port *ap); +static void piix_sata_error_handler(struct ata_port *ap); static unsigned int in_module_init = 1; static const struct pci_device_id piix_pci_tbl[] = { #ifdef ATA_ENABLE_PATA - /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ - /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ - { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, - { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel PIIX4 */ - { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, - /* Intel PIIX4 */ - { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, - /* Intel PIIX */ - { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, - /* Intel ICH (i810, i815, i840) UDMA 66*/ - { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 }, - /* Intel ICH0 : UDMA 33*/ - { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 }, - /* Intel ICH2M */ - { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */ - { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel ICH3M */ - { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel ICH3 (E7500/1) UDMA 100 */ - { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ - { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* Intel ICH5 */ - { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, - /* C-ICH (i810E2) */ - { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* ESB (855GME/875P + 6300ESB) UDMA 100 */ - { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* ICH6 (and 6) (i915) UDMA 100 */ - { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* ICH7/7-R (i945, i975) UDMA 100*/ - { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, - { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, + { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, + { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, #endif /* NOTE: The following PCI ids must be kept in sync with the @@ -301,39 +263,6 @@ static const struct ata_port_operations piix_pata_ops = { .host_stop = piix_host_stop, }; -static const struct ata_port_operations ich_pata_ops = { - .port_disable = ata_port_disable, - .set_piomode = piix_set_piomode, - .set_dmamode = ich_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ich_pata_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - static const struct ata_port_operations piix_sata_ops = { .port_disable = ata_port_disable, @@ -430,56 +359,35 @@ static const struct piix_map_db *piix_map_db_table[] = { }; static struct ata_port_info piix_port_info[] = { - /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ + /* piix4_pata */ { .sht = &piix_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif .udma_mask = ATA_UDMA_MASK_40C, .port_ops = &piix_pata_ops, }, - /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ - { - .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA2, /* UDMA33 */ - .port_ops = &ich_pata_ops, - }, - /* ich_pata_66: 2 ICH controllers up to 66MHz */ - { - .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ - .udma_mask = ATA_UDMA4, - .port_ops = &ich_pata_ops, - }, - - /* ich_pata_100: 3 */ + /* ich5_pata */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, + .flags = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ +#if 0 .mwdma_mask = 0x06, /* mwdma1-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ - .port_ops = &ich_pata_ops, - }, - - /* ich_pata_133: 4 ICH with full UDMA6 */ - { - .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA6, /* UDMA133 */ - .port_ops = &ich_pata_ops, +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = 0x3f, /* udma0-5 */ + .port_ops = &piix_pata_ops, }, - /* ich5_sata: 5 */ + /* ich5_sata */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | @@ -490,7 +398,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* i6300esb_sata: 6 */ + /* i6300esb_sata */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | @@ -501,7 +409,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6_sata: 7 */ + /* ich6_sata */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | @@ -512,7 +420,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6_sata_ahci:8 */ + /* ich6_sata_ahci */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | @@ -524,7 +432,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6m_sata_ahci: 9 */ + /* ich6m_sata_ahci */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | @@ -547,7 +455,6 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, - }; static struct pci_bits piix_enable_bits[] = { @@ -576,8 +483,7 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " * LOCKING: * None (inherited from caller). */ - -static void ich_pata_cbl_detect(struct ata_port *ap) +static void piix_pata_cbl_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 tmp, mask; @@ -597,12 +503,14 @@ static void ich_pata_cbl_detect(struct ata_port *ap) cbl40: ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; } /** * piix_pata_prereset - prereset for PATA host controller * @ap: Target port * + * Prereset including cable detection. * * LOCKING: * None (inherited from caller). @@ -611,48 +519,20 @@ static int piix_pata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); - if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) { - ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); - ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static void piix_pata_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL, - ata_std_postreset); -} - - -/** - * ich_pata_prereset - prereset for PATA host controller - * @ap: Target port - * - * - * LOCKING: - * None (inherited from caller). - */ -static int ich_pata_prereset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) { ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; } - ich_pata_cbl_detect(ap); + piix_pata_cbl_detect(ap); return ata_std_prereset(ap); } -static void ich_pata_error_handler(struct ata_port *ap) +static void piix_pata_error_handler(struct ata_port *ap) { - ata_bmdma_drive_eh(ap, ich_pata_prereset, ata_std_softreset, NULL, + ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL, ata_std_postreset); } @@ -757,13 +637,6 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) unsigned int slave_port = 0x44; u16 master_data; u8 slave_data; - u8 udma_enable; - int control = 0; - - /* - * See Intel Document 298600-004 for the timing programing rules - * for ICH controllers. - */ static const /* ISP RTC */ u8 timings[][2] = { { 0, 0 }, @@ -772,30 +645,20 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) { 2, 1 }, { 2, 3 }, }; - if (pio >= 2) - control |= 1; /* TIME1 enable */ - if (ata_pio_need_iordy(adev)) - control |= 2; /* IE enable */ - - /* Intel specifies that the PPE functionality is for disk only */ - if (adev->class == ATA_DEV_ATA) - control |= 4; /* PPE enable */ - pci_read_config_word(dev, master_port, &master_data); if (is_slave) { - /* Enable SITRE (seperate slave timing register) */ master_data |= 0x4000; - /* enable PPE1, IE1 and TIME1 as needed */ - master_data |= (control << 4); + /* enable PPE, IE and TIME */ + master_data |= 0x0070; pci_read_config_byte(dev, slave_port, &slave_data); slave_data &= (ap->port_no ? 0x0f : 0xf0); - /* Load the timing nibble for this slave */ - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); + slave_data |= + (timings[pio][0] << 2) | + (timings[pio][1] << (ap->port_no ? 4 : 0)); } else { - /* Master keeps the bits in a different format */ master_data &= 0xccf8; - /* Enable PPE, IE and TIME as appropriate */ - master_data |= control; + /* enable PPE, IE and TIME */ + master_data |= 0x0007; master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); @@ -803,23 +666,13 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) pci_write_config_word(dev, master_port, master_data); if (is_slave) pci_write_config_byte(dev, slave_port, slave_data); - - /* Ensure the UDMA bit is off - it will be turned back on if - UDMA is selected */ - - if (ap->udma_mask) { - pci_read_config_byte(dev, 0x48, &udma_enable); - udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); - pci_write_config_byte(dev, 0x48, udma_enable); - } } /** - * do_pata_set_dmamode - Initialize host controller PATA PIO timings + * piix_set_dmamode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring - * @adev: Drive in question + * @adev: um * @udma: udma mode, 0 - 6 - * @is_ich: set if the chip is an ICH device * * Set UDMA mode for device, in host controller PCI config space. * @@ -827,140 +680,70 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) * None (inherited from caller). */ -static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich) +static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) { + unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ struct pci_dev *dev = to_pci_dev(ap->host->dev); - u8 master_port = ap->port_no ? 0x42 : 0x40; - u16 master_data; - u8 speed = adev->dma_mode; - int devid = adev->devno + 2 * ap->port_no; - u8 udma_enable; - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pci_read_config_word(dev, master_port, &master_data); - pci_read_config_byte(dev, 0x48, &udma_enable); + u8 maslave = ap->port_no ? 0x42 : 0x40; + u8 speed = udma; + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + int a_speed = 3 << (drive_dn * 4); + int u_flag = 1 << drive_dn; + int v_flag = 0x01 << drive_dn; + int w_flag = 0x10 << drive_dn; + int u_speed = 0; + int sitre; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; + + pci_read_config_word(dev, maslave, ®4042); + DPRINTK("reg4042 = 0x%04x\n", reg4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive_dn * 4); break; + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: break; + default: + BUG(); + return; + } if (speed >= XFER_UDMA_0) { - unsigned int udma = adev->dma_mode - XFER_UDMA_0; - u16 udma_timing; - u16 ideconf; - int u_clock, u_speed; - - /* - * UDMA is handled by a combination of clock switching and - * selection of dividers - * - * Handy rule: Odd modes are UDMATIMx 01, even are 02 - * except UDMA0 which is 00 - */ - u_speed = min(2 - (udma & 1), udma); - if (udma == 5) - u_clock = 0x1000; /* 100Mhz */ - else if (udma > 2) - u_clock = 1; /* 66Mhz */ - else - u_clock = 0; /* 33Mhz */ - - udma_enable |= (1 << devid); - - /* Load the CT/RP selection */ - pci_read_config_word(dev, 0x4A, &udma_timing); - udma_timing &= ~(3 << (4 * devid)); - udma_timing |= u_speed << (4 * devid); - pci_write_config_word(dev, 0x4A, udma_timing); - - if (isich) { - /* Select a 33/66/100Mhz clock */ - pci_read_config_word(dev, 0x54, &ideconf); - ideconf &= ~(0x1001 << devid); - ideconf |= u_clock << devid; - /* For ICH or later we should set bit 10 for better - performance (WR_PingPong_En) */ - pci_write_config_word(dev, 0x54, ideconf); + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { - /* - * MWDMA is driven by the PIO timings. We must also enable - * IORDY unconditionally along with TIME1. PPE has already - * been set when the PIO timing was set. - */ - unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; - unsigned int control; - u8 slave_data; - const unsigned int needed_pio[3] = { - XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 - }; - int pio = needed_pio[mwdma] - XFER_PIO_0; - - control = 3; /* IORDY|TIME1 */ - - /* If the drive MWDMA is faster than it can do PIO then - we must force PIO into PIO0 */ - - if (adev->pio_mode < needed_pio[mwdma]) - /* Enable DMA timing only */ - control |= 8; /* PIO cycles in PIO0 */ - - if (adev->devno) { /* Slave */ - master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ - master_data |= control << 4; - pci_read_config_byte(dev, 0x44, &slave_data); - slave_data &= (0x0F + 0xE1 * ap->port_no); - /* Load the matching timing */ - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); - pci_write_config_byte(dev, 0x44, slave_data); - } else { /* Master */ - master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY - and master timing bits */ - master_data |= control; - master_data |= - (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } - udma_enable &= ~(1 << devid); - pci_write_config_word(dev, master_port, master_data); + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } - /* Don't scribble on 0x48 if the controller does not support UDMA */ - if (ap->udma_mask) - pci_write_config_byte(dev, 0x48, udma_enable); -} - -/** - * piix_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set MW/UDMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - do_pata_set_dmamode(ap, adev, 0); -} - -/** - * ich_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set MW/UDMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - do_pata_set_dmamode(ap, adev, 1); } #define AHCI_PCI_BAR 5 @@ -1089,7 +872,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, case IDE: WARN_ON((i & 1) || map[i + 1] != IDE); - pinfo[i / 2] = piix_port_info[ich_pata_100]; + pinfo[i / 2] = piix_port_info[ich5_pata]; pinfo[i / 2].private_data = hpriv; i++; printk(" IDE IDE"); @@ -1224,3 +1007,4 @@ static void __exit piix_exit(void) module_init(piix_init); module_exit(piix_exit); + diff --git a/trunk/drivers/ata/pata_ali.c b/trunk/drivers/ata/pata_ali.c deleted file mode 100644 index 8448ee6e0eed..000000000000 --- a/trunk/drivers/ata/pata_ali.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * pata_ali.c - ALI 15x3 PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based in part upon - * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 - * - * Copyright (C) 1998-2000 Michel Aubry, Maintainer - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License - * Copyright (C) 2002 Alan Cox - * ALi (now ULi M5228) support by Clear Zhang - * - * Documentation - * Chipset documentation available under NDA only - * - * TODO/CHECK - * Cannot have ATAPI on both master & slave for rev < c2 (???) but - * otherwise should do atapi DMA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_ali" -#define DRV_VERSION "0.6.5" - -/* - * Cable special cases - */ - -static struct dmi_system_id cable_dmi_table[] = { - { - .ident = "HP Pavilion N5430", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"), - }, - }, - { } -}; - -static int ali_cable_override(struct pci_dev *pdev) -{ - /* Fujitsu P2000 */ - if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF) - return 1; - /* Systems by DMI */ - if (dmi_check_system(cable_dmi_table)) - return 1; - return 0; -} - -/** - * ali_c2_cable_detect - cable detection - * @ap: ATA port - * - * Perform cable detection for C2 and later revisions - */ - -static int ali_c2_cable_detect(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 ata66; - - /* Certain laptops use short but suitable cables and don't - implement the detect logic */ - - if (ali_cable_override(pdev)) - return ATA_CBL_PATA80; - - /* Host view cable detect 0x4A bit 0 primary bit 1 secondary - Bit set for 40 pin */ - pci_read_config_byte(pdev, 0x4A, &ata66); - if (ata66 & (1 << ap->port_no)) - return ATA_CBL_PATA40; - else - return ATA_CBL_PATA80; -} - -/** - * ali_early_error_handler - reset for eary chip - * @ap: ATA port - * - * Handle the reset callback for the later chips with cable detect - */ - -static int ali_c2_pre_reset(struct ata_port *ap) -{ - ap->cbl = ali_c2_cable_detect(ap); - return ata_std_prereset(ap); -} - -static void ali_c2_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, ali_c2_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -/** - * ali_early_cable_detect - cable detection - * @ap: ATA port - * - * Perform cable detection for older chipsets. This turns out to be - * rather easy to implement - */ - -static int ali_early_cable_detect(struct ata_port *ap) -{ - return ATA_CBL_PATA40; -} - -/** - * ali_early_probe_init - reset for early chip - * @ap: ATA port - * - * Handle the reset callback for the early (pre cable detect) chips. - */ - -static int ali_early_pre_reset(struct ata_port *ap) -{ - ap->cbl = ali_early_cable_detect(ap); - return ata_std_prereset(ap); -} - -static void ali_early_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, ali_early_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -/** - * ali_20_filter - filter for earlier ALI DMA - * @ap: ALi ATA port - * @adev: attached device - * - * Ensure that we do not do DMA on CD devices. We may be able to - * fix that later on. Also ensure we do not do UDMA on WDC drives - */ - -static unsigned long ali_20_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - char model_num[40]; - /* No DMA on anything but a disk for now */ - if (adev->class != ATA_DEV_ATA) - mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - if (strstr(model_num, "WDC")) - return mask &= ~ATA_MASK_UDMA; - return ata_pci_default_filter(ap, adev, mask); -} - -/** - * ali_fifo_control - FIFO manager - * @ap: ALi channel to control - * @adev: device for FIFO control - * @on: 0 for off 1 for on - * - * Enable or disable the FIFO on a given device. Because of the way the - * ALi FIFO works it provides a boost on ATA disk but can be confused by - * ATAPI and we must therefore manage it. - */ - -static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int pio_fifo = 0x54 + ap->port_no; - u8 fifo; - int shift = 4 * adev->devno; - - /* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to - 0x00. Not all the docs agree but the behaviour we now use is the - one stated in the BIOS Programming Guide */ - - pci_read_config_byte(pdev, pio_fifo, &fifo); - fifo &= ~(0x0F << shift); - if (on) - fifo |= (on << shift); - pci_write_config_byte(pdev, pio_fifo, fifo); -} - -/** - * ali_program_modes - load mode registers - * @ap: ALi channel to load - * @adev: Device the timing is for - * @cmd: Command timing - * @data: Data timing - * @ultra: UDMA timing or zero for off - * - * Loads the timing registers for cmd/data and disable UDMA if - * ultra is zero. If ultra is set then load and enable the UDMA - * timing but do not touch the command/data timing. - */ - -static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int cas = 0x58 + 4 * ap->port_no; /* Command timing */ - int cbt = 0x59 + 4 * ap->port_no; /* Command timing */ - int drwt = 0x5A + 4 * ap->port_no + adev->devno; /* R/W timing */ - int udmat = 0x56 + ap->port_no; /* UDMA timing */ - int shift = 4 * adev->devno; - u8 udma; - - if (t != NULL) { - t->setup = FIT(t->setup, 1, 8) & 7; - t->act8b = FIT(t->act8b, 1, 8) & 7; - t->rec8b = FIT(t->rec8b, 1, 16) & 15; - t->active = FIT(t->active, 1, 8) & 7; - t->recover = FIT(t->recover, 1, 16) & 15; - - pci_write_config_byte(pdev, cas, t->setup); - pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b); - pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover); - } - - /* Set up the UDMA enable */ - pci_read_config_byte(pdev, udmat, &udma); - udma &= ~(0x0F << shift); - udma |= ultra << shift; - pci_write_config_byte(pdev, udmat, udma); -} - -/** - * ali_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the ALi registers for PIO mode. FIXME: add timings for - * PIO5. - */ - -static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct ata_device *pair = ata_dev_pair(adev); - struct ata_timing t; - unsigned long T = 1000000000 / 33333; /* PCI clock based */ - - ata_timing_compute(adev, adev->pio_mode, &t, T, 1); - if (pair) { - struct ata_timing p; - ata_timing_compute(pair, pair->pio_mode, &p, T, 1); - ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); - if (pair->dma_mode) { - ata_timing_compute(pair, pair->dma_mode, &p, T, 1); - ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); - } - } - - /* PIO FIFO is only permitted on ATA disk */ - if (adev->class != ATA_DEV_ATA) - ali_fifo_control(ap, adev, 0x00); - ali_program_modes(ap, adev, &t, 0); - if (adev->class == ATA_DEV_ATA) - ali_fifo_control(ap, adev, 0x05); - -} - -/** - * ali_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * FIXME: MWDMA timings - */ - -static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD }; - struct ata_device *pair = ata_dev_pair(adev); - struct ata_timing t; - unsigned long T = 1000000000 / 33333; /* PCI clock based */ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - - if (adev->class == ATA_DEV_ATA) - ali_fifo_control(ap, adev, 0x08); - - if (adev->dma_mode >= XFER_UDMA_0) { - ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]); - if (adev->dma_mode >= XFER_UDMA_3) { - u8 reg4b; - pci_read_config_byte(pdev, 0x4B, ®4b); - reg4b |= 1; - pci_write_config_byte(pdev, 0x4B, reg4b); - } - } else { - ata_timing_compute(adev, adev->dma_mode, &t, T, 1); - if (pair) { - struct ata_timing p; - ata_timing_compute(pair, pair->pio_mode, &p, T, 1); - ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); - if (pair->dma_mode) { - ata_timing_compute(pair, pair->dma_mode, &p, T, 1); - ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); - } - } - ali_program_modes(ap, adev, &t, 0); - } -} - -/** - * ali_lock_sectors - Keep older devices to 255 sector mode - * @ap: ATA port - * @adev: Device - * - * Called during the bus probe for each device that is found. We use - * this call to lock the sector count of the device to 255 or less on - * older ALi controllers. If we didn't do this then large I/O's would - * require LBA48 commands which the older ALi requires are issued by - * slower PIO methods - */ - -static void ali_lock_sectors(struct ata_port *ap, struct ata_device *adev) -{ - adev->max_sectors = 255; -} - -static struct scsi_host_template ali_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - /* Keep LBA28 counts so large I/O's don't turn LBA48 and PIO - with older controllers. Not locked so will grow on C5 or later */ - .max_sectors = 255, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -/* - * Port operations for PIO only ALi - */ - -static struct ata_port_operations ali_early_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = ali_set_piomode, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ali_early_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Port operations for DMA capable ALi without cable - * detect - */ -static struct ata_port_operations ali_20_port_ops = { - .port_disable = ata_port_disable, - - .set_piomode = ali_set_piomode, - .set_dmamode = ali_set_dmamode, - .mode_filter = ali_20_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - .dev_config = ali_lock_sectors, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ali_early_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Port operations for DMA capable ALi with cable detect - */ -static struct ata_port_operations ali_c2_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = ali_set_piomode, - .set_dmamode = ali_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - .dev_config = ali_lock_sectors, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ali_c2_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Port operations for DMA capable ALi with cable detect and LBA48 - */ -static struct ata_port_operations ali_c5_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = ali_set_piomode, - .set_dmamode = ali_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ali_c2_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * ali_init_one - discovery callback - * @pdev: PCI device ID - * @id: PCI table info - * - * An ALi IDE interface has been discovered. Figure out what revision - * and perform configuration work before handing it to the ATA layer - */ - -static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - static struct ata_port_info info_early = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &ali_early_port_ops - }; - /* Revision 0x20 added DMA */ - static struct ata_port_info info_20 = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &ali_20_port_ops - }; - /* Revision 0x20 with support logic added UDMA */ - static struct ata_port_info info_20_udma = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, /* UDMA33 */ - .port_ops = &ali_20_port_ops - }; - /* Revision 0xC2 adds UDMA66 */ - static struct ata_port_info info_c2 = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, - .port_ops = &ali_c2_port_ops - }; - /* Revision 0xC3 is UDMA100 */ - static struct ata_port_info info_c3 = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &ali_c2_port_ops - }; - /* Revision 0xC4 is UDMA133 */ - static struct ata_port_info info_c4 = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &ali_c2_port_ops - }; - /* Revision 0xC5 is UDMA133 with LBA48 DMA */ - static struct ata_port_info info_c5 = { - .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &ali_c5_port_ops - }; - - static struct ata_port_info *port_info[2]; - u8 rev, tmp; - struct pci_dev *north, *isa_bridge; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - - /* - * The chipset revision selects the driver operations and - * mode data. - */ - - if (rev < 0x20) { - port_info[0] = port_info[1] = &info_early; - } else if (rev < 0xC2) { - /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ - pci_read_config_byte(pdev, 0x4B, &tmp); - /* Clear CD-ROM DMA write bit */ - tmp &= 0x7F; - pci_write_config_byte(pdev, 0x4B, tmp); - port_info[0] = port_info[1] = &info_20; - } else if (rev == 0xC2) { - port_info[0] = port_info[1] = &info_c2; - } else if (rev == 0xC3) { - port_info[0] = port_info[1] = &info_c3; - } else if (rev == 0xC4) { - port_info[0] = port_info[1] = &info_c4; - } else - port_info[0] = port_info[1] = &info_c5; - - if (rev >= 0xC2) { - /* Enable cable detection logic */ - pci_read_config_byte(pdev, 0x4B, &tmp); - pci_write_config_byte(pdev, 0x4B, tmp | 0x08); - } - - north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0)); - isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - if (north && north->vendor == PCI_VENDOR_ID_AL) { - /* Configure the ALi bridge logic. For non ALi rely on BIOS. - Set the south bridge enable bit */ - pci_read_config_byte(isa_bridge, 0x79, &tmp); - if (rev == 0xC2) - pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); - else if (rev > 0xC2) - pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); - } - - if (rev >= 0x20) { - if (rev < 0xC2) { - /* Are we paired with a UDMA capable chip */ - pci_read_config_byte(isa_bridge, 0x5E, &tmp); - if ((tmp & 0x1E) == 0x12) - port_info[0] = port_info[1] = &info_20_udma; - } - /* - * CD_ROM DMA on (0x53 bit 0). Enable this even if we want - * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control - * via 0x54/55. - */ - pci_read_config_byte(pdev, 0x53, &tmp); - if (rev <= 0x20) - tmp &= ~0x02; - if (rev == 0xc7) - tmp |= 0x03; - else - tmp |= 0x01; /* CD_ROM enable for DMA */ - pci_write_config_byte(pdev, 0x53, tmp); - } - - pci_dev_put(isa_bridge); - pci_dev_put(north); - - ata_pci_clear_simplex(pdev); - return ata_pci_init_one(pdev, port_info, 2); -} - -static struct pci_device_id ali[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228), }, - { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229), }, - { 0, }, -}; - -static struct pci_driver ali_pci_driver = { - .name = DRV_NAME, - .id_table = ali, - .probe = ali_init_one, - .remove = ata_pci_remove_one -}; - -static int __init ali_init(void) -{ - return pci_register_driver(&ali_pci_driver); -} - - -static void __exit ali_exit(void) -{ - pci_unregister_driver(&ali_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for ALi PATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, ali); -MODULE_VERSION(DRV_VERSION); - -module_init(ali_init); -module_exit(ali_exit); diff --git a/trunk/drivers/ata/pata_amd.c b/trunk/drivers/ata/pata_amd.c deleted file mode 100644 index b3f60fdb02d0..000000000000 --- a/trunk/drivers/ata/pata_amd.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * pata_amd.c - AMD PATA for new ATA layer - * (C) 2005-2006 Red Hat Inc - * Alan Cox - * - * Based on pata-sil680. Errata information is taken from data sheets - * and the amd74xx.c driver by Vojtech Pavlik. Nvidia SATA devices are - * claimed by sata-nv.c. - * - * TODO: - * Variable system clock when/if it makes sense - * Power management on ports - * - * - * Documentation publically available. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_amd" -#define DRV_VERSION "0.2.2" - -/** - * timing_setup - shared timing computation and load - * @ap: ATA port being set up - * @adev: drive being configured - * @offset: port offset - * @speed: target speed - * @clock: clock multiplier (number of times 33MHz for this part) - * - * Perform the actual timing set up for Nvidia or AMD PATA devices. - * The actual devices vary so they all call into this helper function - * providing the clock multipler and offset (because AMD and Nvidia put - * the ports at different locations). - */ - -static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offset, int speed, int clock) -{ - static const unsigned char amd_cyc2udma[] = { - 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_device *peer = ata_dev_pair(adev); - int dn = ap->port_no * 2 + adev->devno; - struct ata_timing at, apeer; - int T, UT; - const int amd_clock = 33333; /* KHz. */ - u8 t; - - T = 1000000000 / amd_clock; - UT = T / min_t(int, max_t(int, clock, 1), 2); - - if (ata_timing_compute(adev, speed, &at, T, UT) < 0) { - dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed); - return; - } - - if (peer) { - /* This may be over conservative */ - if (peer->dma_mode) { - ata_timing_compute(peer, peer->dma_mode, &apeer, T, UT); - ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT); - } - ata_timing_compute(peer, peer->pio_mode, &apeer, T, UT); - ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT); - } - - if (speed == XFER_UDMA_5 && amd_clock <= 33333) at.udma = 1; - if (speed == XFER_UDMA_6 && amd_clock <= 33333) at.udma = 15; - - /* - * Now do the setup work - */ - - /* Configure the address set up timing */ - pci_read_config_byte(pdev, offset + 0x0C, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(at.setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(pdev, offset + 0x0C , t); - - /* Configure the 8bit I/O timing */ - pci_write_config_byte(pdev, offset + 0x0E + (1 - (dn >> 1)), - ((FIT(at.act8b, 1, 16) - 1) << 4) | (FIT(at.rec8b, 1, 16) - 1)); - - /* Drive timing */ - pci_write_config_byte(pdev, offset + 0x08 + (3 - dn), - ((FIT(at.active, 1, 16) - 1) << 4) | (FIT(at.recover, 1, 16) - 1)); - - switch (clock) { - case 1: - t = at.udma ? (0xc0 | (FIT(at.udma, 2, 5) - 2)) : 0x03; - break; - - case 2: - t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 2, 10)]) : 0x03; - break; - - case 3: - t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 10)]) : 0x03; - break; - - case 4: - t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 15)]) : 0x03; - break; - - default: - return; - } - - /* UDMA timing */ - pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); -} - -/** - * amd_probe_init - cable detection - * @ap: ATA port - * - * Perform cable detection. The BIOS stores this in PCI config - * space for us. - */ - -static int amd_pre_reset(struct ata_port *ap) -{ - static const u32 bitmask[2] = {0x03, 0xC0}; - static const struct pci_bits amd_enable_bits[] = { - { 0x40, 1, 0x02, 0x02 }, - { 0x40, 1, 0x01, 0x01 } - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 ata66; - - if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - - pci_read_config_byte(pdev, 0x42, &ata66); - if (ata66 & bitmask[ap->port_no]) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); - -} - -static void amd_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, amd_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -static int amd_early_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static struct pci_bits amd_enable_bits[] = { - { 0x40, 1, 0x02, 0x02 }, - { 0x40, 1, 0x01, 0x01 } - }; - - if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - /* No host side cable detection */ - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); - -} - -static void amd_early_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, amd_early_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -/** - * amd33_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the AMD registers for PIO mode. - */ - -static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->pio_mode, 1); -} - -static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->pio_mode, 2); -} - -static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->pio_mode, 3); -} - -static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->pio_mode, 4); -} - -/** - * amd33_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the MWDMA/UDMA modes for the AMD and Nvidia - * chipset. - */ - -static void amd33_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->dma_mode, 1); -} - -static void amd66_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->dma_mode, 2); -} - -static void amd100_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->dma_mode, 3); -} - -static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x40, adev->dma_mode, 4); -} - - -/** - * nv_probe_init - cable detection - * @ap: ATA port - * - * Perform cable detection. The BIOS stores this in PCI config - * space for us. - */ - -static int nv_pre_reset(struct ata_port *ap) { - static const u8 bitmask[2] = {0x03, 0xC0}; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 ata66; - u16 udma; - - pci_read_config_byte(pdev, 0x52, &ata66); - if (ata66 & bitmask[ap->port_no]) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - - /* We now have to double check because the Nvidia boxes BIOS - doesn't always set the cable bits but does set mode bits */ - - pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma); - if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400) - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -static void nv_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, nv_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} -/** - * nv100_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the AMD registers for PIO mode. - */ - -static void nv100_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x50, adev->pio_mode, 3); -} - -static void nv133_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x50, adev->pio_mode, 4); -} - -/** - * nv100_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the MWDMA/UDMA modes for the AMD and Nvidia - * chipset. - */ - -static void nv100_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x50, adev->dma_mode, 3); -} - -static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - timing_setup(ap, adev, 0x50, adev->dma_mode, 4); -} - -static struct scsi_host_template amd_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations amd33_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = amd33_set_piomode, - .set_dmamode = amd33_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = amd_early_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations amd66_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = amd66_set_piomode, - .set_dmamode = amd66_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = amd_early_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations amd100_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = amd100_set_piomode, - .set_dmamode = amd100_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = amd_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations amd133_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = amd133_set_piomode, - .set_dmamode = amd133_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = amd_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations nv100_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = nv100_set_piomode, - .set_dmamode = nv100_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = nv_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations nv133_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = nv133_set_piomode, - .set_dmamode = nv133_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = nv_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - static struct ata_port_info info[10] = { - { /* 0: AMD 7401 */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, /* No SWDMA */ - .udma_mask = 0x07, /* UDMA 33 */ - .port_ops = &amd33_port_ops - }, - { /* 1: Early AMD7409 - no swdma */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, /* UDMA 66 */ - .port_ops = &amd66_port_ops - }, - { /* 2: AMD 7409, no swdma errata */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, /* UDMA 66 */ - .port_ops = &amd66_port_ops - }, - { /* 3: AMD 7411 */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, /* UDMA 100 */ - .port_ops = &amd100_port_ops - }, - { /* 4: AMD 7441 */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, /* UDMA 100 */ - .port_ops = &amd100_port_ops - }, - { /* 5: AMD 8111*/ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, /* UDMA 133, no swdma */ - .port_ops = &amd133_port_ops - }, - { /* 6: AMD 8111 UDMA 100 (Serenade) */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, /* UDMA 100, no swdma */ - .port_ops = &amd133_port_ops - }, - { /* 7: Nvidia Nforce */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, /* UDMA 100 */ - .port_ops = &nv100_port_ops - }, - { /* 8: Nvidia Nforce2 and later */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, /* UDMA 133, no swdma */ - .port_ops = &nv133_port_ops - }, - { /* 9: AMD CS5536 (Geode companion) */ - .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, /* UDMA 100 */ - .port_ops = &amd100_port_ops - } - }; - static struct ata_port_info *port_info[2]; - static int printed_version; - int type = id->driver_data; - u8 rev; - u8 fifo; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - pci_read_config_byte(pdev, 0x41, &fifo); - - /* Check for AMD7409 without swdma errata and if found adjust type */ - if (type == 1 && rev > 0x7) - type = 2; - - /* Check for AMD7411 */ - if (type == 3) - /* FIFO is broken */ - pci_write_config_byte(pdev, 0x41, fifo & 0x0F); - else - pci_write_config_byte(pdev, 0x41, fifo | 0xF0); - - /* Serenade ? */ - if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD && - pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) - type = 6; /* UDMA 100 only */ - - if (type < 3) - ata_pci_clear_simplex(pdev); - - /* And fire it up */ - - port_info[0] = port_info[1] = &info[type]; - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id amd[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, - { 0, }, -}; - -static struct pci_driver amd_pci_driver = { - .name = DRV_NAME, - .id_table = amd, - .probe = amd_init_one, - .remove = ata_pci_remove_one -}; - -static int __init amd_init(void) -{ - return pci_register_driver(&amd_pci_driver); -} - -static void __exit amd_exit(void) -{ - pci_unregister_driver(&amd_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for AMD PATA IDE"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, amd); -MODULE_VERSION(DRV_VERSION); - -module_init(amd_init); -module_exit(amd_exit); diff --git a/trunk/drivers/ata/pata_artop.c b/trunk/drivers/ata/pata_artop.c deleted file mode 100644 index d6ef3bf1bac7..000000000000 --- a/trunk/drivers/ata/pata_artop.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * pata_artop.c - ARTOP ATA controller driver - * - * (C) 2006 Red Hat - * - * Based in part on drivers/ide/pci/aec62xx.c - * Copyright (C) 1999-2002 Andre Hedrick - * 865/865R fixes for Macintosh card version from a patch to the old - * driver by Thibaut VARENE - * When setting the PCI latency we must set 0x80 or higher for burst - * performance Alessandro Zummo - * - * TODO - * 850 serialization once the core supports it - * Investigate no_dsc on 850R - * Clock detect - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_artop" -#define DRV_VERSION "0.4.1" - -/* - * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we - * get PCI bus speed functionality we leave this as 0. Its a variable - * for when we get the functionality and also for folks wanting to - * test stuff. - */ - -static int clock = 0; - -static int artop6210_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - const struct pci_bits artop_enable_bits[] = { - { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ - { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */ - }; - - if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * artop6210_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6210_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, artop6210_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -/** - * artop6260_pre_reset - check for 40/80 pin - * @ap: Port - * - * The ARTOP hardware reports the cable detect bits in register 0x49. - * Nothing complicated needed here. - */ - -static int artop6260_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits artop_enable_bits[] = { - { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ - { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */ - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 tmp; - - /* Odd numbered device ids are the units with enable bits (the -R cards) */ - if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - pci_read_config_byte(pdev, 0x49, &tmp); - if (tmp & (1 >> ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -/** - * artop6260_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6260_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, artop6260_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); -} - -/** - * artop6210_load_piomode - Load a set of PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device - * @pio: PIO mode - * - * Set PIO mode for device, in host controller PCI config space. This - * is used both to set PIO timings in PIO mode and also to set the - * matching PIO clocking for UDMA, as well as the MWDMA timings. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6210_load_piomode(struct ata_port *ap, struct ata_device *adev, unsigned int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = adev->devno + 2 * ap->port_no; - const u16 timing[2][5] = { - { 0x0000, 0x000A, 0x0008, 0x0303, 0x0301 }, - { 0x0700, 0x070A, 0x0708, 0x0403, 0x0401 } - - }; - /* Load the PIO timing active/recovery bits */ - pci_write_config_word(pdev, 0x40 + 2 * dn, timing[clock][pio]); -} - -/** - * artop6210_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring - * - * Set PIO mode for device, in host controller PCI config space. For - * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In - * the event UDMA is used the later call to set_dmamode will set the - * bits as required. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6210_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = adev->devno + 2 * ap->port_no; - u8 ultra; - - artop6210_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); - - /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */ - pci_read_config_byte(pdev, 0x54, &ultra); - ultra &= ~(3 << (2 * dn)); - pci_write_config_byte(pdev, 0x54, ultra); -} - -/** - * artop6260_load_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring - * @pio: PIO mode - * - * Set PIO mode for device, in host controller PCI config space. The - * ARTOP6260 and relatives store the timing data differently. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6260_load_piomode (struct ata_port *ap, struct ata_device *adev, unsigned int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = adev->devno + 2 * ap->port_no; - const u8 timing[2][5] = { - { 0x00, 0x0A, 0x08, 0x33, 0x31 }, - { 0x70, 0x7A, 0x78, 0x43, 0x41 } - - }; - /* Load the PIO timing active/recovery bits */ - pci_write_config_byte(pdev, 0x40 + dn, timing[clock][pio]); -} - -/** - * artop6260_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring - * - * Set PIO mode for device, in host controller PCI config space. For - * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In - * the event UDMA is used the later call to set_dmamode will set the - * bits as required. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6260_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 ultra; - - artop6260_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); - - /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */ - pci_read_config_byte(pdev, 0x44 + ap->port_no, &ultra); - ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */ - pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra); -} - -/** - * artop6210_set_dmamode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set DMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6210_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = adev->devno + 2 * ap->port_no; - u8 ultra; - - if (adev->dma_mode == XFER_MW_DMA_0) - pio = 1; - else - pio = 4; - - /* Load the PIO timing active/recovery bits */ - artop6210_load_piomode(ap, adev, pio); - - pci_read_config_byte(pdev, 0x54, &ultra); - ultra &= ~(3 << (2 * dn)); - - /* Add ultra DMA bits if in UDMA mode */ - if (adev->dma_mode >= XFER_UDMA_0) { - u8 mode = (adev->dma_mode - XFER_UDMA_0) + 1 - clock; - if (mode == 0) - mode = 1; - ultra |= (mode << (2 * dn)); - } - pci_write_config_byte(pdev, 0x54, ultra); -} - -/** - * artop6260_set_dmamode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring - * - * Set DMA mode for device, in host controller PCI config space. The - * ARTOP6260 and relatives store the timing data differently. - * - * LOCKING: - * None (inherited from caller). - */ - -static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 ultra; - - if (adev->dma_mode == XFER_MW_DMA_0) - pio = 1; - else - pio = 4; - - /* Load the PIO timing active/recovery bits */ - artop6260_load_piomode(ap, adev, pio); - - /* Add ultra DMA bits if in UDMA mode */ - pci_read_config_byte(pdev, 0x44 + ap->port_no, &ultra); - ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */ - if (adev->dma_mode >= XFER_UDMA_0) { - u8 mode = adev->dma_mode - XFER_UDMA_0 + 1 - clock; - if (mode == 0) - mode = 1; - ultra |= (mode << (4 * adev->devno)); - } - pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra); -} - -static struct scsi_host_template artop_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations artop6210_ops = { - .port_disable = ata_port_disable, - .set_piomode = artop6210_set_piomode, - .set_dmamode = artop6210_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = artop6210_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations artop6260_ops = { - .port_disable = ata_port_disable, - .set_piomode = artop6260_set_piomode, - .set_dmamode = artop6260_set_dmamode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = artop6260_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * artop_init_one - Register ARTOP ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in artop_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) -{ - static int printed_version; - static struct ata_port_info info_6210 = { - .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA2, - .port_ops = &artop6210_ops, - }; - static struct ata_port_info info_626x = { - .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA4, - .port_ops = &artop6260_ops, - }; - static struct ata_port_info info_626x_fast = { - .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, - .port_ops = &artop6260_ops, - }; - struct ata_port_info *port_info[2]; - struct ata_port_info *info; - int ports = 2; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - if (id->driver_data == 0) { /* 6210 variant */ - info = &info_6210; - /* BIOS may have left us in UDMA, clear it before libata probe */ - pci_write_config_byte(pdev, 0x54, 0); - /* For the moment (also lacks dsc) */ - printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n"); - printk(KERN_WARNING "Secondary ATA ports will not be activated.\n"); - ports = 1; - } - else if (id->driver_data == 1) /* 6260 */ - info = &info_626x; - else if (id->driver_data == 2) { /* 6260 or 6260 + fast */ - unsigned long io = pci_resource_start(pdev, 4); - u8 reg; - - info = &info_626x; - if (inb(io) & 0x10) - info = &info_626x_fast; - /* Mac systems come up with some registers not set as we - will need them */ - - /* Clear reset & test bits */ - pci_read_config_byte(pdev, 0x49, ®); - pci_write_config_byte(pdev, 0x49, reg & ~ 0x30); - - /* PCI latency must be > 0x80 for burst mode, tweak it - * if required. - */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); - if (reg <= 0x80) - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); - - /* Enable IRQ output and burst mode */ - pci_read_config_byte(pdev, 0x4a, ®); - pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); - - } - port_info[0] = port_info[1] = info; - return ata_pci_init_one(pdev, port_info, ports); -} - -static const struct pci_device_id artop_pci_tbl[] = { - { 0x1191, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0x1191, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { 0x1191, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { 0x1191, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - { 0x1191, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - { } /* terminate list */ -}; - -static struct pci_driver artop_pci_driver = { - .name = DRV_NAME, - .id_table = artop_pci_tbl, - .probe = artop_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init artop_init(void) -{ - return pci_register_driver(&artop_pci_driver); -} - -static void __exit artop_exit(void) -{ - pci_unregister_driver(&artop_pci_driver); -} - - -module_init(artop_init); -module_exit(artop_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, artop_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_atiixp.c b/trunk/drivers/ata/pata_atiixp.c deleted file mode 100644 index 3f78a1e54a75..000000000000 --- a/trunk/drivers/ata/pata_atiixp.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * pata_atiixp.c - ATI PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based on - * - * linux/drivers/ide/pci/atiixp.c Version 0.01-bart2 Feb. 26, 2004 - * - * Copyright (C) 2003 ATI Inc. - * Copyright (C) 2004 Bartlomiej Zolnierkiewicz - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_atiixp" -#define DRV_VERSION "0.4.2" - -enum { - ATIIXP_IDE_PIO_TIMING = 0x40, - ATIIXP_IDE_MWDMA_TIMING = 0x44, - ATIIXP_IDE_PIO_CONTROL = 0x48, - ATIIXP_IDE_PIO_MODE = 0x4a, - ATIIXP_IDE_UDMA_CONTROL = 0x54, - ATIIXP_IDE_UDMA_MODE = 0x56 -}; - -static int atiixp_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static struct pci_bits atiixp_enable_bits[] = { - { 0x48, 1, 0x01, 0x00 }, - { 0x48, 1, 0x08, 0x00 } - }; - - if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -static void atiixp_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, atiixp_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * atiixp_set_pio_timing - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called by both the pio and dma setup functions to set the controller - * timings for PIO transfers. We must load both the mode number and - * timing values into the controller. - */ - -static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev, int pio) -{ - static u8 pio_timings[5] = { 0x5D, 0x47, 0x34, 0x22, 0x20 }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = 2 * ap->port_no + adev->devno; - - /* Check this is correct - the order is odd in both drivers */ - int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1); - u16 pio_mode_data, pio_timing_data; - - pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data); - pio_mode_data &= ~(0x7 << (4 * dn)); - pio_mode_data |= pio << (4 * dn); - pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data); - - pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data); - pio_mode_data &= ~(0xFF << timing_shift); - pio_mode_data |= (pio_timings[pio] << timing_shift); - pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data); -} - -/** - * atiixp_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. We use a shared helper for this - * as the DMA setup must also adjust the PIO timing information. - */ - -static void atiixp_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - atiixp_set_pio_timing(ap, adev, adev->pio_mode - XFER_PIO_0); -} - -/** - * atiixp_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the DMA mode setup. We use timing tables for most - * modes but must tune an appropriate PIO mode to match. - */ - -static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static u8 mwdma_timings[5] = { 0x77, 0x21, 0x20 }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dma = adev->dma_mode; - int dn = 2 * ap->port_no + adev->devno; - int wanted_pio; - - if (adev->dma_mode >= XFER_UDMA_0) { - u16 udma_mode_data; - - dma -= XFER_UDMA_0; - - pci_read_config_word(pdev, ATIIXP_IDE_UDMA_MODE, &udma_mode_data); - udma_mode_data &= ~(0x7 << (4 * dn)); - udma_mode_data |= dma << (4 * dn); - pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data); - } else { - u16 mwdma_timing_data; - /* Check this is correct - the order is odd in both drivers */ - int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1); - - dma -= XFER_MW_DMA_0; - - pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data); - mwdma_timing_data &= ~(0xFF << timing_shift); - mwdma_timing_data |= (mwdma_timings[dma] << timing_shift); - pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data); - } - /* - * We must now look at the PIO mode situation. We may need to - * adjust the PIO mode to keep the timings acceptable - */ - if (adev->dma_mode >= XFER_MW_DMA_2) - wanted_pio = 4; - else if (adev->dma_mode == XFER_MW_DMA_1) - wanted_pio = 3; - else if (adev->dma_mode == XFER_MW_DMA_0) - wanted_pio = 0; - else BUG(); - - if (adev->pio_mode != wanted_pio) - atiixp_set_pio_timing(ap, adev, wanted_pio); -} - -/** - * atiixp_bmdma_start - DMA start callback - * @qc: Command in progress - * - * When DMA begins we need to ensure that the UDMA control - * register for the channel is correctly set. - */ - -static void atiixp_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = (2 * ap->port_no) + adev->devno; - u16 tmp16; - - pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - if (adev->dma_mode >= XFER_UDMA_0) - tmp16 |= (1 << dn); - else - tmp16 &= ~(1 << dn); - pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - ata_bmdma_start(qc); -} - -/** - * atiixp_dma_stop - DMA stop callback - * @qc: Command in progress - * - * DMA has completed. Clear the UDMA flag as the next operations will - * be PIO ones not UDMA data transfer. - */ - -static void atiixp_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = (2 * ap->port_no) + qc->dev->devno; - u16 tmp16; - - pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - tmp16 &= ~(1 << dn); - pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - ata_bmdma_stop(qc); -} - -static struct scsi_host_template atiixp_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations atiixp_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = atiixp_set_piomode, - .set_dmamode = atiixp_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = atiixp_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = atiixp_bmdma_start, - .bmdma_stop = atiixp_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &atiixp_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x06, /* No MWDMA0 support */ - .udma_mask = 0x3F, - .port_ops = &atiixp_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id atiixp[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), }, - { 0, }, -}; - -static struct pci_driver atiixp_pci_driver = { - .name = DRV_NAME, - .id_table = atiixp, - .probe = atiixp_init_one, - .remove = ata_pci_remove_one -}; - -static int __init atiixp_init(void) -{ - return pci_register_driver(&atiixp_pci_driver); -} - - -static void __exit atiixp_exit(void) -{ - pci_unregister_driver(&atiixp_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for ATI IXP200/300/400"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, atiixp); -MODULE_VERSION(DRV_VERSION); - -module_init(atiixp_init); -module_exit(atiixp_exit); diff --git a/trunk/drivers/ata/pata_cmd64x.c b/trunk/drivers/ata/pata_cmd64x.c deleted file mode 100644 index abf1bb7bd322..000000000000 --- a/trunk/drivers/ata/pata_cmd64x.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * pata_cmd64x.c - ATI PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based upon - * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 - * - * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. - * Note, this driver is not used at all on other systems because - * there the "BIOS" has done all of the following already. - * Due to massive hardware bugs, UltraDMA is only supported - * on the 646U2 and not on the 646U. - * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * - * Copyright (C) 1999-2002 Andre Hedrick - * - * TODO - * Testing work - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_cmd64x" -#define DRV_VERSION "0.2.1" - -/* - * CMD64x specific registers definition. - */ - -enum { - CFR = 0x50, - CFR_INTR_CH0 = 0x02, - CNTRL = 0x51, - CNTRL_DIS_RA0 = 0x40, - CNTRL_DIS_RA1 = 0x80, - CNTRL_ENA_2ND = 0x08, - CMDTIM = 0x52, - ARTTIM0 = 0x53, - DRWTIM0 = 0x54, - ARTTIM1 = 0x55, - DRWTIM1 = 0x56, - ARTTIM23 = 0x57, - ARTTIM23_DIS_RA2 = 0x04, - ARTTIM23_DIS_RA3 = 0x08, - ARTTIM23_INTR_CH1 = 0x10, - ARTTIM2 = 0x57, - ARTTIM3 = 0x57, - DRWTIM23 = 0x58, - DRWTIM2 = 0x58, - BRST = 0x59, - DRWTIM3 = 0x5b, - BMIDECR0 = 0x70, - MRDMODE = 0x71, - MRDMODE_INTR_CH0 = 0x04, - MRDMODE_INTR_CH1 = 0x08, - MRDMODE_BLK_CH0 = 0x10, - MRDMODE_BLK_CH1 = 0x20, - BMIDESR0 = 0x72, - UDIDETCR0 = 0x73, - DTPR0 = 0x74, - BMIDECR1 = 0x78, - BMIDECSR = 0x79, - BMIDESR1 = 0x7A, - UDIDETCR1 = 0x7B, - DTPR1 = 0x7C -}; - -static int cmd64x_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static int cmd648_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 r; - - /* Check cable detect bits */ - pci_read_config_byte(pdev, BMIDECSR, &r); - if (r & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - - return ata_std_prereset(ap); -} - -static void cmd64x_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, cmd64x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -static void cmd648_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, cmd648_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * cmd64x_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. - */ - -static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_timing t; - const unsigned long T = 1000000 / 33; - const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 }; - - u8 reg; - - /* Port layout is not logical so use a table */ - const u8 arttim_port[2][2] = { - { ARTTIM0, ARTTIM1 }, - { ARTTIM23, ARTTIM23 } - }; - const u8 drwtim_port[2][2] = { - { DRWTIM0, DRWTIM1 }, - { DRWTIM2, DRWTIM3 } - }; - - int arttim = arttim_port[ap->port_no][adev->devno]; - int drwtim = drwtim_port[ap->port_no][adev->devno]; - - - if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) { - printk(KERN_ERR DRV_NAME ": mode computation failed.\n"); - return; - } - if (ap->port_no) { - /* Slave has shared address setup */ - struct ata_device *pair = ata_dev_pair(adev); - - if (pair) { - struct ata_timing tp; - ata_timing_compute(pair, pair->pio_mode, &tp, T, 0); - ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); - } - } - - printk(KERN_DEBUG DRV_NAME ": active %d recovery %d setup %d.\n", - t.active, t.recover, t.setup); - if (t.recover > 16) { - t.active += t.recover - 16; - t.recover = 16; - } - if (t.active > 16) - t.active = 16; - - /* Now convert the clocks into values we can actually stuff into - the chip */ - - if (t.recover > 1) - t.recover--; - else - t.recover = 15; - - if (t.setup > 4) - t.setup = 0xC0; - else - t.setup = setup_data[t.setup]; - - t.active &= 0x0F; /* 0 = 16 */ - - /* Load setup timing */ - pci_read_config_byte(pdev, arttim, ®); - reg &= 0x3F; - reg |= t.setup; - pci_write_config_byte(pdev, arttim, reg); - - /* Load active/recovery */ - pci_write_config_byte(pdev, drwtim, (t.active << 4) | t.recover); -} - -/** - * cmd64x_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the DMA mode setup. - */ - -static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u8 udma_data[] = { - 0x31, 0x21, 0x11, 0x25, 0x15, 0x05 - }; - static const u8 mwdma_data[] = { - 0x30, 0x20, 0x10 - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 regU, regD; - - int pciU = UDIDETCR0 + 8 * ap->port_no; - int pciD = BMIDESR0 + 8 * ap->port_no; - int shift = 2 * adev->devno; - - pci_read_config_byte(pdev, pciD, ®D); - pci_read_config_byte(pdev, pciU, ®U); - - regD &= ~(0x20 << shift); - regU &= ~(0x35 << shift); - - if (adev->dma_mode >= XFER_UDMA_0) - regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; - else - regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift; - - regD |= 0x20 << adev->devno; - - pci_write_config_byte(pdev, pciU, regU); - pci_write_config_byte(pdev, pciD, regD); -} - -/** - * cmd648_dma_stop - DMA stop callback - * @qc: Command in progress - * - * DMA has completed. - */ - -static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 dma_intr; - int dma_reg = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - int dma_mask = ap->port_no ? ARTTIM2 : CFR; - - ata_bmdma_stop(qc); - - pci_read_config_byte(pdev, dma_reg, &dma_intr); - pci_write_config_byte(pdev, dma_reg, dma_intr | dma_mask); -} - -/** - * cmd646r1_dma_stop - DMA stop callback - * @qc: Command in progress - * - * Stub for now while investigating the r1 quirk in the old driver. - */ - -static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc) -{ - ata_bmdma_stop(qc); -} - -static struct scsi_host_template cmd64x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cmd64x_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cmd64x_set_piomode, - .set_dmamode = cmd64x_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cmd64x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations cmd646r1_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cmd64x_set_piomode, - .set_dmamode = cmd64x_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cmd64x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = cmd646r1_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations cmd648_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cmd64x_set_piomode, - .set_dmamode = cmd64x_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cmd648_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = cmd648_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - u32 class_rev; - - static struct ata_port_info cmd_info[6] = { - { /* CMD 643 - no UDMA */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &cmd64x_port_ops - }, - { /* CMD 646 with broken UDMA */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &cmd64x_port_ops - }, - { /* CMD 646 with working UDMA */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA1, - .port_ops = &cmd64x_port_ops - }, - { /* CMD 646 rev 1 */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &cmd646r1_port_ops - }, - { /* CMD 648 */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, - .port_ops = &cmd648_port_ops - }, - { /* CMD 649 */ - .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA3, - .port_ops = &cmd648_port_ops - } - }; - static struct ata_port_info *port_info[2], *info; - u8 mrdmode; - - info = &cmd_info[id->driver_data]; - - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; - - if (id->driver_data == 0) /* 643 */ - ata_pci_clear_simplex(pdev); - - if (pdev->device == PCI_DEVICE_ID_CMD_646) { - /* Does UDMA work ? */ - if (class_rev > 4) - info = &cmd_info[2]; - /* Early rev with other problems ? */ - else if (class_rev == 1) - info = &cmd_info[3]; - } - - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); - pci_read_config_byte(pdev, MRDMODE, &mrdmode); - mrdmode &= ~ 0x30; /* IRQ set up */ - mrdmode |= 0x02; /* Memory read line enable */ - pci_write_config_byte(pdev, MRDMODE, mrdmode); - - /* Force PIO 0 here.. */ - - /* PPC specific fixup copied from old driver */ -#ifdef CONFIG_PPC - pci_write_config_byte(pdev, UDIDETCR0, 0xF0); -#endif - - port_info[0] = port_info[1] = info; - return ata_pci_init_one(pdev, port_info, 2); -} - -static struct pci_device_id cmd64x[] = { - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, - { 0, }, -}; - -static struct pci_driver cmd64x_pci_driver = { - .name = DRV_NAME, - .id_table = cmd64x, - .probe = cmd64x_init_one, - .remove = ata_pci_remove_one -}; - -static int __init cmd64x_init(void) -{ - return pci_register_driver(&cmd64x_pci_driver); -} - - -static void __exit cmd64x_exit(void) -{ - pci_unregister_driver(&cmd64x_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for CMD64x series PATA controllers"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, cmd64x); -MODULE_VERSION(DRV_VERSION); - -module_init(cmd64x_init); -module_exit(cmd64x_exit); diff --git a/trunk/drivers/ata/pata_cs5520.c b/trunk/drivers/ata/pata_cs5520.c deleted file mode 100644 index 792ce4828510..000000000000 --- a/trunk/drivers/ata/pata_cs5520.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * IDE tuning and bus mastering support for the CS5510/CS5520 - * chipsets - * - * The CS5510/CS5520 are slightly unusual devices. Unlike the - * typical IDE controllers they do bus mastering with the drive in - * PIO mode and smarter silicon. - * - * The practical upshot of this is that we must always tune the - * drive for the right PIO mode. We must also ignore all the blacklists - * and the drive bus mastering DMA information. Also to confuse matters - * further we can do DMA on PIO only drives. - * - * DMA on the 5510 also requires we disable_hlt() during DMA on early - * revisions. - * - * *** This driver is strictly experimental *** - * - * (c) Copyright Red Hat Inc 2002 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Documentation: - * Not publically available. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_cs5520" -#define DRV_VERSION "0.6.2" - -struct pio_clocks -{ - int address; - int assert; - int recovery; -}; - -static const struct pio_clocks cs5520_pio_clocks[]={ - {3, 6, 11}, - {2, 5, 6}, - {1, 4, 3}, - {1, 3, 2}, - {1, 2, 1} -}; - -/** - * cs5520_set_timings - program PIO timings - * @ap: ATA port - * @adev: ATA device - * - * Program the PIO mode timings for the controller according to the pio - * clocking table. - */ - -static void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int slave = adev->devno; - - pio -= XFER_PIO_0; - - /* Channel command timing */ - pci_write_config_byte(pdev, 0x62 + ap->port_no, - (cs5520_pio_clocks[pio].recovery << 4) | - (cs5520_pio_clocks[pio].assert)); - /* FIXME: should these use address ? */ - /* Read command timing */ - pci_write_config_byte(pdev, 0x64 + 4*ap->port_no + slave, - (cs5520_pio_clocks[pio].recovery << 4) | - (cs5520_pio_clocks[pio].assert)); - /* Write command timing */ - pci_write_config_byte(pdev, 0x66 + 4*ap->port_no + slave, - (cs5520_pio_clocks[pio].recovery << 4) | - (cs5520_pio_clocks[pio].assert)); -} - -/** - * cs5520_enable_dma - turn on DMA bits - * - * Turn on the DMA bits for this disk. Needed because the BIOS probably - * has not done the work for us. Belongs in the core SATA code. - */ - -static void cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev) -{ - /* Set the DMA enable/disable flag */ - u8 reg = inb(ap->ioaddr.bmdma_addr + 0x02); - reg |= 1<<(adev->devno + 5); - outb(reg, ap->ioaddr.bmdma_addr + 0x02); -} - -/** - * cs5520_set_dmamode - program DMA timings - * @ap: ATA port - * @adev: ATA device - * - * Program the DMA mode timings for the controller according to the pio - * clocking table. Note that this device sets the DMA timings to PIO - * mode values. This may seem bizarre but the 5520 architecture talks - * PIO mode to the disk and DMA mode to the controller so the underlying - * transfers are PIO timed. - */ - -static void cs5520_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const int dma_xlate[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 }; - cs5520_set_timings(ap, adev, dma_xlate[adev->dma_mode]); - cs5520_enable_dma(ap, adev); -} - -/** - * cs5520_set_piomode - program PIO timings - * @ap: ATA port - * @adev: ATA device - * - * Program the PIO mode timings for the controller according to the pio - * clocking table. We know pio_mode will equal dma_mode because of the - * CS5520 architecture. At least once we turned DMA on and wrote a - * mode setter. - */ - -static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - cs5520_set_timings(ap, adev, adev->pio_mode); -} - - -static int cs5520_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static void cs5520_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, cs5520_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -static struct scsi_host_template cs5520_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cs5520_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cs5520_set_piomode, - .set_dmamode = cs5520_set_dmamode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cs5520_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - u8 pcicfg; - static struct ata_probe_ent probe[2]; - int ports = 0; - - /* IDE port enable bits */ - pci_read_config_byte(dev, 0x60, &pcicfg); - - /* Check if the ATA ports are enabled */ - if ((pcicfg & 3) == 0) - return -ENODEV; - - if ((pcicfg & 0x40) == 0) { - printk(KERN_WARNING DRV_NAME ": DMA mode disabled. Enabling.\n"); - pci_write_config_byte(dev, 0x60, pcicfg | 0x40); - } - - /* Perform set up for DMA */ - if (pci_enable_device_bars(dev, 1<<2)) { - printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n"); - return -ENODEV; - } - pci_set_master(dev); - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n"); - return -ENODEV; - } - if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n"); - return -ENODEV; - } - - /* We have to do our own plumbing as the PCI setup for this - chipset is non-standard so we can't punt to the libata code */ - - INIT_LIST_HEAD(&probe[0].node); - probe[0].dev = pci_dev_to_dev(dev); - probe[0].port_ops = &cs5520_port_ops; - probe[0].sht = &cs5520_sht; - probe[0].pio_mask = 0x1F; - probe[0].mwdma_mask = id->driver_data; - probe[0].irq = 14; - probe[0].irq_flags = 0; - probe[0].port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST; - probe[0].n_ports = 1; - probe[0].port[0].cmd_addr = 0x1F0; - probe[0].port[0].ctl_addr = 0x3F6; - probe[0].port[0].altstatus_addr = 0x3F6; - probe[0].port[0].bmdma_addr = pci_resource_start(dev, 2); - - /* The secondary lurks at different addresses but is otherwise - the same beastie */ - - probe[1] = probe[0]; - INIT_LIST_HEAD(&probe[1].node); - probe[1].irq = 15; - probe[1].port[0].cmd_addr = 0x170; - probe[1].port[0].ctl_addr = 0x376; - probe[1].port[0].altstatus_addr = 0x376; - probe[1].port[0].bmdma_addr = pci_resource_start(dev, 2) + 8; - - /* Let libata fill in the port details */ - ata_std_ports(&probe[0].port[0]); - ata_std_ports(&probe[1].port[0]); - - /* Now add the ports that are active */ - if (pcicfg & 1) - ports += ata_device_add(&probe[0]); - if (pcicfg & 2) - ports += ata_device_add(&probe[1]); - if (ports) - return 0; - return -ENODEV; -} - -/** - * cs5520_remove_one - device unload - * @pdev: PCI device being removed - * - * Handle an unplug/unload event for a PCI device. Unload the - * PCI driver but do not use the default handler as we manage - * resources ourself and *MUST NOT* disable the device as it has - * other functions. - */ - -static void __devexit cs5520_remove_one(struct pci_dev *pdev) -{ - struct device *dev = pci_dev_to_dev(pdev); - struct ata_host *host = dev_get_drvdata(dev); - - ata_host_remove(host); - dev_set_drvdata(dev, NULL); -} - -/* For now keep DMA off. We can set it for all but A rev CS5510 once the - core ATA code can handle it */ - -static struct pci_device_id pata_cs5520[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, - { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520), }, - { 0, }, -}; - -static struct pci_driver cs5520_pci_driver = { - .name = DRV_NAME, - .id_table = pata_cs5520, - .probe = cs5520_init_one, - .remove = cs5520_remove_one -}; - - -static int __init cs5520_init(void) -{ - return pci_register_driver(&cs5520_pci_driver); -} - -static void __exit cs5520_exit(void) -{ - pci_unregister_driver(&cs5520_pci_driver); -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pata_cs5520); -MODULE_VERSION(DRV_VERSION); - -module_init(cs5520_init); -module_exit(cs5520_exit); - diff --git a/trunk/drivers/ata/pata_cs5530.c b/trunk/drivers/ata/pata_cs5530.c deleted file mode 100644 index f3d8a3bc1e78..000000000000 --- a/trunk/drivers/ata/pata_cs5530.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * pata-cs5530.c - CS5530 PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based upon cs5530.c by Mark Lord. - * - * 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 program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Loosely based on the piix & svwks drivers. - * - * Documentation: - * Available from AMD web site. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_cs5530" -#define DRV_VERSION "0.6" - -/** - * cs5530_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Set our PIO requirements. This is fairly simple on the CS5530 - * chips. - */ - -static void cs5530_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static const unsigned int cs5530_pio_timings[2][5] = { - {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010} - }; - unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no; - u32 tuning; - int format; - - /* Find out which table to use */ - tuning = inl(base + 0x04); - format = (tuning & 0x80000000UL) ? 1 : 0; - - /* Now load the right timing register */ - if (adev->devno) - base += 0x08; - - outl(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base); -} - -/** - * cs5530_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * We cannot mix MWDMA and UDMA without reloading timings each switch - * master to slave. We track the last DMA setup in order to minimise - * reloads. - */ - -static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no; - u32 tuning, timing = 0; - u8 reg; - - /* Find out which table to use */ - tuning = inl(base + 0x04); - - switch(adev->dma_mode) { - case XFER_UDMA_0: - timing = 0x00921250;break; - case XFER_UDMA_1: - timing = 0x00911140;break; - case XFER_UDMA_2: - timing = 0x00911030;break; - case XFER_MW_DMA_0: - timing = 0x00077771;break; - case XFER_MW_DMA_1: - timing = 0x00012121;break; - case XFER_MW_DMA_2: - timing = 0x00002020;break; - default: - BUG(); - } - /* Merge in the PIO format bit */ - timing |= (tuning & 0x80000000UL); - if (adev->devno == 0) /* Master */ - outl(timing, base + 0x04); - else { - if (timing & 0x00100000) - tuning |= 0x00100000; /* UDMA for both */ - else - tuning &= ~0x00100000; /* MWDMA for both */ - outl(tuning, base + 0x04); - outl(timing, base + 0x0C); - } - - /* Set the DMA capable bit in the BMDMA area */ - reg = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - reg |= (1 << (5 + adev->devno)); - outb(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - - /* Remember the last DMA setup we did */ - - ap->private_data = adev; -} - -/** - * cs5530_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. Specifically we have a problem that there is only - * one MWDMA/UDMA bit. - */ - -static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct ata_device *prev = ap->private_data; - - /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { - /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) - /* Switch the mode bits */ - cs5530_set_dmamode(ap, adev); - } - - return ata_qc_issue_prot(qc); -} - -static int cs5530_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static void cs5530_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, cs5530_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - - -static struct scsi_host_template cs5530_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cs5530_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cs5530_set_piomode, - .set_dmamode = cs5530_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cs5530_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = cs5530_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct dmi_system_id palmax_dmi_table[] = { - { - .ident = "Palmax PD1100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Cyrix"), - DMI_MATCH(DMI_PRODUCT_NAME, "Caddis"), - }, - }, - { } -}; - -static int cs5530_is_palmax(void) -{ - if (dmi_check_system(palmax_dmi_table)) { - printk(KERN_INFO "Palmax PD1100: Disabling DMA on docking port.\n"); - return 1; - } - return 0; -} - -/** - * cs5530_init_one - Initialise a CS5530 - * @dev: PCI device - * @id: Entry in match table - * - * Install a driver for the newly found CS5530 companion chip. Most of - * this is just housekeeping. We have to set the chip up correctly and - * turn off various bits of emulation magic. - */ - -static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - int compiler_warning_pointless_fix; - struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; - static struct ata_port_info info = { - .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &cs5530_port_ops - }; - /* The docking connector doesn't do UDMA, and it seems not MWDMA */ - static struct ata_port_info info_palmax_secondary = { - .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &cs5530_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - dev = NULL; - while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { - switch (dev->device) { - case PCI_DEVICE_ID_CYRIX_PCI_MASTER: - master_0 = pci_dev_get(dev); - break; - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - cs5530_0 = pci_dev_get(dev); - break; - } - } - if (!master_0) { - printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n"); - goto fail_put; - } - if (!cs5530_0) { - printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n"); - goto fail_put; - } - - pci_set_master(cs5530_0); - compiler_warning_pointless_fix = pci_set_mwi(cs5530_0); - - /* - * Set PCI CacheLineSize to 16-bytes: - * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 - * - * Note: This value is constant because the 5530 is only a Geode companion - */ - - pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); - - /* - * Disable trapping of UDMA register accesses (Win98 hack): - * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 - */ - - pci_write_config_word(cs5530_0, 0xd0, 0x5006); - - /* - * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: - * The other settings are what is necessary to get the register - * into a sane state for IDE DMA operation. - */ - - pci_write_config_byte(master_0, 0x40, 0x1e); - - /* - * Set max PCI burst size (16-bytes seems to work best): - * 16bytes: set bit-1 at 0x41 (reg value of 0x16) - * all others: clear bit-1 at 0x41, and do: - * 128bytes: OR 0x00 at 0x41 - * 256bytes: OR 0x04 at 0x41 - * 512bytes: OR 0x08 at 0x41 - * 1024bytes: OR 0x0c at 0x41 - */ - - pci_write_config_byte(master_0, 0x41, 0x14); - - /* - * These settings are necessary to get the chip - * into a sane state for IDE DMA operation. - */ - - pci_write_config_byte(master_0, 0x42, 0x00); - pci_write_config_byte(master_0, 0x43, 0xc1); - - pci_dev_put(master_0); - pci_dev_put(cs5530_0); - - if (cs5530_is_palmax()) - port_info[1] = &info_palmax_secondary; - - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); - -fail_put: - if (master_0) - pci_dev_put(master_0); - if (cs5530_0) - pci_dev_put(cs5530_0); - return -ENODEV; -} - -static struct pci_device_id cs5530[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, - { 0, }, -}; - -static struct pci_driver cs5530_pci_driver = { - .name = DRV_NAME, - .id_table = cs5530, - .probe = cs5530_init_one, - .remove = ata_pci_remove_one -}; - -static int __init cs5530_init(void) -{ - return pci_register_driver(&cs5530_pci_driver); -} - - -static void __exit cs5530_exit(void) -{ - pci_unregister_driver(&cs5530_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, cs5530); -MODULE_VERSION(DRV_VERSION); - -module_init(cs5530_init); -module_exit(cs5530_exit); diff --git a/trunk/drivers/ata/pata_cs5535.c b/trunk/drivers/ata/pata_cs5535.c deleted file mode 100644 index 69d6b4258724..000000000000 --- a/trunk/drivers/ata/pata_cs5535.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * pata-cs5535.c - CS5535 PATA for new ATA layer - * (C) 2005-2006 Red Hat Inc - * Alan Cox - * - * based upon cs5535.c from AMD as cleaned up and - * made readable and Linux style by Wolfgang Zuleger - * - * 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 program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Loosely based on the piix & svwks drivers. - * - * Documentation: - * Available from AMD web site. - * TODO - * Review errata to see if serializing is neccessary - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "cs5535" -#define DRV_VERSION "0.2.10" - -/* - * The Geode (Aka Athlon GX now) uses an internal MSR based - * bus system for control. Demented but there you go. - */ - -#define MSR_ATAC_BASE 0x51300000 -#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0) -#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01) -#define ATAC_GLD_MSR_SMI (MSR_ATAC_BASE+0x02) -#define ATAC_GLD_MSR_ERROR (MSR_ATAC_BASE+0x03) -#define ATAC_GLD_MSR_PM (MSR_ATAC_BASE+0x04) -#define ATAC_GLD_MSR_DIAG (MSR_ATAC_BASE+0x05) -#define ATAC_IO_BAR (MSR_ATAC_BASE+0x08) -#define ATAC_RESET (MSR_ATAC_BASE+0x10) -#define ATAC_CH0D0_PIO (MSR_ATAC_BASE+0x20) -#define ATAC_CH0D0_DMA (MSR_ATAC_BASE+0x21) -#define ATAC_CH0D1_PIO (MSR_ATAC_BASE+0x22) -#define ATAC_CH0D1_DMA (MSR_ATAC_BASE+0x23) -#define ATAC_PCI_ABRTERR (MSR_ATAC_BASE+0x24) - -#define ATAC_BM0_CMD_PRIM 0x00 -#define ATAC_BM0_STS_PRIM 0x02 -#define ATAC_BM0_PRD 0x04 - -#define CS5535_CABLE_DETECT 0x48 - -#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 ) - -/** - * cs5535_pre_reset - detect cable type - * @ap: Port to detect on - * - * Perform cable detection for ATA66 capable cable. Return a libata - * cable type. - */ - -static int cs5535_pre_reset(struct ata_port *ap) -{ - u8 cable; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, CS5535_CABLE_DETECT, &cable); - if (cable & 1) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * cs5535_error_handler - reset/probe - * @ap: Port to reset - * - * Reset and configure a port - */ - -static void cs5535_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, cs5535_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * cs5535_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Set our PIO requirements. The CS5535 is pretty clean about all this - */ - -static void cs5535_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static const u16 pio_timings[5] = { - 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 - }; - static const u16 pio_cmd_timings[5] = { - 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 - }; - u32 reg, dummy; - struct ata_device *pair = ata_dev_pair(adev); - - int mode = adev->pio_mode - XFER_PIO_0; - int cmdmode = mode; - - /* Command timing has to be for the lowest of the pair of devices */ - if (pair) { - int pairmode = pair->pio_mode - XFER_PIO_0; - cmdmode = min(mode, pairmode); - /* Write the other drive timing register if it changed */ - if (cmdmode < pairmode) - wrmsr(ATAC_CH0D0_PIO + 2 * pair->devno, - pio_cmd_timings[cmdmode] << 16 | pio_timings[pairmode], 0); - } - /* Write the drive timing register */ - wrmsr(ATAC_CH0D0_PIO + 2 * adev->devno, - pio_cmd_timings[cmdmode] << 16 | pio_timings[mode], 0); - - /* Set the PIO "format 1" bit in the DMA timing register */ - rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy); - wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg | 0x80000000UL, 0); -} - -/** - * cs5535_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - */ - -static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u32 udma_timings[5] = { - 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 - }; - static const u32 mwdma_timings[3] = { - 0x7F0FFFF3, 0x7F035352, 0x7F024241 - }; - u32 reg, dummy; - int mode = adev->dma_mode; - - rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy); - reg &= 0x80000000UL; - if (mode >= XFER_UDMA_0) - reg |= udma_timings[mode - XFER_UDMA_0]; - else - reg |= mwdma_timings[mode - XFER_MW_DMA_0]; - wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, 0); -} - -static struct scsi_host_template cs5535_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cs5535_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cs5535_set_piomode, - .set_dmamode = cs5535_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cs5535_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * cs5535_init_one - Initialise a CS5530 - * @dev: PCI device - * @id: Entry in match table - * - * Install a driver for the newly found CS5530 companion chip. Most of - * this is just housekeeping. We have to set the chip up correctly and - * turn off various bits of emulation magic. - */ - -static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &cs5535_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, - .port_ops = &cs5535_port_ops - }; - struct ata_port_info *ports[1] = { &info }; - - u32 timings, dummy; - - /* Check the BIOS set the initial timing clock. If not set the - timings for PIO0 */ - rdmsr(ATAC_CH0D0_PIO, timings, dummy); - if (CS5535_BAD_PIO(timings)) - wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0); - rdmsr(ATAC_CH0D1_PIO, timings, dummy); - if (CS5535_BAD_PIO(timings)) - wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); - return ata_pci_init_one(dev, ports, 1); -} - -static struct pci_device_id cs5535[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, 0x002D), }, - { 0, }, -}; - -static struct pci_driver cs5535_pci_driver = { - .name = DRV_NAME, - .id_table = cs5535, - .probe = cs5535_init_one, - .remove = ata_pci_remove_one -}; - -static int __init cs5535_init(void) -{ - return pci_register_driver(&cs5535_pci_driver); -} - - -static void __exit cs5535_exit(void) -{ - pci_unregister_driver(&cs5535_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch"); -MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, cs5535); -MODULE_VERSION(DRV_VERSION); - -module_init(cs5535_init); -module_exit(cs5535_exit); diff --git a/trunk/drivers/ata/pata_cypress.c b/trunk/drivers/ata/pata_cypress.c deleted file mode 100644 index fd55474e0d15..000000000000 --- a/trunk/drivers/ata/pata_cypress.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * pata_cypress.c - Cypress PATA for new ATA layer - * (C) 2006 Red Hat Inc - * Alan Cox - * - * Based heavily on - * linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_cypress" -#define DRV_VERSION "0.1.2" - -/* here are the offset definitions for the registers */ - -enum { - CY82_IDE_CMDREG = 0x04, - CY82_IDE_ADDRSETUP = 0x48, - CY82_IDE_MASTER_IOR = 0x4C, - CY82_IDE_MASTER_IOW = 0x4D, - CY82_IDE_SLAVE_IOR = 0x4E, - CY82_IDE_SLAVE_IOW = 0x4F, - CY82_IDE_MASTER_8BIT = 0x50, - CY82_IDE_SLAVE_8BIT = 0x51, - - CY82_INDEX_PORT = 0x22, - CY82_DATA_PORT = 0x23, - - CY82_INDEX_CTRLREG1 = 0x01, - CY82_INDEX_CHANNEL0 = 0x30, - CY82_INDEX_CHANNEL1 = 0x31, - CY82_INDEX_TIMEOUT = 0x32 -}; - -static int cy82c693_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static void cy82c693_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, cy82c693_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * cy82c693_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. - */ - -static void cy82c693_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_timing t; - const unsigned long T = 1000000 / 33; - short time_16, time_8; - u32 addr; - - if (ata_timing_compute(adev, adev->pio_mode, &t, T, 1) < 0) { - printk(KERN_ERR DRV_NAME ": mome computation failed.\n"); - return; - } - - time_16 = FIT(t.recover, 0, 15) | (FIT(t.active, 0, 15) << 4); - time_8 = FIT(t.act8b, 0, 15) | (FIT(t.rec8b, 0, 15) << 4); - - if (adev->devno == 0) { - pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr); - - addr &= ~0x0F; /* Mask bits */ - addr |= FIT(t.setup, 0, 15); - - pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr); - pci_write_config_byte(pdev, CY82_IDE_MASTER_IOR, time_16); - pci_write_config_byte(pdev, CY82_IDE_MASTER_IOW, time_16); - pci_write_config_byte(pdev, CY82_IDE_MASTER_8BIT, time_8); - } else { - pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr); - - addr &= ~0xF0; /* Mask bits */ - addr |= (FIT(t.setup, 0, 15) << 4); - - pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr); - pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOR, time_16); - pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOW, time_16); - pci_write_config_byte(pdev, CY82_IDE_SLAVE_8BIT, time_8); - } -} - -/** - * cy82c693_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the DMA mode setup. - */ - -static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - int reg = CY82_INDEX_CHANNEL0 + ap->port_no; - - /* Be afraid, be very afraid. Magic registers in low I/O space */ - outb(reg, 0x22); - outb(adev->dma_mode - XFER_MW_DMA_0, 0x23); - - /* 0x50 gives the best behaviour on the Alpha's using this chip */ - outb(CY82_INDEX_TIMEOUT, 0x22); - outb(0x50, 0x23); -} - -static struct scsi_host_template cy82c693_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cy82c693_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cy82c693_set_piomode, - .set_dmamode = cy82c693_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = cy82c693_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &cy82c693_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &cy82c693_port_ops - }; - static struct ata_port_info *port_info[1] = { &info }; - - /* Devfn 1 is the ATA primary. The secondary is magic and on devfn2. For the - moment we don't handle the secondary. FIXME */ - - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - return ata_pci_init_one(pdev, port_info, 1); -} - -static struct pci_device_id cy82c693[] = { - { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0, }, -}; - -static struct pci_driver cy82c693_pci_driver = { - .name = DRV_NAME, - .id_table = cy82c693, - .probe = cy82c693_init_one, - .remove = ata_pci_remove_one -}; - -static int __init cy82c693_init(void) -{ - return pci_register_driver(&cy82c693_pci_driver); -} - - -static void __exit cy82c693_exit(void) -{ - pci_unregister_driver(&cy82c693_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the CY82C693 PATA controller"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, cy82c693); -MODULE_VERSION(DRV_VERSION); - -module_init(cy82c693_init); -module_exit(cy82c693_exit); diff --git a/trunk/drivers/ata/pata_efar.c b/trunk/drivers/ata/pata_efar.c deleted file mode 100644 index c30bc181304f..000000000000 --- a/trunk/drivers/ata/pata_efar.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * pata_efar.c - EFAR PIIX clone controller driver - * - * (C) 2005 Red Hat - * - * Some parts based on ata_piix.c by Jeff Garzik and others. - * - * The EFAR is a PIIX4 clone with UDMA66 support. Unlike the later - * Intel ICH controllers the EFAR widened the UDMA mode register bits - * and doesn't require the funky clock selection. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_efar" -#define DRV_VERSION "0.4.1" - -/** - * efar_pre_reset - check for 40/80 pin - * @ap: Port - * - * Perform cable detection for the EFAR ATA interface. This is - * different to the PIIX arrangement - */ - -static int efar_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits efar_enable_bits[] = { - { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ - { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 tmp; - - if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - pci_read_config_byte(pdev, 0x47, &tmp); - if (tmp & (2 >> ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -/** - * efar_probe_reset - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void efar_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * efar_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set PIO mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *dev = to_pci_dev(ap->host->dev); - unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; - u16 idetm_data; - int control = 0; - - /* - * See Intel Document 298600-004 for the timing programing rules - * for PIIX/ICH. The EFAR is a clone so very similar - */ - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - if (pio > 2) - control |= 1; /* TIME1 enable */ - if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ - control |= 2; /* IE enable */ - /* Intel specifies that the PPE functionality is for disk only */ - if (adev->class == ATA_DEV_ATA) - control |= 4; /* PPE enable */ - - pci_read_config_word(dev, idetm_port, &idetm_data); - - /* Enable PPE, IE and TIME as appropriate */ - - if (adev->devno == 0) { - idetm_data &= 0xCCF0; - idetm_data |= control; - idetm_data |= (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } else { - int shift = 4 * ap->port_no; - u8 slave_data; - - idetm_data &= 0xCC0F; - idetm_data |= (control << 4); - - /* Slave timing in seperate register */ - pci_read_config_byte(dev, 0x44, &slave_data); - slave_data &= 0x0F << shift; - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift; - pci_write_config_byte(dev, 0x44, slave_data); - } - - idetm_data |= 0x4000; /* Ensure SITRE is enabled */ - pci_write_config_word(dev, idetm_port, idetm_data); -} - -/** - * efar_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *dev = to_pci_dev(ap->host->dev); - u8 master_port = ap->port_no ? 0x42 : 0x40; - u16 master_data; - u8 speed = adev->dma_mode; - int devid = adev->devno + 2 * ap->port_no; - u8 udma_enable; - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pci_read_config_word(dev, master_port, &master_data); - pci_read_config_byte(dev, 0x48, &udma_enable); - - if (speed >= XFER_UDMA_0) { - unsigned int udma = adev->dma_mode - XFER_UDMA_0; - u16 udma_timing; - - udma_enable |= (1 << devid); - - /* Load the UDMA mode number */ - pci_read_config_word(dev, 0x4A, &udma_timing); - udma_timing &= ~(7 << (4 * devid)); - udma_timing |= udma << (4 * devid); - pci_write_config_word(dev, 0x4A, udma_timing); - } else { - /* - * MWDMA is driven by the PIO timings. We must also enable - * IORDY unconditionally along with TIME1. PPE has already - * been set when the PIO timing was set. - */ - unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; - unsigned int control; - u8 slave_data; - const unsigned int needed_pio[3] = { - XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 - }; - int pio = needed_pio[mwdma] - XFER_PIO_0; - - control = 3; /* IORDY|TIME1 */ - - /* If the drive MWDMA is faster than it can do PIO then - we must force PIO into PIO0 */ - - if (adev->pio_mode < needed_pio[mwdma]) - /* Enable DMA timing only */ - control |= 8; /* PIO cycles in PIO0 */ - - if (adev->devno) { /* Slave */ - master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ - master_data |= control << 4; - pci_read_config_byte(dev, 0x44, &slave_data); - slave_data &= (0x0F + 0xE1 * ap->port_no); - /* Load the matching timing */ - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); - pci_write_config_byte(dev, 0x44, slave_data); - } else { /* Master */ - master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY - and master timing bits */ - master_data |= control; - master_data |= - (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } - udma_enable &= ~(1 << devid); - pci_write_config_word(dev, master_port, master_data); - } - pci_write_config_byte(dev, 0x48, udma_enable); -} - -static struct scsi_host_template efar_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations efar_ops = { - .port_disable = ata_port_disable, - .set_piomode = efar_set_piomode, - .set_dmamode = efar_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = efar_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * efar_init_one - Register EFAR ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in efar_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - static struct ata_port_info info = { - .sht = &efar_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x0f, /* UDMA 66 */ - .port_ops = &efar_ops, - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id efar_pci_tbl[] = { - { 0x1055, 0x9130, PCI_ANY_ID, PCI_ANY_ID, }, - { } /* terminate list */ -}; - -static struct pci_driver efar_pci_driver = { - .name = DRV_NAME, - .id_table = efar_pci_tbl, - .probe = efar_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init efar_init(void) -{ - return pci_register_driver(&efar_pci_driver); -} - -static void __exit efar_exit(void) -{ - pci_unregister_driver(&efar_pci_driver); -} - - -module_init(efar_init); -module_exit(efar_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for EFAR PIIX clones"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, efar_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_hpt366.c b/trunk/drivers/ata/pata_hpt366.c deleted file mode 100644 index 94bb1dfc3f19..000000000000 --- a/trunk/drivers/ata/pata_hpt366.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers. - * - * This driver is heavily based upon: - * - * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 - * - * Copyright (C) 1999-2003 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * Portions Copyright (C) 2003 Red Hat Inc - * - * - * TODO - * Maybe PLL mode - * Look into engine reset on timeout errors. Should not be - * required. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.5" - -struct hpt_clock { - u8 xfer_speed; - u32 timing; -}; - -/* key for bus clock timings - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. - */ - -static const struct hpt_clock hpt366_40[] = { - { XFER_UDMA_4, 0x900fd943 }, - { XFER_UDMA_3, 0x900ad943 }, - { XFER_UDMA_2, 0x900bd943 }, - { XFER_UDMA_1, 0x9008d943 }, - { XFER_UDMA_0, 0x9008d943 }, - - { XFER_MW_DMA_2, 0xa008d943 }, - { XFER_MW_DMA_1, 0xa010d955 }, - { XFER_MW_DMA_0, 0xa010d9fc }, - - { XFER_PIO_4, 0xc008d963 }, - { XFER_PIO_3, 0xc010d974 }, - { XFER_PIO_2, 0xc010d997 }, - { XFER_PIO_1, 0xc010d9c7 }, - { XFER_PIO_0, 0xc018d9d9 }, - { 0, 0x0120d9d9 } -}; - -static const struct hpt_clock hpt366_33[] = { - { XFER_UDMA_4, 0x90c9a731 }, - { XFER_UDMA_3, 0x90cfa731 }, - { XFER_UDMA_2, 0x90caa731 }, - { XFER_UDMA_1, 0x90cba731 }, - { XFER_UDMA_0, 0x90c8a731 }, - - { XFER_MW_DMA_2, 0xa0c8a731 }, - { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ - { XFER_MW_DMA_0, 0xa0c8a797 }, - - { XFER_PIO_4, 0xc0c8a731 }, - { XFER_PIO_3, 0xc0c8a742 }, - { XFER_PIO_2, 0xc0d0a753 }, - { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ - { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ - { 0, 0x0120a7a7 } -}; - -static const struct hpt_clock hpt366_25[] = { - { XFER_UDMA_4, 0x90c98521 }, - { XFER_UDMA_3, 0x90cf8521 }, - { XFER_UDMA_2, 0x90cf8521 }, - { XFER_UDMA_1, 0x90cb8521 }, - { XFER_UDMA_0, 0x90cb8521 }, - - { XFER_MW_DMA_2, 0xa0ca8521 }, - { XFER_MW_DMA_1, 0xa0ca8532 }, - { XFER_MW_DMA_0, 0xa0ca8575 }, - - { XFER_PIO_4, 0xc0ca8521 }, - { XFER_PIO_3, 0xc0ca8532 }, - { XFER_PIO_2, 0xc0ca8542 }, - { XFER_PIO_1, 0xc0d08572 }, - { XFER_PIO_0, 0xc0d08585 }, - { 0, 0x01208585 } -}; - -static const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -static const char *bad_ata66_4[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -static const char *bad_ata66_3[] = { - "WDC AC310200R", - NULL -}; - -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) -{ - unsigned char model_num[40]; - char *s; - unsigned int len; - int i = 0; - - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - while(list[i] != NULL) { - if (!strncmp(list[i], s, len)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); - return 1; - } - i++; - } - return 0; -} - -/** - * hpt366_filter - mode selection filter - * @ap: ATA interface - * @adev: ATA device - * - * Block UDMA on devices that cause trouble with this controller. - */ - -static unsigned long hpt366_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - if (adev->class == ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) - mask &= ~ATA_MASK_UDMA; - if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3)) - mask &= ~(0x07 << ATA_SHIFT_UDMA); - if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) - mask &= ~(0x0F << ATA_SHIFT_UDMA); - } - return ata_pci_default_filter(ap, adev, mask); -} - -/** - * hpt36x_find_mode - reset the hpt36x bus - * @ap: ATA port - * @speed: transfer mode - * - * Return the 32bit register programming information for this channel - * that matches the speed provided. - */ - -static u32 hpt36x_find_mode(struct ata_port *ap, int speed) -{ - struct hpt_clock *clocks = ap->host->private_data; - - while(clocks->xfer_speed) { - if (clocks->xfer_speed == speed) - return clocks->timing; - clocks++; - } - BUG(); - return 0xffffffffU; /* silence compiler warning */ -} - -static int hpt36x_pre_reset(struct ata_port *ap) -{ - u8 ata66; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, 0x5A, &ata66); - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -/** - * hpt36x_error_handler - reset the hpt36x bus - * @ap: ATA port to reset - * - * Perform the reset handling for the 366/368 - */ - -static void hpt36x_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * hpt366_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ - -static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - if (fast & 0x80) { - fast &= ~0x80; - pci_write_config_byte(pdev, addr2, fast); - } - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt36x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt366_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. - */ - -static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - if (fast & 0x80) { - fast &= ~0x80; - pci_write_config_byte(pdev, addr2, fast); - } - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt36x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -static struct scsi_host_template hpt36x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -/* - * Configuration for HPT366/68 - */ - -static struct ata_port_operations hpt366_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt366_set_piomode, - .set_dmamode = hpt366_set_dmamode, - .mode_filter = hpt366_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt36x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * hpt36x_init_one - Initialise an HPT366/368 - * @dev: PCI device - * @id: Entry in match table - * - * Initialise an HPT36x device. There are some interesting complications - * here. Firstly the chip may report 366 and be one of several variants. - * Secondly all the timings depend on the clock for the chip which we must - * detect and look up - * - * This is the known chip mappings. It may be missing a couple of later - * releases. - * - * Chip version PCI Rev Notes - * HPT366 4 (HPT366) 0 UDMA66 - * HPT366 4 (HPT366) 1 UDMA66 - * HPT368 4 (HPT366) 2 UDMA66 - * HPT37x/30x 4 (HPT366) 3+ Other driver - * - */ - -static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info_hpt366 = { - .sht = &hpt36x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, - .port_ops = &hpt366_port_ops - }; - struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366}; - - u32 class_rev; - u32 reg1; - u8 drive_fast; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; - - /* May be a later chip in disguise. Check */ - /* Newer chips are not in the HPT36x driver. Ignore them */ - if (class_rev > 2) - return -ENODEV; - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); - - pci_read_config_dword(dev, 0x40, ®1); - - /* PCI clocking determines the ATA timing values to use */ - /* info_hpt366 is safe against re-entry so we can scribble on it */ - switch(reg1 & 0x700) { - case 5: - info_hpt366.private_data = &hpt366_40; - break; - case 9: - info_hpt366.private_data = &hpt366_25; - break; - default: - info_hpt366.private_data = &hpt366_33; - break; - } - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id hpt36x[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, - { 0, }, -}; - -static struct pci_driver hpt36x_pci_driver = { - .name = DRV_NAME, - .id_table = hpt36x, - .probe = hpt36x_init_one, - .remove = ata_pci_remove_one -}; - -static int __init hpt36x_init(void) -{ - return pci_register_driver(&hpt36x_pci_driver); -} - - -static void __exit hpt36x_exit(void) -{ - pci_unregister_driver(&hpt36x_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, hpt36x); -MODULE_VERSION(DRV_VERSION); - -module_init(hpt36x_init); -module_exit(hpt36x_exit); diff --git a/trunk/drivers/ata/pata_hpt37x.c b/trunk/drivers/ata/pata_hpt37x.c deleted file mode 100644 index 532a7928f803..000000000000 --- a/trunk/drivers/ata/pata_hpt37x.c +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers. - * - * This driver is heavily based upon: - * - * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 - * - * Copyright (C) 1999-2003 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * Portions Copyright (C) 2003 Red Hat Inc - * - * TODO - * PLL mode - * Look into engine reset on timeout errors. Should not be - * required. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.5" - -struct hpt_clock { - u8 xfer_speed; - u32 timing; -}; - -struct hpt_chip { - const char *name; - unsigned int base; - struct hpt_clock const *clocks[4]; -}; - -/* key for bus clock timings - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. - */ - -/* from highpoint documentation. these are old values */ -static const struct hpt_clock hpt370_timings_33[] = { -/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ - { XFER_UDMA_5, 0x16454e31 }, - { XFER_UDMA_4, 0x16454e31 }, - { XFER_UDMA_3, 0x166d4e31 }, - { XFER_UDMA_2, 0x16494e31 }, - { XFER_UDMA_1, 0x164d4e31 }, - { XFER_UDMA_0, 0x16514e31 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - -static const struct hpt_clock hpt370_timings_66[] = { - { XFER_UDMA_5, 0x14846231 }, - { XFER_UDMA_4, 0x14886231 }, - { XFER_UDMA_3, 0x148c6231 }, - { XFER_UDMA_2, 0x148c6231 }, - { XFER_UDMA_1, 0x14906231 }, - { XFER_UDMA_0, 0x14986231 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - -/* these are the current (4 sep 2001) timings from highpoint */ -static const struct hpt_clock hpt370a_timings_33[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } -}; - -/* 2x 33MHz timings */ -static const struct hpt_clock hpt370a_timings_66[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; - -static const struct hpt_clock hpt370a_timings_50[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0ac1f48a } -}; - -static const struct hpt_clock hpt372_timings_33[] = { - { XFER_UDMA_6, 0x1c81dc62 }, - { XFER_UDMA_5, 0x1c6ddc62 }, - { XFER_UDMA_4, 0x1c8ddc62 }, - { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ - { XFER_UDMA_2, 0x1c91dc62 }, - { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ - { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ - - { XFER_MW_DMA_2, 0x2c829262 }, - { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ - { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d5e } -}; - -static const struct hpt_clock hpt372_timings_50[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0a81f443 } -}; - -static const struct hpt_clock hpt372_timings_66[] = { - { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1cae9c62 }, - { XFER_UDMA_4, 0x1c8a9c62 }, - { XFER_UDMA_3, 0x1c8e9c62 }, - { XFER_UDMA_2, 0x1c929c62 }, - { XFER_UDMA_1, 0x1c9a9c62 }, - { XFER_UDMA_0, 0x1c829c62 }, - - { XFER_MW_DMA_2, 0x2c829c62 }, - { XFER_MW_DMA_1, 0x2c829c66 }, - { XFER_MW_DMA_0, 0x2c829d2e }, - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d26 } -}; - -static const struct hpt_clock hpt374_timings_33[] = { - { XFER_UDMA_6, 0x12808242 }, - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x06814e93 } -}; - -static const struct hpt_chip hpt370 = { - "HPT370", - 48, - { - hpt370_timings_33, - NULL, - NULL, - hpt370_timings_66 - } -}; - -static const struct hpt_chip hpt370a = { - "HPT370A", - 48, - { - hpt370a_timings_33, - NULL, - hpt370a_timings_50, - hpt370a_timings_66 - } -}; - -static const struct hpt_chip hpt372 = { - "HPT372", - 55, - { - hpt372_timings_33, - NULL, - hpt372_timings_50, - hpt372_timings_66 - } -}; - -static const struct hpt_chip hpt302 = { - "HPT302", - 66, - { - hpt372_timings_33, - NULL, - hpt372_timings_50, - hpt372_timings_66 - } -}; - -static const struct hpt_chip hpt371 = { - "HPT371", - 66, - { - hpt372_timings_33, - NULL, - hpt372_timings_50, - hpt372_timings_66 - } -}; - -static const struct hpt_chip hpt372a = { - "HPT372A", - 66, - { - hpt372_timings_33, - NULL, - hpt372_timings_50, - hpt372_timings_66 - } -}; - -static const struct hpt_chip hpt374 = { - "HPT374", - 48, - { - hpt374_timings_33, - NULL, - NULL, - NULL - } -}; - -/** - * hpt37x_find_mode - reset the hpt37x bus - * @ap: ATA port - * @speed: transfer mode - * - * Return the 32bit register programming information for this channel - * that matches the speed provided. - */ - -static u32 hpt37x_find_mode(struct ata_port *ap, int speed) -{ - struct hpt_clock *clocks = ap->host->private_data; - - while(clocks->xfer_speed) { - if (clocks->xfer_speed == speed) - return clocks->timing; - clocks++; - } - BUG(); - return 0xffffffffU; /* silence compiler warning */ -} - -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) -{ - unsigned char model_num[40]; - char *s; - unsigned int len; - int i = 0; - - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - while(list[i] != NULL) { - if (!strncmp(list[i], s, len)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); - return 1; - } - i++; - } - return 0; -} - -static const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -static const char *bad_ata100_5[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -/** - * hpt370_filter - mode selection filter - * @ap: ATA interface - * @adev: ATA device - * - * Block UDMA on devices that cause trouble with this controller. - */ - -static unsigned long hpt370_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - if (adev->class != ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) - mask &= ~ATA_MASK_UDMA; - if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); - } - return ata_pci_default_filter(ap, adev, mask); -} - -/** - * hpt370a_filter - mode selection filter - * @ap: ATA interface - * @adev: ATA device - * - * Block UDMA on devices that cause trouble with this controller. - */ - -static unsigned long hpt370a_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - if (adev->class != ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~ (0x1F << ATA_SHIFT_UDMA); - } - return ata_pci_default_filter(ap, adev, mask); -} - -/** - * hpt37x_pre_reset - reset the hpt37x bus - * @ap: ATA port to reset - * - * Perform the initial reset handling for the 370/372 and 374 func 0 - */ - -static int hpt37x_pre_reset(struct ata_port *ap) -{ - u8 scr2, ata66; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, 0x5B, &scr2); - pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); - /* Cable register now active */ - pci_read_config_byte(pdev, 0x5A, &ata66); - /* Restore state */ - pci_write_config_byte(pdev, 0x5B, scr2); - - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50, 0x37); - pci_write_config_byte(pdev, 0x54, 0x37); - udelay(100); - - return ata_std_prereset(ap); -} - -/** - * hpt37x_error_handler - reset the hpt374 - * @ap: ATA port to reset - * - * Perform probe for HPT37x, except for HPT374 channel 2 - */ - -static void hpt37x_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -static int hpt374_pre_reset(struct ata_port *ap) -{ - u16 mcr3, mcr6; - u8 ata66; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - /* Do the extra channel work */ - pci_read_config_word(pdev, 0x52, &mcr3); - pci_read_config_word(pdev, 0x56, &mcr6); - /* Set bit 15 of 0x52 to enable TCBLID as input - Set bit 15 of 0x56 to enable FCBLID as input - */ - pci_write_config_word(pdev, 0x52, mcr3 | 0x8000); - pci_write_config_word(pdev, 0x56, mcr6 | 0x8000); - pci_read_config_byte(pdev, 0x5A, &ata66); - /* Reset TCBLID/FCBLID to output */ - pci_write_config_word(pdev, 0x52, mcr3); - pci_write_config_word(pdev, 0x56, mcr6); - - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50, 0x37); - pci_write_config_byte(pdev, 0x54, 0x37); - udelay(100); - - return ata_std_prereset(ap); -} - -/** - * hpt374_error_handler - reset the hpt374 - * @classes: - * - * The 374 cable detect is a little different due to the extra - * channels. The function 0 channels work like usual but function 1 - * is special - */ - -static void hpt374_error_handler(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!(PCI_FUNC(pdev->devfn) & 1)) - hpt37x_error_handler(ap); - else - ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * hpt370_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ - -static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x02; - fast |= 0x01; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt370_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. - */ - -static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x02; - fast |= 0x01; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt370_bmdma_start - DMA engine begin - * @qc: ATA command - * - * The 370 and 370A want us to reset the DMA engine each time we - * use it. The 372 and later are fine. - */ - -static void hpt370_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(10); - ata_bmdma_start(qc); -} - -/** - * hpt370_bmdma_end - DMA engine stop - * @qc: ATA command - * - * Work around the HPT370 DMA engine. - */ - -static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 dma_stat = inb(ap->ioaddr.bmdma_addr + 2); - u8 dma_cmd; - unsigned long bmdma = ap->ioaddr.bmdma_addr; - - if (dma_stat & 0x01) { - udelay(20); - dma_stat = inb(bmdma + 2); - } - if (dma_stat & 0x01) { - /* Clear the engine */ - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(10); - /* Stop DMA */ - dma_cmd = inb(bmdma ); - outb(dma_cmd & 0xFE, bmdma); - /* Clear Error */ - dma_stat = inb(bmdma + 2); - outb(dma_stat | 0x06 , bmdma + 2); - /* Clear the engine */ - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(10); - } - ata_bmdma_stop(qc); -} - -/** - * hpt372_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ - -static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x07; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->pio_mode); - - printk("Find mode for %d reports %X\n", adev->pio_mode, mode); - mode &= ~0x80000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt372_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. - */ - -static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x07; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->dma_mode); - printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); - mode &= ~0xC0000000; /* Leave config bits alone */ - mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt37x_bmdma_end - DMA engine stop - * @qc: ATA command - * - * Clean up after the HPT372 and later DMA engine - */ - -static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int mscreg = 0x50 + 2 * ap->port_no; - u8 bwsr_stat, msc_stat; - - pci_read_config_byte(pdev, 0x6A, &bwsr_stat); - pci_read_config_byte(pdev, mscreg, &msc_stat); - if (bwsr_stat & (1 << ap->port_no)) - pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); - ata_bmdma_stop(qc); -} - - -static struct scsi_host_template hpt37x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -/* - * Configuration for HPT370 - */ - -static struct ata_port_operations hpt370_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt370_set_piomode, - .set_dmamode = hpt370_set_dmamode, - .mode_filter = hpt370_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = hpt370_bmdma_start, - .bmdma_stop = hpt370_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Configuration for HPT370A. Close to 370 but less filters - */ - -static struct ata_port_operations hpt370a_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt370_set_piomode, - .set_dmamode = hpt370_set_dmamode, - .mode_filter = hpt370a_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = hpt370_bmdma_start, - .bmdma_stop = hpt370_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Configuration for HPT372, HPT371, HPT302. Slightly different PIO - * and DMA mode setting functionality. - */ - -static struct ata_port_operations hpt372_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt372_set_piomode, - .set_dmamode = hpt372_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = hpt37x_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Configuration for HPT374. Mode setting works like 372 and friends - * but we have a different cable detection procedure. - */ - -static struct ata_port_operations hpt374_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt372_set_piomode, - .set_dmamode = hpt372_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt374_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = hpt37x_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * htp37x_clock_slot - Turn timing to PC clock entry - * @freq: Reported frequency timing - * @base: Base timing - * - * Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50 - * and 3 for 66Mhz) - */ - -static int hpt37x_clock_slot(unsigned int freq, unsigned int base) -{ - unsigned int f = (base * freq) / 192; /* Mhz */ - if (f < 40) - return 0; /* 33Mhz slot */ - if (f < 45) - return 1; /* 40Mhz slot */ - if (f < 55) - return 2; /* 50Mhz slot */ - return 3; /* 60Mhz slot */ -} - -/** - * hpt37x_calibrate_dpll - Calibrate the DPLL loop - * @dev: PCI device - * - * Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this - * succeeds - */ - -static int hpt37x_calibrate_dpll(struct pci_dev *dev) -{ - u8 reg5b; - u32 reg5c; - int tries; - - for(tries = 0; tries < 0x5000; tries++) { - udelay(50); - pci_read_config_byte(dev, 0x5b, ®5b); - if (reg5b & 0x80) { - /* See if it stays set */ - for(tries = 0; tries < 0x1000; tries ++) { - pci_read_config_byte(dev, 0x5b, ®5b); - /* Failed ? */ - if ((reg5b & 0x80) == 0) - return 0; - } - /* Turn off tuning, we have the DPLL set */ - pci_read_config_dword(dev, 0x5c, ®5c); - pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); - return 1; - } - } - /* Never went stable */ - return 0; -} -/** - * hpt37x_init_one - Initialise an HPT37X/302 - * @dev: PCI device - * @id: Entry in match table - * - * Initialise an HPT37x device. There are some interesting complications - * here. Firstly the chip may report 366 and be one of several variants. - * Secondly all the timings depend on the clock for the chip which we must - * detect and look up - * - * This is the known chip mappings. It may be missing a couple of later - * releases. - * - * Chip version PCI Rev Notes - * HPT366 4 (HPT366) 0 Other driver - * HPT366 4 (HPT366) 1 Other driver - * HPT368 4 (HPT366) 2 Other driver - * HPT370 4 (HPT366) 3 UDMA100 - * HPT370A 4 (HPT366) 4 UDMA100 - * HPT372 4 (HPT366) 5 UDMA133 (1) - * HPT372N 4 (HPT366) 6 Other driver - * HPT372A 5 (HPT372) 1 UDMA133 (1) - * HPT372N 5 (HPT372) 2 Other driver - * HPT302 6 (HPT302) 1 UDMA133 - * HPT302N 6 (HPT302) 2 Other driver - * HPT371 7 (HPT371) * UDMA133 - * HPT374 8 (HPT374) * UDMA133 4 channel - * HPT372N 9 (HPT372N) * Other driver - * - * (1) UDMA133 support depends on the bus clock - */ - -static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - /* HPT370 - UDMA100 */ - static struct ata_port_info info_hpt370 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &hpt370_port_ops - }; - /* HPT370A - UDMA100 */ - static struct ata_port_info info_hpt370a = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &hpt370a_port_ops - }; - /* HPT371, 372 and friends - UDMA133 */ - static struct ata_port_info info_hpt372 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &hpt372_port_ops - }; - /* HPT371, 372 and friends - UDMA100 at 50MHz clock */ - static struct ata_port_info info_hpt372_50 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &hpt372_port_ops - }; - /* HPT374 - UDMA133 */ - static struct ata_port_info info_hpt374 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &hpt374_port_ops - }; - - static const int MHz[4] = { 33, 40, 50, 66 }; - - struct ata_port_info *port_info[2]; - struct ata_port_info *port; - - u8 irqmask; - u32 class_rev; - u32 freq; - - const struct hpt_chip *chip_table; - int clock_slot; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; - - if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { - /* May be a later chip in disguise. Check */ - /* Older chips are in the HPT366 driver. Ignore them */ - if (class_rev < 3) - return -ENODEV; - /* N series chips have their own driver. Ignore */ - if (class_rev == 6) - return -ENODEV; - - switch(class_rev) { - case 3: - port = &info_hpt370; - chip_table = &hpt370; - break; - case 4: - port = &info_hpt370a; - chip_table = &hpt370a; - break; - case 5: - port = &info_hpt372; - chip_table = &hpt372; - break; - default: - printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev); - return -ENODEV; - } - } else { - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT372: - /* 372N if rev >= 2*/ - if (class_rev >= 2) - return -ENODEV; - port = &info_hpt372; - chip_table = &hpt372a; - break; - case PCI_DEVICE_ID_TTI_HPT302: - /* 302N if rev > 1 */ - if (class_rev > 1) - return -ENODEV; - port = &info_hpt372; - /* Check this */ - chip_table = &hpt302; - break; - case PCI_DEVICE_ID_TTI_HPT371: - port = &info_hpt372; - chip_table = &hpt371; - break; - case PCI_DEVICE_ID_TTI_HPT374: - chip_table = &hpt374; - port = &info_hpt374; - break; - default: - printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); - return -ENODEV; - } - } - /* Ok so this is a chip we support */ - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - pci_read_config_byte(dev, 0x5A, &irqmask); - irqmask &= ~0x10; - pci_write_config_byte(dev, 0x5a, irqmask); - - /* - * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. Needed - * for some drives such as IBM-DTLA which will not enter ready - * state on reset when PDIAG is a input. - */ - - pci_write_config_byte(dev, 0x5b, 0x23); - - pci_read_config_dword(dev, 0x70, &freq); - if ((freq >> 12) != 0xABCDE) { - int i; - u8 sr; - u32 total = 0; - - printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n"); - - /* This is the process the HPT371 BIOS is reported to use */ - for(i = 0; i < 128; i++) { - pci_read_config_byte(dev, 0x78, &sr); - total += sr; - udelay(15); - } - freq = total / 128; - } - freq &= 0x1FF; - - /* - * Turn the frequency check into a band and then find a timing - * table to match it. - */ - - clock_slot = hpt37x_clock_slot(freq, chip_table->base); - if (chip_table->clocks[clock_slot] == NULL) { - /* - * We need to try PLL mode instead - */ - unsigned int f_low = (MHz[clock_slot] * chip_table->base) / 192; - unsigned int f_high = f_low + 2; - int adjust; - - for(adjust = 0; adjust < 8; adjust++) { - if (hpt37x_calibrate_dpll(dev)) - break; - /* See if it'll settle at a fractionally different clock */ - if ((adjust & 3) == 3) { - f_low --; - f_high ++; - } - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); - } - if (adjust == 8) { - printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n"); - return -ENODEV; - } - /* Check if this works for all cases */ - port->private_data = (void *)hpt370_timings_66; - - printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]); - } else { - port->private_data = (void *)chip_table->clocks[clock_slot]; - /* - * Perform a final fixup. The 371 and 372 clock determines - * if UDMA133 is available. - */ - - if (clock_slot == 2 && chip_table == &hpt372) { /* 50Mhz */ - printk(KERN_WARNING "pata_hpt37x: No UDMA133 support available with 50MHz bus clock.\n"); - if (port == &info_hpt372) - port = &info_hpt372_50; - else BUG(); - } - printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]); - } - port_info[0] = port_info[1] = port; - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id hpt37x[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), }, - { 0, }, -}; - -static struct pci_driver hpt37x_pci_driver = { - .name = DRV_NAME, - .id_table = hpt37x, - .probe = hpt37x_init_one, - .remove = ata_pci_remove_one -}; - -static int __init hpt37x_init(void) -{ - return pci_register_driver(&hpt37x_pci_driver); -} - - -static void __exit hpt37x_exit(void) -{ - pci_unregister_driver(&hpt37x_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, hpt37x); -MODULE_VERSION(DRV_VERSION); - -module_init(hpt37x_init); -module_exit(hpt37x_exit); diff --git a/trunk/drivers/ata/pata_hpt3x2n.c b/trunk/drivers/ata/pata_hpt3x2n.c deleted file mode 100644 index 06c8db079b91..000000000000 --- a/trunk/drivers/ata/pata_hpt3x2n.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers. - * - * This driver is heavily based upon: - * - * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 - * - * Copyright (C) 1999-2003 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * Portions Copyright (C) 2003 Red Hat Inc - * - * - * TODO - * 371N - * Work out best PLL policy - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3" - -enum { - HPT_PCI_FAST = (1 << 31), - PCI66 = (1 << 1), - USE_DPLL = (1 << 0) -}; - -struct hpt_clock { - u8 xfer_speed; - u32 timing; -}; - -struct hpt_chip { - const char *name; - struct hpt_clock *clocks[3]; -}; - -/* key for bus clock timings - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. - */ - -/* 66MHz DPLL clocks */ - -static struct hpt_clock hpt3x2n_clocks[] = { - { XFER_UDMA_7, 0x1c869c62 }, - { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1c8a9c62 }, - { XFER_UDMA_4, 0x1c8a9c62 }, - { XFER_UDMA_3, 0x1c8e9c62 }, - { XFER_UDMA_2, 0x1c929c62 }, - { XFER_UDMA_1, 0x1c9a9c62 }, - { XFER_UDMA_0, 0x1c829c62 }, - - { XFER_MW_DMA_2, 0x2c829c62 }, - { XFER_MW_DMA_1, 0x2c829c66 }, - { XFER_MW_DMA_0, 0x2c829d2c }, - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d5e } -}; - -/** - * hpt3x2n_find_mode - reset the hpt3x2n bus - * @ap: ATA port - * @speed: transfer mode - * - * Return the 32bit register programming information for this channel - * that matches the speed provided. For the moment the clocks table - * is hard coded but easy to change. This will be needed if we use - * different DPLLs - */ - -static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed) -{ - struct hpt_clock *clocks = hpt3x2n_clocks; - - while(clocks->xfer_speed) { - if (clocks->xfer_speed == speed) - return clocks->timing; - clocks++; - } - BUG(); - return 0xffffffffU; /* silence compiler warning */ -} - -/** - * hpt3x2n_pre_reset - reset the hpt3x2n bus - * @ap: ATA port to reset - * - * Perform the initial reset handling for the 3x2n series controllers. - * Reset the hardware and state machine, obtain the cable type. - */ - -static int hpt3xn_pre_reset(struct ata_port *ap) -{ - u8 scr2, ata66; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, 0x5B, &scr2); - pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); - /* Cable register now active */ - pci_read_config_byte(pdev, 0x5A, &ata66); - /* Restore state */ - pci_write_config_byte(pdev, 0x5B, scr2); - - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50, 0x37); - pci_write_config_byte(pdev, 0x54, 0x37); - udelay(100); - - return ata_std_prereset(ap); -} - -/** - * hpt3x2n_error_handler - probe the hpt3x2n bus - * @ap: ATA port to reset - * - * Perform the probe reset handling for the 3x2N - */ - -static void hpt3x2n_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * hpt3x2n_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ - -static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x07; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt3x2n_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt3x2n_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. - */ - -static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - fast &= ~0x07; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt3x2n_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); -} - -/** - * hpt3x2n_bmdma_end - DMA engine stop - * @qc: ATA command - * - * Clean up after the HPT3x2n and later DMA engine - */ - -static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int mscreg = 0x50 + 2 * ap->port_no; - u8 bwsr_stat, msc_stat; - - pci_read_config_byte(pdev, 0x6A, &bwsr_stat); - pci_read_config_byte(pdev, mscreg, &msc_stat); - if (bwsr_stat & (1 << ap->port_no)) - pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); - ata_bmdma_stop(qc); -} - -/** - * hpt3x2n_set_clock - clock control - * @ap: ATA port - * @source: 0x21 or 0x23 for PLL or PCI sourced clock - * - * Switch the ATA bus clock between the PLL and PCI clock sources - * while correctly isolating the bus and resetting internal logic - * - * We must use the DPLL for - * - writing - * - second channel UDMA7 (SATA ports) or higher - * - 66MHz PCI - * - * or we will underclock the device and get reduced performance. - */ - -static void hpt3x2n_set_clock(struct ata_port *ap, int source) -{ - unsigned long bmdma = ap->ioaddr.bmdma_addr; - - /* Tristate the bus */ - outb(0x80, bmdma+0x73); - outb(0x80, bmdma+0x77); - - /* Switch clock and reset channels */ - outb(source, bmdma+0x7B); - outb(0xC0, bmdma+0x79); - - /* Reset state machines */ - outb(0x37, bmdma+0x70); - outb(0x37, bmdma+0x74); - - /* Complete reset */ - outb(0x00, bmdma+0x79); - - /* Reconnect channels to bus */ - outb(0x00, bmdma+0x73); - outb(0x00, bmdma+0x77); -} - -/* Check if our partner interface is busy */ - -static int hpt3x2n_pair_idle(struct ata_port *ap) -{ - struct ata_host *host = ap->host; - struct ata_port *pair = host->ports[ap->port_no ^ 1]; - - if (pair->hsm_task_state == HSM_ST_IDLE) - return 1; - return 0; -} - -static int hpt3x2n_use_dpll(struct ata_port *ap, int reading) -{ - long flags = (long)ap->host->private_data; - /* See if we should use the DPLL */ - if (reading == 0) - return USE_DPLL; /* Needed for write */ - if (flags & PCI66) - return USE_DPLL; /* Needed at 66Mhz */ - return 0; -} - -static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_taskfile *tf = &qc->tf; - struct ata_port *ap = qc->ap; - int flags = (long)ap->host->private_data; - - if (hpt3x2n_pair_idle(ap)) { - int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE)); - if ((flags & USE_DPLL) != dpll) { - if (dpll == 1) - hpt3x2n_set_clock(ap, 0x21); - else - hpt3x2n_set_clock(ap, 0x23); - } - } - return ata_qc_issue_prot(qc); -} - -static struct scsi_host_template hpt3x2n_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -/* - * Configuration for HPT3x2n. - */ - -static struct ata_port_operations hpt3x2n_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt3x2n_set_piomode, - .set_dmamode = hpt3x2n_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt3x2n_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = hpt3x2n_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = hpt3x2n_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * hpt3xn_calibrate_dpll - Calibrate the DPLL loop - * @dev: PCI device - * - * Perform a calibration cycle on the HPT3xN DPLL. Returns 1 if this - * succeeds - */ - -static int hpt3xn_calibrate_dpll(struct pci_dev *dev) -{ - u8 reg5b; - u32 reg5c; - int tries; - - for(tries = 0; tries < 0x5000; tries++) { - udelay(50); - pci_read_config_byte(dev, 0x5b, ®5b); - if (reg5b & 0x80) { - /* See if it stays set */ - for(tries = 0; tries < 0x1000; tries ++) { - pci_read_config_byte(dev, 0x5b, ®5b); - /* Failed ? */ - if ((reg5b & 0x80) == 0) - return 0; - } - /* Turn off tuning, we have the DPLL set */ - pci_read_config_dword(dev, 0x5c, ®5c); - pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); - return 1; - } - } - /* Never went stable */ - return 0; -} - -static int hpt3x2n_pci_clock(struct pci_dev *pdev) -{ - unsigned long freq; - u32 fcnt; - - pci_read_config_dword(pdev, 0x70/*CHECKME*/, &fcnt); - if ((fcnt >> 12) != 0xABCDE) { - printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); - return 33; /* Not BIOS set */ - } - fcnt &= 0x1FF; - - freq = (fcnt * 77) / 192; - - /* Clamp to bands */ - if (freq < 40) - return 33; - if (freq < 45) - return 40; - if (freq < 55) - return 50; - return 66; -} - -/** - * hpt3x2n_init_one - Initialise an HPT37X/302 - * @dev: PCI device - * @id: Entry in match table - * - * Initialise an HPT3x2n device. There are some interesting complications - * here. Firstly the chip may report 366 and be one of several variants. - * Secondly all the timings depend on the clock for the chip which we must - * detect and look up - * - * This is the known chip mappings. It may be missing a couple of later - * releases. - * - * Chip version PCI Rev Notes - * HPT372 4 (HPT366) 5 Other driver - * HPT372N 4 (HPT366) 6 UDMA133 - * HPT372 5 (HPT372) 1 Other driver - * HPT372N 5 (HPT372) 2 UDMA133 - * HPT302 6 (HPT302) * Other driver - * HPT302N 6 (HPT302) > 1 UDMA133 - * HPT371 7 (HPT371) * Other driver - * HPT371N 7 (HPT371) > 1 UDMA133 - * HPT374 8 (HPT374) * Other driver - * HPT372N 9 (HPT372N) * UDMA133 - * - * (1) UDMA133 support depends on the bus clock - * - * To pin down HPT371N - */ - -static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - /* HPT372N and friends - UDMA133 */ - static struct ata_port_info info = { - .sht = &hpt3x2n_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &hpt3x2n_port_ops - }; - struct ata_port_info *port_info[2]; - struct ata_port_info *port = &info; - - u8 irqmask; - u32 class_rev; - - unsigned int pci_mhz; - unsigned int f_low, f_high; - int adjust; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; - - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT366: - if (class_rev < 6) - return -ENODEV; - break; - case PCI_DEVICE_ID_TTI_HPT372: - /* 372N if rev >= 1*/ - if (class_rev == 0) - return -ENODEV; - break; - case PCI_DEVICE_ID_TTI_HPT302: - if (class_rev < 2) - return -ENODEV; - break; - case PCI_DEVICE_ID_TTI_HPT372N: - break; - default: - printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device); - return -ENODEV; - } - - /* Ok so this is a chip we support */ - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - pci_read_config_byte(dev, 0x5A, &irqmask); - irqmask &= ~0x10; - pci_write_config_byte(dev, 0x5a, irqmask); - - /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or - 50 for UDMA100. Right now we always use 66 */ - - pci_mhz = hpt3x2n_pci_clock(dev); - - f_low = (pci_mhz * 48) / 66; /* PCI Mhz for 66Mhz DPLL */ - f_high = f_low + 2; /* Tolerance */ - - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); - /* PLL clock */ - pci_write_config_byte(dev, 0x5B, 0x21); - - /* Unlike the 37x we don't try jiggling the frequency */ - for(adjust = 0; adjust < 8; adjust++) { - if (hpt3xn_calibrate_dpll(dev)) - break; - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); - } - if (adjust == 8) - printk(KERN_WARNING "hpt3xn: DPLL did not stabilize.\n"); - - /* Set our private data up. We only need a few flags so we use - it directly */ - port->private_data = NULL; - if (pci_mhz > 60) - port->private_data = (void *)PCI66; - - /* Now kick off ATA set up */ - port_info[0] = port_info[1] = port; - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id hpt3x2n[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), }, - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N), }, - { 0, }, -}; - -static struct pci_driver hpt3x2n_pci_driver = { - .name = DRV_NAME, - .id_table = hpt3x2n, - .probe = hpt3x2n_init_one, - .remove = ata_pci_remove_one -}; - -static int __init hpt3x2n_init(void) -{ - return pci_register_driver(&hpt3x2n_pci_driver); -} - - -static void __exit hpt3x2n_exit(void) -{ - pci_unregister_driver(&hpt3x2n_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, hpt3x2n); -MODULE_VERSION(DRV_VERSION); - -module_init(hpt3x2n_init); -module_exit(hpt3x2n_exit); diff --git a/trunk/drivers/ata/pata_hpt3x3.c b/trunk/drivers/ata/pata_hpt3x3.c deleted file mode 100644 index 152770133ab1..000000000000 --- a/trunk/drivers/ata/pata_hpt3x3.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * pata_hpt3x3 - HPT3x3 driver - * (c) Copyright 2005-2006 Red Hat - * - * Was pata_hpt34x but the naming was confusing as it supported the - * 343 and 363 so it has been renamed. - * - * Based on: - * linux/drivers/ide/pci/hpt34x.c Version 0.40 Sept 10, 2002 - * Copyright (C) 1998-2000 Andre Hedrick - * - * May be copied or modified under the terms of the GNU General Public - * License - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_hpt3x3" -#define DRV_VERSION "0.4.1" - -static int hpt3x3_probe_init(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * hpt3x3_probe_reset - reset the hpt3x3 bus - * @ap: ATA port to reset - * - * Perform the housekeeping when doing an ATA bus reeset. We just - * need to force the cable type. - */ - -static void hpt3x3_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, hpt3x3_probe_init, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * hpt3x3_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Set our PIO requirements. This is fairly simple on the HPT3x3 as - * all we have to do is clear the MWDMA and UDMA bits then load the - * mode number. - */ - -static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 r1, r2; - int dn = 2 * ap->port_no + adev->devno; - - pci_read_config_dword(pdev, 0x44, &r1); - pci_read_config_dword(pdev, 0x48, &r2); - /* Load the PIO timing number */ - r1 &= ~(7 << (3 * dn)); - r1 |= (adev->pio_mode - XFER_PIO_0) << (3 * dn); - r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ - - pci_write_config_dword(pdev, 0x44, r1); - pci_write_config_dword(pdev, 0x48, r2); -} - -/** - * hpt3x3_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. - */ - -static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 r1, r2; - int dn = 2 * ap->port_no + adev->devno; - int mode_num = adev->dma_mode & 0x0F; - - pci_read_config_dword(pdev, 0x44, &r1); - pci_read_config_dword(pdev, 0x48, &r2); - /* Load the timing number */ - r1 &= ~(7 << (3 * dn)); - r1 |= (mode_num << (3 * dn)); - r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ - - if (adev->dma_mode >= XFER_UDMA_0) - r2 |= 0x01 << dn; /* Ultra mode */ - else - r2 |= 0x10 << dn; /* MWDMA */ - - pci_write_config_dword(pdev, 0x44, r1); - pci_write_config_dword(pdev, 0x48, r2); -} - -static struct scsi_host_template hpt3x3_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations hpt3x3_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt3x3_set_piomode, - .set_dmamode = hpt3x3_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt3x3_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * hpt3x3_init_one - Initialise an HPT343/363 - * @dev: PCI device - * @id: Entry in match table - * - * Perform basic initialisation. The chip has a quirk that it won't - * function unless it is at XX00. The old ATA driver touched this up - * but we leave it for pci quirks to do properly. - */ - -static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &hpt3x3_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &hpt3x3_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - u16 cmd; - - /* Initialize the board */ - pci_write_config_word(dev, 0x80, 0x00); - /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (cmd & PCI_COMMAND_MEMORY) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); - else - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); - - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id hpt3x3[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343), }, - { 0, }, -}; - -static struct pci_driver hpt3x3_pci_driver = { - .name = DRV_NAME, - .id_table = hpt3x3, - .probe = hpt3x3_init_one, - .remove = ata_pci_remove_one -}; - -static int __init hpt3x3_init(void) -{ - return pci_register_driver(&hpt3x3_pci_driver); -} - - -static void __exit hpt3x3_exit(void) -{ - pci_unregister_driver(&hpt3x3_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Highpoint HPT343/363"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, hpt3x3); -MODULE_VERSION(DRV_VERSION); - -module_init(hpt3x3_init); -module_exit(hpt3x3_exit); diff --git a/trunk/drivers/ata/pata_isapnp.c b/trunk/drivers/ata/pata_isapnp.c deleted file mode 100644 index 73948c8b7270..000000000000 --- a/trunk/drivers/ata/pata_isapnp.c +++ /dev/null @@ -1,156 +0,0 @@ - -/* - * pata-isapnp.c - ISA PnP PATA controller driver. - * Copyright 2005/2006 Red Hat Inc , all rights reserved. - * - * Based in part on ide-pnp.c by Andrey Panin - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_isapnp" -#define DRV_VERSION "0.1.5" - -static struct scsi_host_template isapnp_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations isapnp_port_ops = { - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * isapnp_init_one - attach an isapnp interface - * @idev: PnP device - * @dev_id: matching detect line - * - * Register an ISA bus IDE interface. Such interfaces are PIO 0 and - * non shared IRQ. - */ - -static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id) -{ - struct ata_probe_ent ae; - - if (pnp_port_valid(idev, 0) == 0) - return -ENODEV; - - /* FIXME: Should selected polled PIO here not fail */ - if (pnp_irq_valid(idev, 0) == 0) - return -ENODEV; - - memset(&ae, 0, sizeof(struct ata_probe_ent)); - INIT_LIST_HEAD(&ae.node); - ae.dev = &idev->dev; - ae.port_ops = &isapnp_port_ops; - ae.sht = &isapnp_sht; - ae.n_ports = 1; - ae.pio_mask = 1; /* ISA so PIO 0 cycles */ - ae.irq = pnp_irq(idev, 0); - ae.irq_flags = 0; - ae.port_flags = ATA_FLAG_SLAVE_POSS; - ae.port[0].cmd_addr = pnp_port_start(idev, 0); - - if (pnp_port_valid(idev, 1) == 0) { - ae.port[0].altstatus_addr = pnp_port_start(idev, 1); - ae.port[0].ctl_addr = pnp_port_start(idev, 1); - ae.port_flags |= ATA_FLAG_SRST; - } - ata_std_ports(&ae.port[0]); - - if (ata_device_add(&ae) == 0) - return -ENODEV; - return 0; -} - -/** - * isapnp_remove_one - unplug an isapnp interface - * @idev: PnP device - * - * Remove a previously configured PnP ATA port. Called only on module - * unload events as the core does not currently deal with ISAPnP docking. - */ - -static void isapnp_remove_one(struct pnp_dev *idev) -{ - struct device *dev = &idev->dev; - struct ata_host *host = dev_get_drvdata(dev); - - ata_host_remove(host); - dev_set_drvdata(dev, NULL); -} - -static struct pnp_device_id isapnp_devices[] = { - /* Generic ESDI/IDE/ATA compatible hard disk controller */ - {.id = "PNP0600", .driver_data = 0}, - {.id = ""} -}; - -static struct pnp_driver isapnp_driver = { - .name = DRV_NAME, - .id_table = isapnp_devices, - .probe = isapnp_init_one, - .remove = isapnp_remove_one, -}; - -static int __init isapnp_init(void) -{ - return pnp_register_driver(&isapnp_driver); -} - -static void __exit isapnp_exit(void) -{ - pnp_unregister_driver(&isapnp_driver); -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for ISA PnP ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(isapnp_init); -module_exit(isapnp_exit); diff --git a/trunk/drivers/ata/pata_it8172.c b/trunk/drivers/ata/pata_it8172.c deleted file mode 100644 index 53d35bb6fcf9..000000000000 --- a/trunk/drivers/ata/pata_it8172.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * pata_it8172.c - IT8172 PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based heavily on - * - * BRIEF MODULE DESCRIPTION - * IT8172 IDE controller support - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * TODO - * Check for errata - * See if we really need to force native mode - * PIO timings (also lacking in original) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_it8172" -#define DRV_VERSION "0.3.1" - -static int it8172_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits it8172_enable_bits[] = { - { 0x00, 0, 0x00, 0x00 }, - { 0x40, 1, 0x00, 0x01 } - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (ap->port_no && !pci_test_config_bits(pdev, &it8172_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -static void it8172_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, it8172_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * it8172_set_pio_timing - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called by both the pio and dma setup functions to set the controller - * timings for PIO transfers. We must load both the mode number and - * timing values into the controller. - */ - -static void it8172_set_pio_timing(struct ata_port *ap, struct ata_device *adev, int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u16 reg40; - - pci_read_config_word(pdev, 0x40, ®40); - - /* - * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 - * are being left at the default values of 8 PCI clocks (242 nsec - * for a 33 MHz clock). These can be safely shortened at higher - * PIO modes. The DIOR/DIOW pulse width and recovery times only - * apply to PIO modes, not to the DMA modes. - */ - - /* - * Enable port 0x44. The IT8172G spec is confused; it calls - * this register the "Slave IDE Timing Register", but in fact, - * it controls timing for both master and slave drives. - */ - - reg40 |= 0x4000; - if (adev->devno) { - reg40 &= 0xC006; - if (pio > 1) - /* Enable prefetch and IORDY sample-point */ - reg40 |= 0x0060; - } else { - reg40 &= 0xC060; - if (pio > 1) - /* Enable prefetch and IORDY sample-point */ - reg40 |= 0x0006; - } - /* Write back the enables */ - pci_write_config_word(pdev, 0x40, reg40); -} - -/** - * it8172_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. We use a shared helper for this - * as the DMA setup must also adjust the PIO timing information. - */ - -static void it8172_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - it8172_set_pio_timing(ap, adev, adev->pio_mode - XFER_PIO_0); -} - -/** - * it8172_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the DMA mode setup. We must tune an appropriate PIO - * mode to match. - */ - -static void it8172_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int dn = (2 * ap->port_no) + adev->devno; - u8 reg48, reg4a; - int pio; - - static const int pio_map[] = { 1, 3, 4}; - /* - * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec - * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA - * transfers on some drives, even though both numbers meet the minimum - * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. - * So the faster times are just commented out here. The good news is - * that the slower cycle time has very little affect on transfer - * performance. - */ - - pci_read_config_byte(pdev, 0x48, ®48); - pci_read_config_byte(pdev, 0x4A, ®4a); - - reg4a &= ~(3 << (4 * dn)); - - if (adev->dma_mode >= XFER_UDMA_0) { - reg48 |= 1 << dn; -#ifdef UDMA_TIMING_SET - reg4a |= ((adev->dma_mode - XFER_UDMA_0) << (4 * dn)); -#endif - pio = 4; - } else { - pio = pio_map[adev->dma_mode - XFER_MW_DMA_0]; - reg48 &= ~ (1 << dn); - } - pci_write_config_byte(pdev, 0x48, reg48); - pci_write_config_byte(pdev, 0x4A, reg4a); - it8172_set_pio_timing(ap, adev, pio); - -} - -static struct scsi_host_template it8172_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations it8172_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = it8172_set_piomode, - .set_dmamode = it8172_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = it8172_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &it8172_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x06, /* No MWDMA0 support */ - .udma_mask = 0x7, - .port_ops = &it8172_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - if ((!(PCI_FUNC(dev->devfn) & 1) || - (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) - return -ENODEV; /* IT8172 is more than an IDE controller */ - - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id it8172[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G), }, - { 0, }, -}; - -static struct pci_driver it8172_pci_driver = { - .name = DRV_NAME, - .id_table = it8172, - .probe = it8172_init_one, - .remove = ata_pci_remove_one -}; - -static int __init it8172_init(void) -{ - return pci_register_driver(&it8172_pci_driver); -} - - -static void __exit it8172_exit(void) -{ - pci_unregister_driver(&it8172_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for ITE IT8172"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, it8172); -MODULE_VERSION(DRV_VERSION); - -module_init(it8172_init); -module_exit(it8172_exit); diff --git a/trunk/drivers/ata/pata_it821x.c b/trunk/drivers/ata/pata_it821x.c deleted file mode 100644 index af39097d8081..000000000000 --- a/trunk/drivers/ata/pata_it821x.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * ata-it821x.c - IT821x PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based upon - * - * it821x.c - * - * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 - * - * Copyright (C) 2004 Red Hat - * - * May be copied or modified under the terms of the GNU General Public License - * Based in part on the ITE vendor provided SCSI driver. - * - * Documentation available from - * http://www.ite.com.tw/pc/IT8212F_V04.pdf - * Some other documents are NDA. - * - * The ITE8212 isn't exactly a standard IDE controller. It has two - * modes. In pass through mode then it is an IDE controller. In its smart - * mode its actually quite a capable hardware raid controller disguised - * as an IDE controller. Smart mode only understands DMA read/write and - * identify, none of the fancier commands apply. The IT8211 is identical - * in other respects but lacks the raid mode. - * - * Errata: - * o Rev 0x10 also requires master/slave hold the same DMA timings and - * cannot do ATAPI MWDMA. - * o The identify data for raid volumes lacks CHS info (technically ok) - * but also fails to set the LBA28 and other bits. We fix these in - * the IDE probe quirk code. - * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode - * raid then the controller firmware dies - * o Smart mode without RAID doesn't clear all the necessary identify - * bits to reduce the command set to the one used - * - * This has a few impacts on the driver - * - In pass through mode we do all the work you would expect - * - In smart mode the clocking set up is done by the controller generally - * but we must watch the other limits and filter. - * - There are a few extra vendor commands that actually talk to the - * controller but only work PIO with no IRQ. - * - * Vendor areas of the identify block in smart mode are used for the - * timing and policy set up. Each HDD in raid mode also has a serial - * block on the disk. The hardware extra commands are get/set chip status, - * rebuild, get rebuild status. - * - * In Linux the driver supports pass through mode as if the device was - * just another IDE controller. If the smart mode is running then - * volumes are managed by the controller firmware and each IDE "disk" - * is a raid volume. Even more cute - the controller can do automated - * hotplug and rebuild. - * - * The pass through controller itself is a little demented. It has a - * flaw that it has a single set of PIO/MWDMA timings per channel so - * non UDMA devices restrict each others performance. It also has a - * single clock source per channel so mixed UDMA100/133 performance - * isn't perfect and we have to pick a clock. Thankfully none of this - * matters in smart mode. ATAPI DMA is not currently supported. - * - * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. - * - * TODO - * - ATAPI and other speed filtering - * - Command filter in smart mode - * - RAID configuration ioctls - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "pata_it821x" -#define DRV_VERSION "0.3.2" - -struct it821x_dev -{ - unsigned int smart:1, /* Are we in smart raid mode */ - timing10:1; /* Rev 0x10 */ - u8 clock_mode; /* 0, ATA_50 or ATA_66 */ - u8 want[2][2]; /* Mode/Pri log for master slave */ - /* We need these for switching the clock when DMA goes on/off - The high byte is the 66Mhz timing */ - u16 pio[2]; /* Cached PIO values */ - u16 mwdma[2]; /* Cached MWDMA values */ - u16 udma[2]; /* Cached UDMA values (per drive) */ - u16 last_device; /* Master or slave loaded ? */ -}; - -#define ATA_66 0 -#define ATA_50 1 -#define ATA_ANY 2 - -#define UDMA_OFF 0 -#define MWDMA_OFF 0 - -/* - * We allow users to force the card into non raid mode without - * flashing the alternative BIOS. This is also neccessary right now - * for embedded platforms that cannot run a PC BIOS but are using this - * device. - */ - -static int it8212_noraid; - -/** - * it821x_pre_reset - probe - * @ap: ATA port - * - * Set the cable type - */ - -static int it821x_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -/** - * it821x_error_handler - probe/reset - * @ap: ATA port - * - * Set the cable type and trigger a probe - */ - -static void it821x_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, it821x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * it821x_program - program the PIO/MWDMA registers - * @ap: ATA port - * @adev: Device to program - * @timing: Timing value (66Mhz in top 8bits, 50 in the low 8) - * - * Program the PIO/MWDMA timing for this channel according to the - * current clock. These share the same register so are managed by - * the DMA start/stop sequence as with the old driver. - */ - -static void it821x_program(struct ata_port *ap, struct ata_device *adev, u16 timing) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct it821x_dev *itdev = ap->private_data; - int channel = ap->port_no; - u8 conf; - - /* Program PIO/MWDMA timing bits */ - if (itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - pci_write_config_byte(pdev, 0x54 + 4 * channel, conf); -} - - -/** - * it821x_program_udma - program the UDMA registers - * @ap: ATA port - * @adev: ATA device to update - * @timing: Timing bits. Top 8 are for 66Mhz bottom for 50Mhz - * - * Program the UDMA timing for this drive according to the - * current clock. Handles the dual clocks and also knows about - * the errata on the 0x10 revision. The UDMA errata is partly handled - * here and partly in start_dma. - */ - -static void it821x_program_udma(struct ata_port *ap, struct ata_device *adev, u16 timing) -{ - struct it821x_dev *itdev = ap->private_data; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int channel = ap->port_no; - int unit = adev->devno; - u8 conf; - - /* Program UDMA timing bits */ - if (itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - if (itdev->timing10 == 0) - pci_write_config_byte(pdev, 0x56 + 4 * channel + unit, conf); - else { - /* Early revision must be programmed for both together */ - pci_write_config_byte(pdev, 0x56 + 4 * channel, conf); - pci_write_config_byte(pdev, 0x56 + 4 * channel + 1, conf); - } -} - -/** - * it821x_clock_strategy - * @ap: ATA interface - * @adev: ATA device being updated - * - * Select between the 50 and 66Mhz base clocks to get the best - * results for this interface. - */ - -static void it821x_clock_strategy(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct it821x_dev *itdev = ap->private_data; - u8 unit = adev->devno; - struct ata_device *pair = ata_dev_pair(adev); - - int clock, altclock; - u8 v; - int sel = 0; - - /* Look for the most wanted clocking */ - if (itdev->want[0][0] > itdev->want[1][0]) { - clock = itdev->want[0][1]; - altclock = itdev->want[1][1]; - } else { - clock = itdev->want[1][1]; - altclock = itdev->want[0][1]; - } - - /* Master doesn't care does the slave ? */ - if (clock == ATA_ANY) - clock = altclock; - - /* Nobody cares - keep the same clock */ - if (clock == ATA_ANY) - return; - /* No change */ - if (clock == itdev->clock_mode) - return; - - /* Load this into the controller */ - if (clock == ATA_66) - itdev->clock_mode = ATA_66; - else { - itdev->clock_mode = ATA_50; - sel = 1; - } - pci_read_config_byte(pdev, 0x50, &v); - v &= ~(1 << (1 + ap->port_no)); - v |= sel << (1 + ap->port_no); - pci_write_config_byte(pdev, 0x50, v); - - /* - * Reprogram the UDMA/PIO of the pair drive for the switch - * MWDMA will be dealt with by the dma switcher - */ - if (pair && itdev->udma[1-unit] != UDMA_OFF) { - it821x_program_udma(ap, pair, itdev->udma[1-unit]); - it821x_program(ap, pair, itdev->pio[1-unit]); - } - /* - * Reprogram the UDMA/PIO of our drive for the switch. - * MWDMA will be dealt with by the dma switcher - */ - if (itdev->udma[unit] != UDMA_OFF) { - it821x_program_udma(ap, adev, itdev->udma[unit]); - it821x_program(ap, adev, itdev->pio[unit]); - } -} - -/** - * it821x_passthru_set_piomode - set PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Configure for PIO mode. This is complicated as the register is - * shared by PIO and MWDMA and for both channels. - */ - -static void it821x_passthru_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - /* Spec says 89 ref driver uses 88 */ - static const u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; - static const u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; - - struct it821x_dev *itdev = ap->private_data; - int unit = adev->devno; - int mode_wanted = adev->pio_mode - XFER_PIO_0; - - /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ - itdev->want[unit][1] = pio_want[mode_wanted]; - itdev->want[unit][0] = 1; /* PIO is lowest priority */ - itdev->pio[unit] = pio[mode_wanted]; - it821x_clock_strategy(ap, adev); - it821x_program(ap, adev, itdev->pio[unit]); -} - -/** - * it821x_passthru_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Set up the DMA modes. The actions taken depend heavily on the mode - * to use. If UDMA is used as is hopefully the usual case then the - * timing register is private and we need only consider the clock. If - * we are using MWDMA then we have to manage the setting ourself as - * we switch devices and mode. - */ - -static void it821x_passthru_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u16 dma[] = { 0x8866, 0x3222, 0x3121 }; - static const u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; - static const u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; - static const u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct it821x_dev *itdev = ap->private_data; - int channel = ap->port_no; - int unit = adev->devno; - u8 conf; - - if (adev->dma_mode >= XFER_UDMA_0) { - int mode_wanted = adev->dma_mode - XFER_UDMA_0; - - itdev->want[unit][1] = udma_want[mode_wanted]; - itdev->want[unit][0] = 3; /* UDMA is high priority */ - itdev->mwdma[unit] = MWDMA_OFF; - itdev->udma[unit] = udma[mode_wanted]; - if (mode_wanted >= 5) - itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ - - /* UDMA on. Again revision 0x10 must do the pair */ - pci_read_config_byte(pdev, 0x50, &conf); - if (itdev->timing10) - conf &= channel ? 0x9F: 0xE7; - else - conf &= ~ (1 << (3 + 2 * channel + unit)); - pci_write_config_byte(pdev, 0x50, conf); - it821x_clock_strategy(ap, adev); - it821x_program_udma(ap, adev, itdev->udma[unit]); - } else { - int mode_wanted = adev->dma_mode - XFER_MW_DMA_0; - - itdev->want[unit][1] = mwdma_want[mode_wanted]; - itdev->want[unit][0] = 2; /* MWDMA is low priority */ - itdev->mwdma[unit] = dma[mode_wanted]; - itdev->udma[unit] = UDMA_OFF; - - /* UDMA bits off - Revision 0x10 do them in pairs */ - pci_read_config_byte(pdev, 0x50, &conf); - if (itdev->timing10) - conf |= channel ? 0x60: 0x18; - else - conf |= 1 << (3 + 2 * channel + unit); - pci_write_config_byte(pdev, 0x50, conf); - it821x_clock_strategy(ap, adev); - } -} - -/** - * it821x_passthru_dma_start - DMA start callback - * @qc: Command in progress - * - * Usually drivers set the DMA timing at the point the set_dmamode call - * is made. IT821x however requires we load new timings on the - * transitions in some cases. - */ - -static void it821x_passthru_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct it821x_dev *itdev = ap->private_data; - int unit = adev->devno; - - if (itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(ap, adev, itdev->mwdma[unit]); - else if (itdev->udma[unit] != UDMA_OFF && itdev->timing10) - it821x_program_udma(ap, adev, itdev->udma[unit]); - ata_bmdma_start(qc); -} - -/** - * it821x_passthru_dma_stop - DMA stop callback - * @qc: ATA command - * - * We loaded new timings in dma_start, as a result we need to restore - * the PIO timings in dma_stop so that the next command issue gets the - * right clock values. - */ - -static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct it821x_dev *itdev = ap->private_data; - int unit = adev->devno; - - ata_bmdma_stop(qc); - if (itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(ap, adev, itdev->pio[unit]); -} - - -/** - * it821x_passthru_dev_select - Select master/slave - * @ap: ATA port - * @device: Device number (not pointer) - * - * Device selection hook. If neccessary perform clock switching - */ - -static void it821x_passthru_dev_select(struct ata_port *ap, - unsigned int device) -{ - struct it821x_dev *itdev = ap->private_data; - if (itdev && device != itdev->last_device) { - struct ata_device *adev = &ap->device[device]; - it821x_program(ap, adev, itdev->pio[adev->devno]); - itdev->last_device = device; - } - ata_std_dev_select(ap, device); -} - -/** - * it821x_smart_qc_issue_prot - wrap qc issue prot - * @qc: command - * - * Wrap the command issue sequence for the IT821x. We need to - * perform out own device selection timing loads before the - * usual happenings kick off - */ - -static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc) -{ - switch(qc->tf.command) - { - /* Commands the firmware supports */ - case ATA_CMD_READ: - case ATA_CMD_READ_EXT: - case ATA_CMD_WRITE: - case ATA_CMD_WRITE_EXT: - case ATA_CMD_PIO_READ: - case ATA_CMD_PIO_READ_EXT: - case ATA_CMD_PIO_WRITE: - case ATA_CMD_PIO_WRITE_EXT: - case ATA_CMD_READ_MULTI: - case ATA_CMD_READ_MULTI_EXT: - case ATA_CMD_WRITE_MULTI: - case ATA_CMD_WRITE_MULTI_EXT: - case ATA_CMD_ID_ATA: - /* Arguably should just no-op this one */ - case ATA_CMD_SET_FEATURES: - return ata_qc_issue_prot(qc); - } - printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command); - return AC_ERR_INVALID; -} - -/** - * it821x_passthru_qc_issue_prot - wrap qc issue prot - * @qc: command - * - * Wrap the command issue sequence for the IT821x. We need to - * perform out own device selection timing loads before the - * usual happenings kick off - */ - -static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc) -{ - it821x_passthru_dev_select(qc->ap, qc->dev->devno); - return ata_qc_issue_prot(qc); -} - -/** - * it821x_smart_set_mode - mode setting - * @ap: interface to set up - * - * Use a non standard set_mode function. We don't want to be tuned. - * The BIOS configured everything. Our job is not to fiddle. We - * read the dma enabled bits from the PCI configuration of the device - * and respect them. - */ - -static void it821x_smart_set_mode(struct ata_port *ap) -{ - int dma_enabled = 0; - int i; - - /* Bits 5 and 6 indicate if DMA is active on master/slave */ - /* It is possible that BMDMA isn't allocated */ - if (ap->ioaddr.bmdma_addr) - dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->dma_mode = XFER_MW_DMA_0; - /* We do need the right mode information for DMA or PIO - and this comes from the current configuration flags */ - if (dma_enabled & (1 << (5 + i))) { - dev->xfer_mode = XFER_MW_DMA_0; - dev->xfer_shift = ATA_SHIFT_MWDMA; - dev->flags &= ~ATA_DFLAG_PIO; - } else { - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } - } - } -} - -/** - * it821x_dev_config - Called each device identify - * @ap: ATA port - * @adev: Device that has just been identified - * - * Perform the initial setup needed for each device that is chip - * special. In our case we need to lock the sector count to avoid - * blowing the brains out of the firmware with large LBA48 requests - * - * FIXME: When FUA appears we need to block FUA too. And SMART and - * basically we need to filter commands for this chip. - */ - -static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev) -{ - unsigned char model_num[40]; - char *s; - unsigned int len; - - /* This block ought to be a library routine as it is in several - drivers now */ - - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - if (adev->max_sectors > 255) - adev->max_sectors = 255; - - if (strstr(model_num, "Integrated Technology Express")) { - /* RAID mode */ - printk(KERN_INFO "IT821x %sRAID%d volume", - adev->id[147]?"Bootable ":"", - adev->id[129]); - if (adev->id[129] != 1) - printk("(%dK stripe)", adev->id[146]); - printk(".\n"); - } -} - - -/** - * it821x_check_atapi_dma - ATAPI DMA handler - * @qc: Command we are about to issue - * - * Decide if this ATAPI command can be issued by DMA on this - * controller. Return 0 if it can be. - */ - -static int it821x_check_atapi_dma(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct it821x_dev *itdev = ap->private_data; - - /* No ATAPI DMA in smart mode */ - if (itdev->smart) - return -EOPNOTSUPP; - /* No ATAPI DMA on rev 10 */ - if (itdev->timing10) - return -EOPNOTSUPP; - /* Cool */ - return 0; -} - - -/** - * it821x_port_start - port setup - * @ap: ATA port being set up - * - * The it821x needs to maintain private data structures and also to - * use the standard PCI interface which lacks support for this - * functionality. We instead set up the private data on the port - * start hook, and tear it down on port stop - */ - -static int it821x_port_start(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct it821x_dev *itdev; - u8 conf; - - int ret = ata_port_start(ap); - if (ret < 0) - return ret; - - ap->private_data = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL); - if (ap->private_data == NULL) { - ata_port_stop(ap); - return -ENOMEM; - } - - itdev = ap->private_data; - memset(itdev, 0, sizeof(struct it821x_dev)); - - pci_read_config_byte(pdev, 0x50, &conf); - - if (conf & 1) { - itdev->smart = 1; - /* Long I/O's although allowed in LBA48 space cause the - onboard firmware to enter the twighlight zone */ - /* No ATAPI DMA in this mode either */ - } - /* Pull the current clocks from 0x50 */ - if (conf & (1 << (1 + ap->port_no))) - itdev->clock_mode = ATA_50; - else - itdev->clock_mode = ATA_66; - - itdev->want[0][1] = ATA_ANY; - itdev->want[1][1] = ATA_ANY; - itdev->last_device = -1; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &conf); - if (conf == 0x10) { - itdev->timing10 = 1; - /* Need to disable ATAPI DMA for this case */ - if (!itdev->smart) - printk(KERN_WARNING DRV_NAME": Revision 0x10, workarounds activated.\n"); - } - - return 0; -} - -/** - * it821x_port_stop - port shutdown - * @ap: ATA port being removed - * - * Release the private objects we added in it821x_port_start - */ - -static void it821x_port_stop(struct ata_port *ap) { - kfree(ap->private_data); - ap->private_data = NULL; /* We want an OOPS if we reuse this - too late! */ - ata_port_stop(ap); -} - -static struct scsi_host_template it821x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - /* 255 sectors to begin with. This is locked in smart mode but not - in pass through */ - .max_sectors = 255, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations it821x_smart_port_ops = { - .set_mode = it821x_smart_set_mode, - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .mode_filter = ata_pci_default_filter, - - .check_status = ata_check_status, - .check_atapi_dma= it821x_check_atapi_dma, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - .dev_config = it821x_dev_config, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = it821x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = it821x_smart_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = it821x_port_start, - .port_stop = it821x_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations it821x_passthru_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = it821x_passthru_set_piomode, - .set_dmamode = it821x_passthru_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .check_atapi_dma= it821x_check_atapi_dma, - .dev_select = it821x_passthru_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = it821x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = it821x_passthru_bmdma_start, - .bmdma_stop = it821x_passthru_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = it821x_passthru_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_clear = ata_bmdma_irq_clear, - .irq_handler = ata_interrupt, - - .port_start = it821x_port_start, - .port_stop = it821x_port_stop, - .host_stop = ata_host_stop -}; - -static void __devinit it821x_disable_raid(struct pci_dev *pdev) -{ - /* Reset local CPU, and set BIOS not ready */ - pci_write_config_byte(pdev, 0x5E, 0x01); - - /* Set to bypass mode, and reset PCI bus */ - pci_write_config_byte(pdev, 0x50, 0x00); - pci_write_config_word(pdev, PCI_COMMAND, - PCI_COMMAND_PARITY | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(pdev, 0x40, 0xA0F3); - - pci_write_config_dword(pdev,0x4C, 0x02040204); - pci_write_config_byte(pdev, 0x42, 0x36); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20); -} - - -static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - u8 conf; - - static struct ata_port_info info_smart = { - .sht = &it821x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &it821x_smart_port_ops - }; - static struct ata_port_info info_passthru = { - .sht = &it821x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &it821x_passthru_port_ops - }; - static struct ata_port_info *port_info[2]; - - static char *mode[2] = { "pass through", "smart" }; - - /* Force the card into bypass mode if so requested */ - if (it8212_noraid) { - printk(KERN_INFO DRV_NAME ": forcing bypass mode.\n"); - it821x_disable_raid(pdev); - } - pci_read_config_byte(pdev, 0x50, &conf); - conf &= 1; - - printk(KERN_INFO DRV_NAME ": controller in %s mode.\n", mode[conf]); - if (conf == 0) - port_info[0] = port_info[1] = &info_passthru; - else - port_info[0] = port_info[1] = &info_smart; - - return ata_pci_init_one(pdev, port_info, 2); -} - -static struct pci_device_id it821x[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211), }, - { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212), }, - { 0, }, -}; - -static struct pci_driver it821x_pci_driver = { - .name = DRV_NAME, - .id_table = it821x, - .probe = it821x_init_one, - .remove = ata_pci_remove_one -}; - -static int __init it821x_init(void) -{ - return pci_register_driver(&it821x_pci_driver); -} - - -static void __exit it821x_exit(void) -{ - pci_unregister_driver(&it821x_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the IT8211/IT8212 IDE RAID controller"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, it821x); -MODULE_VERSION(DRV_VERSION); - - -module_param_named(noraid, it8212_noraid, int, S_IRUGO); -MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode"); - -module_init(it821x_init); -module_exit(it821x_exit); diff --git a/trunk/drivers/ata/pata_jmicron.c b/trunk/drivers/ata/pata_jmicron.c deleted file mode 100644 index 6832a643a9eb..000000000000 --- a/trunk/drivers/ata/pata_jmicron.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * pata_jmicron.c - JMicron ATA driver for non AHCI mode. This drives the - * PATA port of the controller. The SATA ports are - * driven by AHCI in the usual configuration although - * this driver can handle other setups if we need it. - * - * (c) 2006 Red Hat - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_jmicron" -#define DRV_VERSION "0.1.2" - -typedef enum { - PORT_PATA0 = 0, - PORT_PATA1 = 1, - PORT_SATA = 2, -} port_type; - -/** - * jmicron_pre_reset - check for 40/80 pin - * @ap: Port - * - * Perform the PATA port setup we need. - - * On the Jmicron 361/363 there is a single PATA port that can be mapped - * either as primary or secondary (or neither). We don't do any policy - * and setup here. We assume that has been done by init_one and the - * BIOS. - */ - -static int jmicron_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 control; - u32 control5; - int port_mask = 1<< (4 * ap->port_no); - int port = ap->port_no; - port_type port_map[2]; - - /* Check if our port is enabled */ - pci_read_config_dword(pdev, 0x40, &control); - if ((control & port_mask) == 0) - return 0; - - /* There are two basic mappings. One has the two SATA ports merged - as master/slave and the secondary as PATA, the other has only the - SATA port mapped */ - if (control & (1 << 23)) { - port_map[0] = PORT_SATA; - port_map[1] = PORT_PATA0; - } else { - port_map[0] = PORT_SATA; - port_map[1] = PORT_SATA; - } - - /* The 365/366 may have this bit set to map the second PATA port - as the internal primary channel */ - pci_read_config_dword(pdev, 0x80, &control5); - if (control5 & (1<<24)) - port_map[0] = PORT_PATA1; - - /* The two ports may then be logically swapped by the firmware */ - if (control & (1 << 22)) - port = port ^ 1; - - /* - * Now we know which physical port we are talking about we can - * actually do our cable checking etc. Thankfully we don't need - * to do the plumbing for other cases. - */ - switch (port_map[port]) - { - case PORT_PATA0: - if (control & (1 << 5)) - return 0; - if (control & (1 << 3)) /* 40/80 pin primary */ - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - break; - case PORT_PATA1: - /* Bit 21 is set if the port is enabled */ - if ((control5 & (1 << 21)) == 0) - return 0; - if (control5 & (1 << 19)) /* 40/80 pin secondary */ - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - break; - case PORT_SATA: - ap->cbl = ATA_CBL_SATA; - break; - } - return ata_std_prereset(ap); -} - -/** - * jmicron_error_handler - Setup and error handler - * @ap: Port to handle - * - * LOCKING: - * None (inherited from caller). - */ - -static void jmicron_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/* No PIO or DMA methods needed for this device */ - -static struct scsi_host_template jmicron_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - /* Special handling needed if you have sector or LBA48 limits */ - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - /* Use standard CHS mapping rules */ - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations jmicron_ops = { - .port_disable = ata_port_disable, - - /* Task file is PCI ATA format, use helpers */ - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = jmicron_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - /* BMDMA handling is PCI ATA format, use helpers */ - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - /* Timeout handling. Special recovery hooks here */ - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - /* Generic PATA PCI ATA helpers */ - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * jmicron_init_one - Register Jmicron ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in jmicron_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &jmicron_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - - .port_ops = &jmicron_ops, - }; - struct ata_port_info *port_info[2] = { &info, &info }; - - u32 reg; - - if (id->driver_data != 368) { - /* Put the controller into AHCI mode in case the AHCI driver - has not yet been loaded. This can be done with either - function present */ - - /* FIXME: We may want a way to override this in future */ - pci_write_config_byte(pdev, 0x41, 0xa1); - } - - /* PATA controller is fn 1, AHCI is fn 0 */ - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - if ( id->driver_data == 365 || id->driver_data == 366) { - /* The 365/66 have two PATA channels, redirect the second */ - pci_read_config_dword(pdev, 0x80, ®); - reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ - pci_write_config_dword(pdev, 0x80, reg); - } - - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id jmicron_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 365}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 366}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 368}, - { } /* terminate list */ -}; - -static struct pci_driver jmicron_pci_driver = { - .name = DRV_NAME, - .id_table = jmicron_pci_tbl, - .probe = jmicron_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init jmicron_init(void) -{ - return pci_register_driver(&jmicron_pci_driver); -} - -static void __exit jmicron_exit(void) -{ - pci_unregister_driver(&jmicron_pci_driver); -} - -module_init(jmicron_init); -module_exit(jmicron_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for Jmicron PATA ports"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_legacy.c b/trunk/drivers/ata/pata_legacy.c deleted file mode 100644 index ad37c220bb2c..000000000000 --- a/trunk/drivers/ata/pata_legacy.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * pata-legacy.c - Legacy port PATA/SATA controller driver. - * Copyright 2005/2006 Red Hat , all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * An ATA driver for the legacy ATA ports. - * - * Data Sources: - * Opti 82C465/82C611 support: Data sheets at opti-inc.com - * HT6560 series: - * Promise 20230/20620: - * http://www.ryston.cz/petr/vlb/pdc20230b.html - * http://www.ryston.cz/petr/vlb/pdc20230c.html - * http://www.ryston.cz/petr/vlb/pdc20630.html - * - * Unsupported but docs exist: - * Appian/Adaptec AIC25VL01/Cirrus Logic PD7220 - * Winbond W83759A - * - * This driver handles legacy (that is "ISA/VLB side") IDE ports found - * on PC class systems. There are three hybrid devices that are exceptions - * The Cyrix 5510/5520 where a pre SFF ATA device is on the bridge and - * the MPIIX where the tuning is PCI side but the IDE is "ISA side". - * - * Specific support is included for the ht6560a/ht6560b/opti82c611a/ - * opti82c465mv/promise 20230c/20630 - * - * Use the autospeed and pio_mask options with: - * Appian ADI/2 aka CLPD7220 or AIC25VL01. - * Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with - * Goldstar GM82C711, PIC-1288A-125, UMC 82C871F, Winbond W83759, - * Winbond W83759A, Promise PDC20230-B - * - * For now use autospeed and pio_mask as above with the W83759A. This may - * change. - * - * TODO - * Merge existing pata_qdi driver - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_legacy" -#define DRV_VERSION "0.5.3" - -#define NR_HOST 6 - -static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; -static int legacy_irq[NR_HOST] = { 15, 14, 11, 10, 8, 12 }; - -struct legacy_data { - unsigned long timing; - u8 clock[2]; - u8 last; - int fast; - struct platform_device *platform_dev; - -}; - -static struct legacy_data legacy_data[NR_HOST]; -static struct ata_host *legacy_host[NR_HOST]; -static int nr_legacy_host; - - -static int probe_all; /* Set to check all ISA port ranges */ -static int ht6560a; /* HT 6560A on primary 1, secondary 2, both 3 */ -static int ht6560b; /* HT 6560A on primary 1, secondary 2, both 3 */ -static int opti82c611a; /* Opti82c611A on primary 1, secondary 2, both 3 */ -static int opti82c46x; /* Opti 82c465MV present (pri/sec autodetect) */ -static int autospeed; /* Chip present which snoops speed changes */ -static int pio_mask = 0x1F; /* PIO range for autospeed devices */ - -/** - * legacy_set_mode - mode setting - * @ap: IDE interface - * - * Use a non standard set_mode function. We don't want to be tuned. - * - * The BIOS configured everything. Our job is not to fiddle. Just use - * whatever PIO the hardware is using and leave it at that. When we - * get some kind of nice user driven API for control then we can - * expand on this as per hdparm in the base kernel. - */ - -static void legacy_set_mode(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } - } -} - -static struct scsi_host_template legacy_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -/* - * These ops are used if the user indicates the hardware - * snoops the commands to decide on the mode and handles the - * mode selection "magically" itself. Several legacy controllers - * do this. The mode range can be set if it is not 0x1F by setting - * pio_mask as well. - */ - -static struct ata_port_operations simple_port_ops = { - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer_noirq, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations legacy_port_ops = { - .set_mode = legacy_set_mode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer_noirq, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Promise 20230C and 20620 support - * - * This controller supports PIO0 to PIO2. We set PIO timings conservatively to - * allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to - * controller and PIO'd to the host and not supported. - */ - -static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - int tries = 5; - int pio = adev->pio_mode - XFER_PIO_0; - u8 rt; - unsigned long flags; - - /* Safe as UP only. Force I/Os to occur together */ - - local_irq_save(flags); - - /* Unlock the control interface */ - do - { - inb(0x1F5); - outb(inb(0x1F2) | 0x80, 0x1F2); - inb(0x1F2); - inb(0x3F6); - inb(0x3F6); - inb(0x1F2); - inb(0x1F2); - } - while((inb(0x1F2) & 0x80) && --tries); - - local_irq_restore(flags); - - outb(inb(0x1F4) & 0x07, 0x1F4); - - rt = inb(0x1F3); - rt &= 0x07 << (3 * adev->devno); - if (pio) - rt |= (1 + 3 * pio) << (3 * adev->devno); - - udelay(100); - outb(inb(0x1F2) | 0x01, 0x1F2); - udelay(100); - inb(0x1F5); - -} - -static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) -{ - struct ata_port *ap = adev->ap; - int slop = buflen & 3; - unsigned long flags; - - if (ata_id_has_dword_io(adev->id)) { - local_irq_save(flags); - - /* Perform the 32bit I/O synchronization sequence */ - inb(ap->ioaddr.nsect_addr); - inb(ap->ioaddr.nsect_addr); - inb(ap->ioaddr.nsect_addr); - - /* Now the data */ - - if (write_data) - outsl(ap->ioaddr.data_addr, buf, buflen >> 2); - else - insl(ap->ioaddr.data_addr, buf, buflen >> 2); - - if (unlikely(slop)) { - u32 pad; - if (write_data) { - memcpy(&pad, buf + buflen - slop, slop); - outl(le32_to_cpu(pad), ap->ioaddr.data_addr); - } else { - pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); - memcpy(buf + buflen - slop, &pad, slop); - } - } - local_irq_restore(flags); - } - else - ata_pio_data_xfer_noirq(adev, buf, buflen, write_data); -} - -static struct ata_port_operations pdc20230_port_ops = { - .set_piomode = pdc20230_set_piomode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = pdc_data_xfer_vlb, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Holtek 6560A support - * - * This controller supports PIO0 to PIO2 (no IORDY even though higher timings - * can be loaded). - */ - -static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - u8 active, recover; - struct ata_timing t; - - /* Get the timing data in cycles. For now play safe at 50Mhz */ - ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); - - active = FIT(t.active, 2, 15); - recover = FIT(t.recover, 4, 15); - - inb(0x3E6); - inb(0x3E6); - inb(0x3E6); - inb(0x3E6); - - outb(recover << 4 | active, ap->ioaddr.device_addr); - inb(ap->ioaddr.status_addr); -} - -static struct ata_port_operations ht6560a_port_ops = { - .set_piomode = ht6560a_set_piomode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, /* Check vlb/noirq */ - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Holtek 6560B support - * - * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting - * unless we see an ATAPI device in which case we force it off. - * - * FIXME: need to implement 2nd channel support. - */ - -static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - u8 active, recover; - struct ata_timing t; - - /* Get the timing data in cycles. For now play safe at 50Mhz */ - ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); - - active = FIT(t.active, 2, 15); - recover = FIT(t.recover, 2, 16); - recover &= 0x15; - - inb(0x3E6); - inb(0x3E6); - inb(0x3E6); - inb(0x3E6); - - outb(recover << 4 | active, ap->ioaddr.device_addr); - - if (adev->class != ATA_DEV_ATA) { - u8 rconf = inb(0x3E6); - if (rconf & 0x24) { - rconf &= ~ 0x24; - outb(rconf, 0x3E6); - } - } - inb(ap->ioaddr.status_addr); -} - -static struct ata_port_operations ht6560b_port_ops = { - .set_piomode = ht6560b_set_piomode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, /* FIXME: Check 32bit and noirq */ - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Opti core chipset helpers - */ - -/** - * opti_syscfg - read OPTI chipset configuration - * @reg: Configuration register to read - * - * Returns the value of an OPTI system board configuration register. - */ - -static u8 opti_syscfg(u8 reg) -{ - unsigned long flags; - u8 r; - - /* Uniprocessor chipset and must force cycles adjancent */ - local_irq_save(flags); - outb(reg, 0x22); - r = inb(0x24); - local_irq_restore(flags); - return r; -} - -/* - * Opti 82C611A - * - * This controller supports PIO0 to PIO3. - */ - -static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - u8 active, recover, setup; - struct ata_timing t; - struct ata_device *pair = ata_dev_pair(adev); - int clock; - int khz[4] = { 50000, 40000, 33000, 25000 }; - u8 rc; - - /* Enter configuration mode */ - inw(ap->ioaddr.error_addr); - inw(ap->ioaddr.error_addr); - outb(3, ap->ioaddr.nsect_addr); - - /* Read VLB clock strapping */ - clock = 1000000000 / khz[inb(ap->ioaddr.lbah_addr) & 0x03]; - - /* Get the timing data in cycles */ - ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000); - - /* Setup timing is shared */ - if (pair) { - struct ata_timing tp; - ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000); - - ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); - } - - active = FIT(t.active, 2, 17) - 2; - recover = FIT(t.recover, 1, 16) - 1; - setup = FIT(t.setup, 1, 4) - 1; - - /* Select the right timing bank for write timing */ - rc = inb(ap->ioaddr.lbal_addr); - rc &= 0x7F; - rc |= (adev->devno << 7); - outb(rc, ap->ioaddr.lbal_addr); - - /* Write the timings */ - outb(active << 4 | recover, ap->ioaddr.error_addr); - - /* Select the right bank for read timings, also - load the shared timings for address */ - rc = inb(ap->ioaddr.device_addr); - rc &= 0xC0; - rc |= adev->devno; /* Index select */ - rc |= (setup << 4) | 0x04; - outb(rc, ap->ioaddr.device_addr); - - /* Load the read timings */ - outb(active << 4 | recover, ap->ioaddr.data_addr); - - /* Ensure the timing register mode is right */ - rc = inb (ap->ioaddr.lbal_addr); - rc &= 0x73; - rc |= 0x84; - outb(rc, ap->ioaddr.lbal_addr); - - /* Exit command mode */ - outb(0x83, ap->ioaddr.nsect_addr); -} - - -static struct ata_port_operations opti82c611a_port_ops = { - .set_piomode = opti82c611a_set_piomode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/* - * Opti 82C465MV - * - * This controller supports PIO0 to PIO3. Unlike the 611A the MVB - * version is dual channel but doesn't have a lot of unique registers. - */ - -static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - u8 active, recover, setup; - struct ata_timing t; - struct ata_device *pair = ata_dev_pair(adev); - int clock; - int khz[4] = { 50000, 40000, 33000, 25000 }; - u8 rc; - u8 sysclk; - - /* Get the clock */ - sysclk = opti_syscfg(0xAC) & 0xC0; /* BIOS set */ - - /* Enter configuration mode */ - inw(ap->ioaddr.error_addr); - inw(ap->ioaddr.error_addr); - outb(3, ap->ioaddr.nsect_addr); - - /* Read VLB clock strapping */ - clock = 1000000000 / khz[sysclk]; - - /* Get the timing data in cycles */ - ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000); - - /* Setup timing is shared */ - if (pair) { - struct ata_timing tp; - ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000); - - ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); - } - - active = FIT(t.active, 2, 17) - 2; - recover = FIT(t.recover, 1, 16) - 1; - setup = FIT(t.setup, 1, 4) - 1; - - /* Select the right timing bank for write timing */ - rc = inb(ap->ioaddr.lbal_addr); - rc &= 0x7F; - rc |= (adev->devno << 7); - outb(rc, ap->ioaddr.lbal_addr); - - /* Write the timings */ - outb(active << 4 | recover, ap->ioaddr.error_addr); - - /* Select the right bank for read timings, also - load the shared timings for address */ - rc = inb(ap->ioaddr.device_addr); - rc &= 0xC0; - rc |= adev->devno; /* Index select */ - rc |= (setup << 4) | 0x04; - outb(rc, ap->ioaddr.device_addr); - - /* Load the read timings */ - outb(active << 4 | recover, ap->ioaddr.data_addr); - - /* Ensure the timing register mode is right */ - rc = inb (ap->ioaddr.lbal_addr); - rc &= 0x73; - rc |= 0x84; - outb(rc, ap->ioaddr.lbal_addr); - - /* Exit command mode */ - outb(0x83, ap->ioaddr.nsect_addr); - - /* We need to know this for quad device on the MVB */ - ap->host->private_data = ap; -} - -/** - * opt82c465mv_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings. The - * MVB has a single set of timing registers and these are shared - * across channels. As there are two registers we really ought to - * track the last two used values as a sort of register window. For - * now we just reload on a channel switch. On the single channel - * setup this condition never fires so we do nothing extra. - * - * FIXME: dual channel needs ->serialize support - */ - -static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - /* If timings are set and for the wrong channel (2nd test is - due to a libata shortcoming and will eventually go I hope) */ - if (ap->host->private_data != ap->host - && ap->host->private_data != NULL) - opti82c46x_set_piomode(ap, adev); - - return ata_qc_issue_prot(qc); -} - -static struct ata_port_operations opti82c46x_port_ops = { - .set_piomode = opti82c46x_set_piomode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .qc_prep = ata_qc_prep, - .qc_issue = opti82c46x_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - - -/** - * legacy_init_one - attach a legacy interface - * @port: port number - * @io: I/O port start - * @ctrl: control port - * @irq: interrupt line - * - * Register an ISA bus IDE interface. Such interfaces are PIO and we - * assume do not support IRQ sharing. - */ - -static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq) -{ - struct legacy_data *ld = &legacy_data[nr_legacy_host]; - struct ata_probe_ent ae; - struct platform_device *pdev; - int ret = -EBUSY; - struct ata_port_operations *ops = &legacy_port_ops; - int pio_modes = pio_mask; - u32 mask = (1 << port); - - if (request_region(io, 8, "pata_legacy") == NULL) - return -EBUSY; - if (request_region(ctrl, 1, "pata_legacy") == NULL) - goto fail_io; - - pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0); - if (pdev == NULL) - goto fail_dev; - - if (ht6560a & mask) { - ops = &ht6560a_port_ops; - pio_modes = 0x07; - } - if (ht6560b & mask) { - ops = &ht6560b_port_ops; - pio_modes = 0x1F; - } - if (opti82c611a & mask) { - ops = &opti82c611a_port_ops; - pio_modes = 0x0F; - } - if (opti82c46x & mask) { - ops = &opti82c46x_port_ops; - pio_modes = 0x0F; - } - - /* Probe for automatically detectable controllers */ - - if (io == 0x1F0 && ops == &legacy_port_ops) { - unsigned long flags; - - local_irq_save(flags); - - /* Probes */ - inb(0x1F5); - outb(inb(0x1F2) | 0x80, 0x1F2); - inb(0x1F2); - inb(0x3F6); - inb(0x3F6); - inb(0x1F2); - inb(0x1F2); - - if ((inb(0x1F2) & 0x80) == 0) { - /* PDC20230c or 20630 ? */ - printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n"); - pio_modes = 0x07; - ops = &pdc20230_port_ops; - udelay(100); - inb(0x1F5); - } else { - outb(0x55, 0x1F2); - inb(0x1F2); - inb(0x1F2); - if (inb(0x1F2) == 0x00) { - printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n"); - } - } - local_irq_restore(flags); - } - - - /* Chip does mode setting by command snooping */ - if (ops == &legacy_port_ops && (autospeed & mask)) - ops = &simple_port_ops; - memset(&ae, 0, sizeof(struct ata_probe_ent)); - INIT_LIST_HEAD(&ae.node); - ae.dev = &pdev->dev; - ae.port_ops = ops; - ae.sht = &legacy_sht; - ae.n_ports = 1; - ae.pio_mask = pio_modes; - ae.irq = irq; - ae.irq_flags = 0; - ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST; - ae.port[0].cmd_addr = io; - ae.port[0].altstatus_addr = ctrl; - ae.port[0].ctl_addr = ctrl; - ata_std_ports(&ae.port[0]); - ae.private_data = ld; - - ret = ata_device_add(&ae); - if (ret == 0) { - ret = -ENODEV; - goto fail; - } - legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev); - ld->platform_dev = pdev; - return 0; - -fail: - platform_device_unregister(pdev); -fail_dev: - release_region(ctrl, 1); -fail_io: - release_region(io, 8); - return ret; -} - -/** - * legacy_check_special_cases - ATA special cases - * @p: PCI device to check - * @master: set this if we find an ATA master - * @master: set this if we find an ATA secondary - * - * A small number of vendors implemented early PCI ATA interfaces on bridge logic - * without the ATA interface being PCI visible. Where we have a matching PCI driver - * we must skip the relevant device here. If we don't know about it then the legacy - * driver is the right driver anyway. - */ - -static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary) -{ - /* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */ - if (p->vendor == 0x1078 && p->device == 0x0000) { - *primary = *secondary = 1; - return; - } - /* Cyrix CS5520 pre SFF MWDMA ATA on the bridge */ - if (p->vendor == 0x1078 && p->device == 0x0002) { - *primary = *secondary = 1; - return; - } - /* Intel MPIIX - PIO ATA on non PCI side of bridge */ - if (p->vendor == 0x8086 && p->device == 0x1234) { - u16 r; - pci_read_config_word(p, 0x6C, &r); - if (r & 0x8000) { /* ATA port enabled */ - if (r & 0x4000) - *secondary = 1; - else - *primary = 1; - } - return; - } -} - - -/** - * legacy_init - attach legacy interfaces - * - * Attach legacy IDE interfaces by scanning the usual IRQ/port suspects. - * Right now we do not scan the ide0 and ide1 address but should do so - * for non PCI systems or systems with no PCI IDE legacy mode devices. - * If you fix that note there are special cases to consider like VLB - * drivers and CS5510/20. - */ - -static __init int legacy_init(void) -{ - int i; - int ct = 0; - int primary = 0; - int secondary = 0; - int last_port = NR_HOST; - - struct pci_dev *p = NULL; - - for_each_pci_dev(p) { - int r; - /* Check for any overlap of the system ATA mappings. Native mode controllers - stuck on these addresses or some devices in 'raid' mode won't be found by - the storage class test */ - for (r = 0; r < 6; r++) { - if (pci_resource_start(p, r) == 0x1f0) - primary = 1; - if (pci_resource_start(p, r) == 0x170) - secondary = 1; - } - /* Check for special cases */ - legacy_check_special_cases(p, &primary, &secondary); - - /* If PCI bus is present then don't probe for tertiary legacy ports */ - if (probe_all == 0) - last_port = 2; - } - - /* If an OPTI 82C46X is present find out where the channels are */ - if (opti82c46x) { - static const char *optis[4] = { - "3/463MV", "5MV", - "5MVA", "5MVB" - }; - u8 chans = 1; - u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6; - - opti82c46x = 3; /* Assume master and slave first */ - printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]); - if (ctrl == 3) - chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1; - ctrl = opti_syscfg(0xAC); - /* Check enabled and this port is the 465MV port. On the - MVB we may have two channels */ - if (ctrl & 8) { - if (ctrl & 4) - opti82c46x = 2; /* Slave */ - else - opti82c46x = 1; /* Master */ - if (chans == 2) - opti82c46x = 3; /* Master and Slave */ - } /* Slave only */ - else if (chans == 1) - opti82c46x = 1; - } - - for (i = 0; i < last_port; i++) { - /* Skip primary if we have seen a PCI one */ - if (i == 0 && primary == 1) - continue; - /* Skip secondary if we have seen a PCI one */ - if (i == 1 && secondary == 1) - continue; - if (legacy_init_one(i, legacy_port[i], - legacy_port[i] + 0x0206, - legacy_irq[i]) == 0) - ct++; - } - if (ct != 0) - return 0; - return -ENODEV; -} - -static __exit void legacy_exit(void) -{ - int i; - - for (i = 0; i < nr_legacy_host; i++) { - struct legacy_data *ld = &legacy_data[i]; - struct ata_port *ap =legacy_host[i]->ports[0]; - unsigned long io = ap->ioaddr.cmd_addr; - unsigned long ctrl = ap->ioaddr.ctl_addr; - ata_host_remove(legacy_host[i]); - platform_device_unregister(ld->platform_dev); - if (ld->timing) - release_region(ld->timing, 2); - release_region(io, 8); - release_region(ctrl, 1); - } -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for legacy ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(probe_all, int, 0); -module_param(autospeed, int, 0); -module_param(ht6560a, int, 0); -module_param(ht6560b, int, 0); -module_param(opti82c611a, int, 0); -module_param(opti82c46x, int, 0); -module_param(pio_mask, int, 0); - -module_init(legacy_init); -module_exit(legacy_exit); - diff --git a/trunk/drivers/ata/pata_mpiix.c b/trunk/drivers/ata/pata_mpiix.c deleted file mode 100644 index 1958c4ed09a8..000000000000 --- a/trunk/drivers/ata/pata_mpiix.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * pata_mpiix.c - Intel MPIIX PATA for new ATA layer - * (C) 2005-2006 Red Hat Inc - * Alan Cox - * - * The MPIIX is different enough to the PIIX4 and friends that we give it - * a separate driver. The old ide/pci code handles this by just not tuning - * MPIIX at all. - * - * The MPIIX also differs in another important way from the majority of PIIX - * devices. The chip is a bridge (pardon the pun) between the old world of - * ISA IDE and PCI IDE. Although the ATA timings are PCI configured the actual - * IDE controller is not decoded in PCI space and the chip does not claim to - * be IDE class PCI. This requires slightly non-standard probe logic compared - * with PCI IDE and also that we do not disable the device when our driver is - * unloaded (as it has many other functions). - * - * The driver conciously keeps this logic internally to avoid pushing quirky - * PATA history into the clean libata layer. - * - * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA - * hard disk present this driver will not detect it. This is not a bug. In this - * configuration the secondary port of the MPIIX is disabled and the addresses - * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver - * to operate. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_mpiix" -#define DRV_VERSION "0.7.1" - -enum { - IDETIM = 0x6C, /* IDE control register */ - IORDY = (1 << 1), - PPE = (1 << 2), - FTIM = (1 << 0), - ENABLED = (1 << 15), - SECONDARY = (1 << 14) -}; - -static int mpiix_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits mpiix_enable_bits[] = { - { 0x6D, 1, 0x80, 0x80 }, - { 0x6F, 1, 0x80, 0x80 } - }; - - if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * mpiix_error_handler - probe reset - * @ap: ATA port - * - * Perform the ATA probe and bus reset sequence plus specific handling - * for this hardware. The MPIIX has the enable bits in a different place - * to PIIX4 and friends. As a pure PIO device it has no cable detect - */ - -static void mpiix_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * mpiix_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. The MPIIX allows us to program the - * IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether - * prefetching or iordy are used. - * - * This would get very ugly because we can only program timing for one - * device at a time, the other gets PIO0. Fortunately libata calls - * our qc_issue_prot command before a command is issued so we can - * flip the timings back and forth to reduce the pain. - */ - -static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - int control = 0; - int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u16 idetim; - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pci_read_config_word(pdev, IDETIM, &idetim); - /* Mask the IORDY/TIME/PPE0 bank for this device */ - if (adev->class == ATA_DEV_ATA) - control |= PPE; /* PPE enable for disk */ - if (ata_pio_need_iordy(adev)) - control |= IORDY; /* IORDY */ - if (pio > 0) - control |= FTIM; /* This drive is on the fast timing bank */ - - /* Mask out timing and clear both TIME bank selects */ - idetim &= 0xCCEE; - idetim &= ~(0x07 << (2 * adev->devno)); - idetim |= (control << (2 * adev->devno)); - - idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - pci_write_config_word(pdev, IDETIM, idetim); - - /* We use ap->private_data as a pointer to the device currently - loaded for timing */ - ap->private_data = adev; -} - -/** - * mpiix_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. Our logic also clears TIME0/TIME1 for the other device so - * that, even if we get this wrong, cycles to the other device will - * be made PIO0. - */ - -static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - /* If modes have been configured and the channel data is not loaded - then load it. We have to check if pio_mode is set as the core code - does not set adev->pio_mode to XFER_PIO_0 while probing as would be - logical */ - - if (adev->pio_mode && adev != ap->private_data) - mpiix_set_piomode(ap, adev); - - return ata_qc_issue_prot(qc); -} - -static struct scsi_host_template mpiix_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations mpiix_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = mpiix_set_piomode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = mpiix_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = mpiix_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - /* Single threaded by the PCI probe logic */ - static struct ata_probe_ent probe[2]; - static int printed_version; - u16 idetim; - int enabled; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - - /* MPIIX has many functions which can be turned on or off according - to other devices present. Make sure IDE is enabled before we try - and use it */ - - pci_read_config_word(dev, IDETIM, &idetim); - if (!(idetim & ENABLED)) - return -ENODEV; - - /* We do our own plumbing to avoid leaking special cases for whacko - ancient hardware into the core code. There are two issues to - worry about. #1 The chip is a bridge so if in legacy mode and - without BARs set fools the setup. #2 If you pci_disable_device - the MPIIX your box goes castors up */ - - INIT_LIST_HEAD(&probe[0].node); - probe[0].dev = pci_dev_to_dev(dev); - probe[0].port_ops = &mpiix_port_ops; - probe[0].sht = &mpiix_sht; - probe[0].pio_mask = 0x1F; - probe[0].irq = 14; - probe[0].irq_flags = SA_SHIRQ; - probe[0].port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; - probe[0].n_ports = 1; - probe[0].port[0].cmd_addr = 0x1F0; - probe[0].port[0].ctl_addr = 0x3F6; - probe[0].port[0].altstatus_addr = 0x3F6; - - /* The secondary lurks at different addresses but is otherwise - the same beastie */ - - INIT_LIST_HEAD(&probe[1].node); - probe[1] = probe[0]; - probe[1].irq = 15; - probe[1].port[0].cmd_addr = 0x170; - probe[1].port[0].ctl_addr = 0x376; - probe[1].port[0].altstatus_addr = 0x376; - - /* Let libata fill in the port details */ - ata_std_ports(&probe[0].port[0]); - ata_std_ports(&probe[1].port[0]); - - /* Now add the port that is active */ - enabled = (idetim & SECONDARY) ? 1 : 0; - - if (ata_device_add(&probe[enabled])) - return 0; - return -ENODEV; -} - -/** - * mpiix_remove_one - device unload - * @pdev: PCI device being removed - * - * Handle an unplug/unload event for a PCI device. Unload the - * PCI driver but do not use the default handler as we *MUST NOT* - * disable the device as it has other functions. - */ - -static void __devexit mpiix_remove_one(struct pci_dev *pdev) -{ - struct device *dev = pci_dev_to_dev(pdev); - struct ata_host *host = dev_get_drvdata(dev); - - ata_host_remove(host); - dev_set_drvdata(dev, NULL); -} - - - -static const struct pci_device_id mpiix[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX), }, - { 0, }, -}; - -static struct pci_driver mpiix_pci_driver = { - .name = DRV_NAME, - .id_table = mpiix, - .probe = mpiix_init_one, - .remove = mpiix_remove_one -}; - -static int __init mpiix_init(void) -{ - return pci_register_driver(&mpiix_pci_driver); -} - - -static void __exit mpiix_exit(void) -{ - pci_unregister_driver(&mpiix_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Intel MPIIX"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, mpiix); -MODULE_VERSION(DRV_VERSION); - -module_init(mpiix_init); -module_exit(mpiix_exit); diff --git a/trunk/drivers/ata/pata_netcell.c b/trunk/drivers/ata/pata_netcell.c deleted file mode 100644 index 16cb254cb973..000000000000 --- a/trunk/drivers/ata/pata_netcell.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * pata_netcell.c - Netcell PATA driver - * - * (c) 2006 Red Hat - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_netcell" -#define DRV_VERSION "0.1.5" - -/** - * netcell_probe_init - check for 40/80 pin - * @ap: Port - * - * Cables are handled by the RAID controller. Report 80 pin. - */ - -static int netcell_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - -/** - * netcell_probe_reset - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void netcell_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, netcell_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/* No PIO or DMA methods needed for this device */ - -static struct scsi_host_template netcell_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - /* Special handling needed if you have sector or LBA48 limits */ - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - /* Use standard CHS mapping rules */ - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations netcell_ops = { - .port_disable = ata_port_disable, - - /* Task file is PCI ATA format, use helpers */ - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = netcell_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - /* BMDMA handling is PCI ATA format, use helpers */ - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - /* Timeout handling. Special recovery hooks here */ - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - /* Generic PATA PCI ATA helpers */ - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * netcell_init_one - Register Netcell ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in netcell_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - static struct ata_port_info info = { - .sht = &netcell_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - /* Actually we don't really care about these as the - firmware deals with it */ - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x3f, /* UDMA 133 */ - .port_ops = &netcell_ops, - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - /* Any chip specific setup/optimisation/messages here */ - ata_pci_clear_simplex(pdev); - - /* And let the library code do the work */ - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id netcell_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NETCELL, PCI_DEVICE_ID_REVOLUTION), }, - { } /* terminate list */ -}; - -static struct pci_driver netcell_pci_driver = { - .name = DRV_NAME, - .id_table = netcell_pci_tbl, - .probe = netcell_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init netcell_init(void) -{ - return pci_register_driver(&netcell_pci_driver); -} - -static void __exit netcell_exit(void) -{ - pci_unregister_driver(&netcell_pci_driver); -} - -module_init(netcell_init); -module_exit(netcell_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, netcell_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_ns87410.c b/trunk/drivers/ata/pata_ns87410.c deleted file mode 100644 index 93d6646d2954..000000000000 --- a/trunk/drivers/ata/pata_ns87410.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * pata_ns87410.c - National Semiconductor 87410 PATA for new ATA layer - * (C) 2006 Red Hat Inc - * Alan Cox - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_ns87410" -#define DRV_VERSION "0.4.2" - -/** - * ns87410_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int ns87410_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits ns87410_enable_bits[] = { - { 0x43, 1, 0x08, 0x08 }, - { 0x47, 1, 0x08, 0x08 } - }; - - if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * ns87410_error_handler - probe reset - * @ap: ATA port - * - * Perform the ATA probe and bus reset sequence plus specific handling - * for this hardware. The MPIIX has the enable bits in a different place - * to PIIX4 and friends. As a pure PIO device it has no cable detect - */ - -static void ns87410_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * ns87410_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program timing data. This is kept per channel not per device, - * and only affects the data port. - */ - -static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = 0x40 + 4 * ap->port_no; - u8 idetcr, idefr; - struct ata_timing at; - - static const u8 activebits[15] = { - 0, 1, 2, 3, 4, - 5, 5, 6, 6, 6, - 6, 7, 7, 7, 7 - }; - - static const u8 recoverbits[12] = { - 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7 - }; - - pci_read_config_byte(pdev, port + 3, &idefr); - - if (ata_pio_need_iordy(adev)) - idefr |= 0x04; /* IORDY enable */ - else - idefr &= ~0x04; - - if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) { - dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode); - return; - } - - at.active = FIT(at.active, 2, 16) - 2; - at.setup = FIT(at.setup, 1, 4) - 1; - at.recover = FIT(at.recover, 1, 12) - 1; - - idetcr = (at.setup << 6) | (recoverbits[at.recover] << 3) | activebits[at.active]; - - pci_write_config_byte(pdev, port, idetcr); - pci_write_config_byte(pdev, port + 3, idefr); - /* We use ap->private_data as a pointer to the device currently - loaded for timing */ - ap->private_data = adev; -} - -/** - * ns87410_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. - */ - -static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - /* If modes have been configured and the channel data is not loaded - then load it. We have to check if pio_mode is set as the core code - does not set adev->pio_mode to XFER_PIO_0 while probing as would be - logical */ - - if (adev->pio_mode && adev != ap->private_data) - ns87410_set_piomode(ap, adev); - - return ata_qc_issue_prot(qc); -} - -static struct scsi_host_template ns87410_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations ns87410_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = ns87410_set_piomode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ns87410_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ns87410_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &ns87410_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x0F, - .port_ops = &ns87410_port_ops - }; - static struct ata_port_info *port_info[2] = {&info, &info}; - return ata_pci_init_one(dev, port_info, 2); -} - -static const struct pci_device_id ns87410[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), }, - { 0, }, -}; - -static struct pci_driver ns87410_pci_driver = { - .name = DRV_NAME, - .id_table = ns87410, - .probe = ns87410_init_one, - .remove = ata_pci_remove_one -}; - -static int __init ns87410_init(void) -{ - return pci_register_driver(&ns87410_pci_driver); -} - - -static void __exit ns87410_exit(void) -{ - pci_unregister_driver(&ns87410_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Nat Semi 87410"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, ns87410); -MODULE_VERSION(DRV_VERSION); - -module_init(ns87410_init); -module_exit(ns87410_exit); diff --git a/trunk/drivers/ata/pata_oldpiix.c b/trunk/drivers/ata/pata_oldpiix.c deleted file mode 100644 index 04c618a2664b..000000000000 --- a/trunk/drivers/ata/pata_oldpiix.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * pata_oldpiix.c - Intel PATA/SATA controllers - * - * (C) 2005 Red Hat - * - * Some parts based on ata_piix.c by Jeff Garzik and others. - * - * Early PIIX differs significantly from the later PIIX as it lacks - * SITRE and the slave timing registers. This means that you have to - * set timing per channel, or be clever. Libata tells us whenever it - * does drive selection and we use this to reload the timings. - * - * Because of these behaviour differences PIIX gets its own driver module. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_oldpiix" -#define DRV_VERSION "0.5.1" - -/** - * oldpiix_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int oldpiix_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits oldpiix_enable_bits[] = { - { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ - { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ - }; - - if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * oldpiix_pata_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * @classes: - * - * LOCKING: - * None (inherited from caller). - */ - -static void oldpiix_pata_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * oldpiix_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set PIO mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void oldpiix_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *dev = to_pci_dev(ap->host->dev); - unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; - u16 idetm_data; - int control = 0; - - /* - * See Intel Document 298600-004 for the timing programing rules - * for PIIX/ICH. Note that the early PIIX does not have the slave - * timing port at 0x44. - */ - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - if (pio > 2) - control |= 1; /* TIME1 enable */ - if (ata_pio_need_iordy(adev)) - control |= 2; /* IE IORDY */ - - /* Intel specifies that the PPE functionality is for disk only */ - if (adev->class == ATA_DEV_ATA) - control |= 4; /* PPE enable */ - - pci_read_config_word(dev, idetm_port, &idetm_data); - - /* Enable PPE, IE and TIME as appropriate. Clear the other - drive timing bits */ - if (adev->devno == 0) { - idetm_data &= 0xCCE0; - idetm_data |= control; - } else { - idetm_data &= 0xCC0E; - idetm_data |= (control << 4); - } - idetm_data |= (timings[pio][0] << 12) | - (timings[pio][1] << 8); - pci_write_config_word(dev, idetm_port, idetm_data); - - /* Track which port is configured */ - ap->private_data = adev; -} - -/** - * oldpiix_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers - * - * Set MWDMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *dev = to_pci_dev(ap->host->dev); - u8 idetm_port = ap->port_no ? 0x42 : 0x40; - u16 idetm_data; - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - /* - * MWDMA is driven by the PIO timings. We must also enable - * IORDY unconditionally along with TIME1. PPE has already - * been set when the PIO timing was set. - */ - - unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; - unsigned int control; - const unsigned int needed_pio[3] = { - XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 - }; - int pio = needed_pio[mwdma] - XFER_PIO_0; - - pci_read_config_word(dev, idetm_port, &idetm_data); - - control = 3; /* IORDY|TIME0 */ - /* Intel specifies that the PPE functionality is for disk only */ - if (adev->class == ATA_DEV_ATA) - control |= 4; /* PPE enable */ - - /* If the drive MWDMA is faster than it can do PIO then - we must force PIO into PIO0 */ - - if (adev->pio_mode < needed_pio[mwdma]) - /* Enable DMA timing only */ - control |= 8; /* PIO cycles in PIO0 */ - - /* Mask out the relevant control and timing bits we will load. Also - clear the other drive TIME register as a precaution */ - if (adev->devno == 0) { - idetm_data &= 0xCCE0; - idetm_data |= control; - } else { - idetm_data &= 0xCC0E; - idetm_data |= (control << 4); - } - idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - pci_write_config_word(dev, idetm_port, idetm_data); - - /* Track which port is configured */ - ap->private_data = adev; -} - -/** - * oldpiix_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. Our logic also clears TIME0/TIME1 for the other device so - * that, even if we get this wrong, cycles to the other device will - * be made PIO0. - */ - -static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - if (adev != ap->private_data) { - if (adev->dma_mode) - oldpiix_set_dmamode(ap, adev); - else if (adev->pio_mode) - oldpiix_set_piomode(ap, adev); - } - return ata_qc_issue_prot(qc); -} - - -static struct scsi_host_template oldpiix_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations oldpiix_pata_ops = { - .port_disable = ata_port_disable, - .set_piomode = oldpiix_set_piomode, - .set_dmamode = oldpiix_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = oldpiix_pata_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = oldpiix_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * oldpiix_init_one - Register PIIX ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in oldpiix_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. We probe for combined mode (sigh), - * and then hand over control to libata, for it to do the rest. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - static struct ata_port_info info = { - .sht = &oldpiix_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .port_ops = &oldpiix_pata_ops, - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id oldpiix_pci_tbl[] = { - { PCI_DEVICE(0x8086, 0x1230), }, - { } /* terminate list */ -}; - -static struct pci_driver oldpiix_pci_driver = { - .name = DRV_NAME, - .id_table = oldpiix_pci_tbl, - .probe = oldpiix_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init oldpiix_init(void) -{ - return pci_register_driver(&oldpiix_pci_driver); -} - -static void __exit oldpiix_exit(void) -{ - pci_unregister_driver(&oldpiix_pci_driver); -} - - -module_init(oldpiix_init); -module_exit(oldpiix_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for early PIIX series controllers"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, oldpiix_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_opti.c b/trunk/drivers/ata/pata_opti.c deleted file mode 100644 index c3d01325e0e2..000000000000 --- a/trunk/drivers/ata/pata_opti.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * pata_opti.c - ATI PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based on - * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002 - * - * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) - * - * Authors: - * Jaromir Koutek , - * Jan Harkes , - * Mark Lord - * Some parts of code are from ali14xx.c and from rz1000.c. - * - * Also consulted the FreeBSD prototype driver by Kevin Day to try - * and resolve some confusions. Further documentation can be found in - * Ralf Brown's interrupt list - * - * If you have other variants of the Opti range (Viper/Vendetta) please - * try this driver with those PCI idents and report back. For the later - * chips see the pata_optidma driver - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_opti" -#define DRV_VERSION "0.2.4" - -enum { - READ_REG = 0, /* index of Read cycle timing register */ - WRITE_REG = 1, /* index of Write cycle timing register */ - CNTRL_REG = 3, /* index of Control register */ - STRAP_REG = 5, /* index of Strap register */ - MISC_REG = 6 /* index of Miscellaneous register */ -}; - -/** - * opti_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int opti_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits opti_enable_bits[] = { - { 0x45, 1, 0x80, 0x00 }, - { 0x40, 1, 0x08, 0x00 } - }; - - if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * opti_probe_reset - probe reset - * @ap: ATA port - * - * Perform the ATA probe and bus reset sequence plus specific handling - * for this hardware. The Opti needs little handling - we have no UDMA66 - * capability that needs cable detection. All we must do is check the port - * is enabled. - */ - -static void opti_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * opti_write_reg - control register setup - * @ap: ATA port - * @value: value - * @reg: control register number - * - * The Opti uses magic 'trapdoor' register accesses to do configuration - * rather than using PCI space as other controllers do. The double inw - * on the error register activates configuration mode. We can then write - * the control register - */ - -static void opti_write_reg(struct ata_port *ap, u8 val, int reg) -{ - unsigned long regio = ap->ioaddr.cmd_addr; - - /* These 3 unlock the control register access */ - inw(regio + 1); - inw(regio + 1); - outb(3, regio + 2); - - /* Do the I/O */ - outb(val, regio + reg); - - /* Relock */ - outb(0x83, regio + 2); -} - -#if 0 -/** - * opti_read_reg - control register read - * @ap: ATA port - * @reg: control register number - * - * The Opti uses magic 'trapdoor' register accesses to do configuration - * rather than using PCI space as other controllers do. The double inw - * on the error register activates configuration mode. We can then read - * the control register - */ - -static u8 opti_read_reg(struct ata_port *ap, int reg) -{ - unsigned long regio = ap->ioaddr.cmd_addr; - u8 ret; - inw(regio + 1); - inw(regio + 1); - outb(3, regio + 2); - ret = inb(regio + reg); - outb(0x83, regio + 2); -} -#endif - -/** - * opti_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. Timing numbers are taken from - * the FreeBSD driver then pre computed to keep the code clean. There - * are two tables depending on the hardware clock speed. - */ - -static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct ata_device *pair = ata_dev_pair(adev); - int clock; - int pio = adev->pio_mode - XFER_PIO_0; - unsigned long regio = ap->ioaddr.cmd_addr; - u8 addr; - - /* Address table precomputed with prefetch off and a DCLK of 2 */ - static const u8 addr_timing[2][5] = { - { 0x30, 0x20, 0x20, 0x10, 0x10 }, - { 0x20, 0x20, 0x10, 0x10, 0x10 } - }; - static const u8 data_rec_timing[2][5] = { - { 0x6B, 0x56, 0x42, 0x32, 0x31 }, - { 0x58, 0x44, 0x32, 0x22, 0x21 } - }; - - outb(0xff, regio + 5); - clock = inw(regio + 5) & 1; - - /* - * As with many controllers the address setup time is shared - * and must suit both devices if present. - */ - - addr = addr_timing[clock][pio]; - if (pair) { - /* Hardware constraint */ - u8 pair_addr = addr_timing[clock][pair->pio_mode - XFER_PIO_0]; - if (pair_addr > addr) - addr = pair_addr; - } - - /* Commence primary programming sequence */ - opti_write_reg(ap, adev->devno, MISC_REG); - opti_write_reg(ap, data_rec_timing[clock][pio], READ_REG); - opti_write_reg(ap, data_rec_timing[clock][pio], WRITE_REG); - opti_write_reg(ap, addr, MISC_REG); - - /* Programming sequence complete, override strapping */ - opti_write_reg(ap, 0x85, CNTRL_REG); -} - -static struct scsi_host_template opti_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations opti_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = opti_set_piomode, -/* .set_dmamode = opti_set_dmamode, */ - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = opti_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &opti_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &opti_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - static int printed_version; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - - return ata_pci_init_one(dev, port_info, 2); -} - -static const struct pci_device_id opti[] = { - { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { 0, }, -}; - -static struct pci_driver opti_pci_driver = { - .name = DRV_NAME, - .id_table = opti, - .probe = opti_init_one, - .remove = ata_pci_remove_one -}; - -static int __init opti_init(void) -{ - return pci_register_driver(&opti_pci_driver); -} - - -static void __exit opti_exit(void) -{ - pci_unregister_driver(&opti_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Opti 621/621X"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, opti); -MODULE_VERSION(DRV_VERSION); - -module_init(opti_init); -module_exit(opti_exit); diff --git a/trunk/drivers/ata/pata_optidma.c b/trunk/drivers/ata/pata_optidma.c deleted file mode 100644 index 177a455f4251..000000000000 --- a/trunk/drivers/ata/pata_optidma.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * pata_optidma.c - Opti DMA PATA for new ATA layer - * (C) 2006 Red Hat Inc - * Alan Cox - * - * The Opti DMA controllers are related to the older PIO PCI controllers - * and indeed the VLB ones. The main differences are that the timing - * numbers are now based off PCI clocks not VLB and differ, and that - * MWDMA is supported. - * - * This driver should support Viper-N+, FireStar, FireStar Plus. - * - * These devices support virtual DMA for read (aka the CS5520). Later - * chips support UDMA33, but only if the rest of the board logic does, - * so you have to get this right. We don't support the virtual DMA - * but we do handle UDMA. - * - * Bits that are worth knowing - * Most control registers are shadowed into I/O registers - * 0x1F5 bit 0 tells you if the PCI/VLB clock is 33 or 25Mhz - * Virtual DMA registers *move* between rev 0x02 and rev 0x10 - * UDMA requires a 66MHz FSB - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_optidma" -#define DRV_VERSION "0.2.1" - -enum { - READ_REG = 0, /* index of Read cycle timing register */ - WRITE_REG = 1, /* index of Write cycle timing register */ - CNTRL_REG = 3, /* index of Control register */ - STRAP_REG = 5, /* index of Strap register */ - MISC_REG = 6 /* index of Miscellaneous register */ -}; - -static int pci_clock; /* 0 = 33 1 = 25 */ - -/** - * optidma_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int optidma_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits optidma_enable_bits = { - 0x40, 1, 0x08, 0x00 - }; - - if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits)) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * optidma_probe_reset - probe reset - * @ap: ATA port - * - * Perform the ATA probe and bus reset sequence plus specific handling - * for this hardware. The Opti needs little handling - we have no UDMA66 - * capability that needs cable detection. All we must do is check the port - * is enabled. - */ - -static void optidma_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, optidma_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * optidma_unlock - unlock control registers - * @ap: ATA port - * - * Unlock the control register block for this adapter. Registers must not - * be unlocked in a situation where libata might look at them. - */ - -static void optidma_unlock(struct ata_port *ap) -{ - unsigned long regio = ap->ioaddr.cmd_addr; - - /* These 3 unlock the control register access */ - inw(regio + 1); - inw(regio + 1); - outb(3, regio + 2); -} - -/** - * optidma_lock - issue temporary relock - * @ap: ATA port - * - * Re-lock the configuration register settings. - */ - -static void optidma_lock(struct ata_port *ap) -{ - unsigned long regio = ap->ioaddr.cmd_addr; - - /* Relock */ - outb(0x83, regio + 2); -} - -/** - * optidma_set_mode - set mode data - * @ap: ATA interface - * @adev: ATA device - * @mode: Mode to set - * - * Called to do the DMA or PIO mode setup. Timing numbers are all - * pre computed to keep the code clean. There are two tables depending - * on the hardware clock speed. - * - * WARNING: While we do this the IDE registers vanish. If we take an - * IRQ here we depend on the host set locking to avoid catastrophe. - */ - -static void optidma_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mode) -{ - struct ata_device *pair = ata_dev_pair(adev); - int pio = adev->pio_mode - XFER_PIO_0; - int dma = adev->dma_mode - XFER_MW_DMA_0; - unsigned long regio = ap->ioaddr.cmd_addr; - u8 addr; - - /* Address table precomputed with a DCLK of 2 */ - static const u8 addr_timing[2][5] = { - { 0x30, 0x20, 0x20, 0x10, 0x10 }, - { 0x20, 0x20, 0x10, 0x10, 0x10 } - }; - static const u8 data_rec_timing[2][5] = { - { 0x59, 0x46, 0x30, 0x20, 0x20 }, - { 0x46, 0x32, 0x20, 0x20, 0x10 } - }; - static const u8 dma_data_rec_timing[2][3] = { - { 0x76, 0x20, 0x20 }, - { 0x54, 0x20, 0x10 } - }; - - /* Switch from IDE to control mode */ - optidma_unlock(ap); - - - /* - * As with many controllers the address setup time is shared - * and must suit both devices if present. FIXME: Check if we - * need to look at slowest of PIO/DMA mode of either device - */ - - if (mode >= XFER_MW_DMA_0) - addr = 0; - else - addr = addr_timing[pci_clock][pio]; - - if (pair) { - u8 pair_addr; - /* Hardware constraint */ - if (pair->dma_mode) - pair_addr = 0; - else - pair_addr = addr_timing[pci_clock][pair->pio_mode - XFER_PIO_0]; - if (pair_addr > addr) - addr = pair_addr; - } - - /* Commence primary programming sequence */ - /* First we load the device number into the timing select */ - outb(adev->devno, regio + MISC_REG); - /* Now we load the data timings into read data/write data */ - if (mode < XFER_MW_DMA_0) { - outb(data_rec_timing[pci_clock][pio], regio + READ_REG); - outb(data_rec_timing[pci_clock][pio], regio + WRITE_REG); - } else if (mode < XFER_UDMA_0) { - outb(dma_data_rec_timing[pci_clock][dma], regio + READ_REG); - outb(dma_data_rec_timing[pci_clock][dma], regio + WRITE_REG); - } - /* Finally we load the address setup into the misc register */ - outb(addr | adev->devno, regio + MISC_REG); - - /* Programming sequence complete, timing 0 dev 0, timing 1 dev 1 */ - outb(0x85, regio + CNTRL_REG); - - /* Switch back to IDE mode */ - optidma_lock(ap); - - /* Note: at this point our programming is incomplete. We are - not supposed to program PCI 0x43 "things we hacked onto the chip" - until we've done both sets of PIO/DMA timings */ -} - -/** - * optiplus_set_mode - DMA setup for Firestar Plus - * @ap: ATA port - * @adev: device - * @mode: desired mode - * - * The Firestar plus has additional UDMA functionality for UDMA0-2 and - * requires we do some additional work. Because the base work we must do - * is mostly shared we wrap the Firestar setup functionality in this - * one - */ - -static void optiplus_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mode) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 udcfg; - u8 udslave; - int dev2 = 2 * adev->devno; - int unit = 2 * ap->port_no + adev->devno; - int udma = mode - XFER_UDMA_0; - - pci_read_config_byte(pdev, 0x44, &udcfg); - if (mode <= XFER_UDMA_0) { - udcfg &= ~(1 << unit); - optidma_set_mode(ap, adev, adev->dma_mode); - } else { - udcfg |= (1 << unit); - if (ap->port_no) { - pci_read_config_byte(pdev, 0x45, &udslave); - udslave &= ~(0x03 << dev2); - udslave |= (udma << dev2); - pci_write_config_byte(pdev, 0x45, udslave); - } else { - udcfg &= ~(0x30 << dev2); - udcfg |= (udma << dev2); - } - } - pci_write_config_byte(pdev, 0x44, udcfg); -} - -/** - * optidma_set_pio_mode - PIO setup callback - * @ap: ATA port - * @adev: Device - * - * The libata core provides separate functions for handling PIO and - * DMA programming. The architecture of the Firestar makes it easier - * for us to have a common function so we provide wrappers - */ - -static void optidma_set_pio_mode(struct ata_port *ap, struct ata_device *adev) -{ - optidma_set_mode(ap, adev, adev->pio_mode); -} - -/** - * optidma_set_dma_mode - DMA setup callback - * @ap: ATA port - * @adev: Device - * - * The libata core provides separate functions for handling PIO and - * DMA programming. The architecture of the Firestar makes it easier - * for us to have a common function so we provide wrappers - */ - -static void optidma_set_dma_mode(struct ata_port *ap, struct ata_device *adev) -{ - optidma_set_mode(ap, adev, adev->dma_mode); -} - -/** - * optiplus_set_pio_mode - PIO setup callback - * @ap: ATA port - * @adev: Device - * - * The libata core provides separate functions for handling PIO and - * DMA programming. The architecture of the Firestar makes it easier - * for us to have a common function so we provide wrappers - */ - -static void optiplus_set_pio_mode(struct ata_port *ap, struct ata_device *adev) -{ - optiplus_set_mode(ap, adev, adev->pio_mode); -} - -/** - * optiplus_set_dma_mode - DMA setup callback - * @ap: ATA port - * @adev: Device - * - * The libata core provides separate functions for handling PIO and - * DMA programming. The architecture of the Firestar makes it easier - * for us to have a common function so we provide wrappers - */ - -static void optiplus_set_dma_mode(struct ata_port *ap, struct ata_device *adev) -{ - optiplus_set_mode(ap, adev, adev->dma_mode); -} - -/** - * optidma_make_bits - PCI setup helper - * @adev: ATA device - * - * Turn the ATA device setup into PCI configuration bits - * for register 0x43 and return the two bits needed. - */ - -static u8 optidma_make_bits43(struct ata_device *adev) -{ - static const u8 bits43[5] = { - 0, 0, 0, 1, 2 - }; - if (!ata_dev_enabled(adev)) - return 0; - if (adev->dma_mode) - return adev->dma_mode - XFER_MW_DMA_0; - return bits43[adev->pio_mode - XFER_PIO_0]; -} - -/** - * optidma_post_set_mode - finalize PCI setup - * @ap: port to set up - * - * Finalise the configuration by writing the nibble of extra bits - * of data into the chip. - */ - -static void optidma_post_set_mode(struct ata_port *ap) -{ - u8 r; - int nybble = 4 * ap->port_no; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, 0x43, &r); - - r &= (0x0F << nybble); - r |= (optidma_make_bits43(&ap->device[0]) + - (optidma_make_bits43(&ap->device[0]) << 2)) << nybble; - - pci_write_config_byte(pdev, 0x43, r); -} - -static struct scsi_host_template optidma_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations optidma_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = optidma_set_pio_mode, - .set_dmamode = optidma_set_dma_mode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .error_handler = optidma_error_handler, - .post_set_mode = optidma_post_set_mode, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations optiplus_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = optiplus_set_pio_mode, - .set_dmamode = optiplus_set_dma_mode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .error_handler = optidma_error_handler, - .post_set_mode = optidma_post_set_mode, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * optiplus_with_udma - Look for UDMA capable setup - * @pdev; ATA controller - */ - -static int optiplus_with_udma(struct pci_dev *pdev) -{ - u8 r; - int ret = 0; - int ioport = 0x22; - struct pci_dev *dev1; - - /* Find function 1 */ - dev1 = pci_get_device(0x1045, 0xC701, NULL); - if(dev1 == NULL) - return 0; - - /* Rev must be >= 0x10 */ - pci_read_config_byte(dev1, 0x08, &r); - if (r < 0x10) - goto done_nomsg; - /* Read the chipset system configuration to check our mode */ - pci_read_config_byte(dev1, 0x5F, &r); - ioport |= (r << 8); - outb(0x10, ioport); - /* Must be 66Mhz sync */ - if ((inb(ioport + 2) & 1) == 0) - goto done; - - /* Check the ATA arbitration/timing is suitable */ - pci_read_config_byte(pdev, 0x42, &r); - if ((r & 0x36) != 0x36) - goto done; - pci_read_config_byte(dev1, 0x52, &r); - if (r & 0x80) /* IDEDIR disabled */ - ret = 1; -done: - printk(KERN_WARNING "UDMA not supported in this configuration.\n"); -done_nomsg: /* Wrong chip revision */ - pci_dev_put(dev1); - return ret; -} - -static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info_82c700 = { - .sht = &optidma_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &optidma_port_ops - }; - static struct ata_port_info info_82c700_udma = { - .sht = &optidma_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &optiplus_port_ops - }; - static struct ata_port_info *port_info[2]; - struct ata_port_info *info = &info_82c700; - static int printed_version; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - - /* Fixed location chipset magic */ - inw(0x1F1); - inw(0x1F1); - pci_clock = inb(0x1F5) & 1; /* 0 = 33Mhz, 1 = 25Mhz */ - - if (optiplus_with_udma(dev)) - info = &info_82c700_udma; - - port_info[0] = port_info[1] = info; - return ata_pci_init_one(dev, port_info, 2); -} - -static const struct pci_device_id optidma[] = { - { PCI_DEVICE(0x1045, 0xD568), }, /* Opti 82C700 */ - { 0, }, -}; - -static struct pci_driver optidma_pci_driver = { - .name = DRV_NAME, - .id_table = optidma, - .probe = optidma_init_one, - .remove = ata_pci_remove_one -}; - -static int __init optidma_init(void) -{ - return pci_register_driver(&optidma_pci_driver); -} - - -static void __exit optidma_exit(void) -{ - pci_unregister_driver(&optidma_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Opti Firestar/Firestar Plus"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, optidma); -MODULE_VERSION(DRV_VERSION); - -module_init(optidma_init); -module_exit(optidma_exit); diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c deleted file mode 100644 index 62b25cda409b..000000000000 --- a/trunk/drivers/ata/pata_pcmcia.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * pata_pcmcia.c - PCMCIA PATA controller driver. - * Copyright 2005-2006 Red Hat Inc , all rights reserved. - * PCMCIA ident update Copyright 2006 Marcin Juszkiewicz - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Heavily based upon ide-cs.c - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#define DRV_NAME "pata_pcmcia" -#define DRV_VERSION "0.2.9" - -/* - * Private data structure to glue stuff together - */ - -struct ata_pcmcia_info { - struct pcmcia_device *pdev; - int ndev; - dev_node_t node; -}; - -static struct scsi_host_template pcmcia_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations pcmcia_port_ops = { - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer_noirq, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -/** - * pcmcia_init_one - attach a PCMCIA interface - * @pdev: pcmcia device - * - * Register a PCMCIA IDE interface. Such interfaces are PIO 0 and - * shared IRQ. - */ - -static int pcmcia_init_one(struct pcmcia_device *pdev) -{ - struct ata_probe_ent ae; - struct ata_pcmcia_info *info; - tuple_t tuple; - struct { - unsigned short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t dflt; - } *stk = NULL; - cistpl_cftable_entry_t *cfg; - int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM; - unsigned long io_base, ctl_base; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) - return -ENOMEM; - - /* Glue stuff together. FIXME: We may be able to get rid of info with care */ - info->pdev = pdev; - pdev->priv = info; - - /* Set up attributes in order to probe card and get resources */ - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - pdev->io.IOAddrLines = 3; - pdev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - pdev->irq.IRQInfo1 = IRQ_LEVEL_ID; - pdev->conf.Attributes = CONF_ENABLE_IRQ; - pdev->conf.IntType = INT_MEMORY_AND_IO; - - /* Allocate resoure probing structures */ - - stk = kzalloc(sizeof(*stk), GFP_KERNEL); - if (!stk) - goto out1; - - cfg = &stk->parse.cftable_entry; - - /* Tuples we are walking */ - tuple.TupleData = (cisdata_t *)&stk->buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, &stk->parse)); - pdev->conf.ConfigBase = stk->parse.config.base; - pdev->conf.Present = stk->parse.config.rmask[0]; - - /* See if we have a manufacturer identifier. Use it to set is_kme for - vendor quirks */ - tuple.DesiredTuple = CISTPL_MANFID; - if (!pcmcia_get_first_tuple(pdev, &tuple) && !pcmcia_get_tuple_data(pdev, &tuple) && !pcmcia_parse_tuple(pdev, &tuple, &stk->parse)) - is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); - - /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf)); -/* link->conf.Vcc = stk->conf.Vcc; */ - - pass = io_base = ctl_base = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - - /* Now munch the resources looking for a suitable set */ - while (1) { - if (pcmcia_get_tuple_data(pdev, &tuple) != 0) - goto next_entry; - if (pcmcia_parse_tuple(pdev, &tuple, &stk->parse) != 0) - goto next_entry; - /* Check for matching Vcc, unless we're desperate */ - if (!pass) { - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) - goto next_entry; - } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) - goto next_entry; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - pdev->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; - - if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; - pdev->conf.ConfigIndex = cfg->index; - pdev->io.BasePort1 = io->win[0].base; - pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - if (io->nwin == 2) { - pdev->io.NumPorts1 = 8; - pdev->io.BasePort2 = io->win[1].base; - pdev->io.NumPorts2 = (is_kme) ? 2 : 1; - if (pcmcia_request_io(pdev, &pdev->io) != 0) - goto next_entry; - io_base = pdev->io.BasePort1; - ctl_base = pdev->io.BasePort2; - } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - pdev->io.NumPorts1 = io->win[0].len; - pdev->io.NumPorts2 = 0; - if (pcmcia_request_io(pdev, &pdev->io) != 0) - goto next_entry; - io_base = pdev->io.BasePort1; - ctl_base = pdev->io.BasePort1 + 0x0e; - } else goto next_entry; - /* If we've got this far, we're done */ - break; - } -next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); - if (pass) { - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple)); - } else if (pcmcia_get_next_tuple(pdev, &tuple) != 0) { - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - memset(&stk->dflt, 0, sizeof(stk->dflt)); - pass++; - } - } - - CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); - - /* Success. Disable the IRQ nIEN line, do quirks */ - outb(0x02, ctl_base); - if (is_kme) - outb(0x81, ctl_base + 0x01); - - /* FIXME: Could be more ports at base + 0x10 but we only deal with - one right now */ - if (pdev->io.NumPorts1 >= 0x20) - printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n"); - - /* - * Having done the PCMCIA plumbing the ATA side is relatively - * sane. - */ - - memset(&ae, 0, sizeof(struct ata_probe_ent)); - INIT_LIST_HEAD(&ae.node); - ae.dev = &pdev->dev; - ae.port_ops = &pcmcia_port_ops; - ae.sht = &pcmcia_sht; - ae.n_ports = 1; - ae.pio_mask = 1; /* ISA so PIO 0 cycles */ - ae.irq = pdev->irq.AssignedIRQ; - ae.irq_flags = SA_SHIRQ; - ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; - ae.port[0].cmd_addr = io_base; - ae.port[0].altstatus_addr = ctl_base; - ae.port[0].ctl_addr = ctl_base; - ata_std_ports(&ae.port[0]); - - if (ata_device_add(&ae) == 0) - goto failed; - - info->ndev = 1; - kfree(stk); - return 0; - -cs_failed: - cs_error(pdev, last_fn, last_ret); -failed: - kfree(stk); - info->ndev = 0; - pcmcia_disable_device(pdev); -out1: - kfree(info); - return ret; -} - -/** - * pcmcia_remove_one - unplug an pcmcia interface - * @pdev: pcmcia device - * - * A PCMCIA ATA device has been unplugged. Perform the needed - * cleanup. Also called on module unload for any active devices. - */ - -static void pcmcia_remove_one(struct pcmcia_device *pdev) -{ - struct ata_pcmcia_info *info = pdev->priv; - struct device *dev = &pdev->dev; - - if (info != NULL) { - /* If we have attached the device to the ATA layer, detach it */ - if (info->ndev) { - struct ata_host *host = dev_get_drvdata(dev); - ata_host_remove(host); - dev_set_drvdata(dev, NULL); - } - info->ndev = 0; - pdev->priv = NULL; - } - pcmcia_disable_device(pdev); - kfree(info); -} - -static struct pcmcia_device_id pcmcia_devices[] = { - PCMCIA_DEVICE_FUNC_ID(4), - PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), - PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ - PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), - PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ - PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ - PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */ - PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), - PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), - PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), - PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf), - PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), - PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), - PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), - PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c), - PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), - PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883), - PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d), - PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), - PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), - PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), - PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), - PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), - PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), - PCMCIA_DEVICE_NULL, -}; - -MODULE_DEVICE_TABLE(pcmcia, pcmcia_devices); - -static struct pcmcia_driver pcmcia_driver = { - .owner = THIS_MODULE, - .drv = { - .name = DRV_NAME, - }, - .id_table = pcmcia_devices, - .probe = pcmcia_init_one, - .remove = pcmcia_remove_one, -}; - -static int __init pcmcia_init(void) -{ - return pcmcia_register_driver(&pcmcia_driver); -} - -static void __exit pcmcia_exit(void) -{ - pcmcia_unregister_driver(&pcmcia_driver); -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for PCMCIA ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(pcmcia_init); -module_exit(pcmcia_exit); diff --git a/trunk/drivers/ata/pata_pdc2027x.c b/trunk/drivers/ata/pata_pdc2027x.c deleted file mode 100644 index 56b8c1ee2937..000000000000 --- a/trunk/drivers/ata/pata_pdc2027x.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Ported to libata by: - * Albert Lee IBM Corporation - * - * Copyright (C) 1998-2002 Andre Hedrick - * Portions Copyright (C) 1999 Promise Technology, Inc. - * - * Author: Frank Tiernan (frankt@promise.com) - * Released under terms of General Public License - * - * - * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* - * - * Hardware information only available under NDA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_pdc2027x" -#define DRV_VERSION "0.74-ac3" -#undef PDC_DEBUG - -#ifdef PDC_DEBUG -#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) -#else -#define PDPRINTK(fmt, args...) -#endif - -enum { - PDC_UDMA_100 = 0, - PDC_UDMA_133 = 1, - - PDC_100_MHZ = 100000000, - PDC_133_MHZ = 133333333, - - PDC_SYS_CTL = 0x1100, - PDC_ATA_CTL = 0x1104, - PDC_GLOBAL_CTL = 0x1108, - PDC_CTCR0 = 0x110C, - PDC_CTCR1 = 0x1110, - PDC_BYTE_COUNT = 0x1120, - PDC_PLL_CTL = 0x1202, -}; - -static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc2027x_remove_one(struct pci_dev *pdev); -static void pdc2027x_error_handler(struct ata_port *ap); -static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev); -static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); -static void pdc2027x_post_set_mode(struct ata_port *ap); -static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc); - -/* - * ATA Timing Tables based on 133MHz controller clock. - * These tables are only used when the controller is in 133MHz clock. - * If the controller is in 100MHz clock, the ASIC hardware will - * set the timing registers automatically when "set feature" command - * is issued to the device. However, if the controller clock is 133MHz, - * the following tables must be used. - */ -static struct pdc2027x_pio_timing { - u8 value0, value1, value2; -} pdc2027x_pio_timing_tbl [] = { - { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ - { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ - { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ - { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ - { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ -}; - -static struct pdc2027x_mdma_timing { - u8 value0, value1; -} pdc2027x_mdma_timing_tbl [] = { - { 0xdf, 0x5f }, /* MDMA mode 0 */ - { 0x6b, 0x27 }, /* MDMA mode 1 */ - { 0x69, 0x25 }, /* MDMA mode 2 */ -}; - -static struct pdc2027x_udma_timing { - u8 value0, value1, value2; -} pdc2027x_udma_timing_tbl [] = { - { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ - { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ - { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ - { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ - { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ - { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ - { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ -}; - -static const struct pci_device_id pdc2027x_pci_tbl[] = { - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, - { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, - { } /* terminate list */ -}; - -static struct pci_driver pdc2027x_pci_driver = { - .name = DRV_NAME, - .id_table = pdc2027x_pci_tbl, - .probe = pdc2027x_init_one, - .remove = __devexit_p(pdc2027x_remove_one), -}; - -static struct scsi_host_template pdc2027x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations pdc2027x_pata100_ops = { - .port_disable = ata_port_disable, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .check_atapi_dma = pdc2027x_check_atapi_dma, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_mmio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = pdc2027x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_pci_host_stop, -}; - -static struct ata_port_operations pdc2027x_pata133_ops = { - .port_disable = ata_port_disable, - .set_piomode = pdc2027x_set_piomode, - .set_dmamode = pdc2027x_set_dmamode, - .post_set_mode = pdc2027x_post_set_mode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .check_atapi_dma = pdc2027x_check_atapi_dma, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_mmio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = pdc2027x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_pci_host_stop, -}; - -static struct ata_port_info pdc2027x_port_info[] = { - /* PDC_UDMA_100 */ - { - .sht = &pdc2027x_sht, - .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | - ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ - .port_ops = &pdc2027x_pata100_ops, - }, - /* PDC_UDMA_133 */ - { - .sht = &pdc2027x_sht, - .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | - ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, /* udma0-6 */ - .port_ops = &pdc2027x_pata133_ops, - }, -}; - -MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); -MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl); - -/** - * port_mmio - Get the MMIO address of PDC2027x extended registers - * @ap: Port - * @offset: offset from mmio base - */ -static inline void* port_mmio(struct ata_port *ap, unsigned int offset) -{ - return ap->host->mmio_base + ap->port_no * 0x100 + offset; -} - -/** - * dev_mmio - Get the MMIO address of PDC2027x extended registers - * @ap: Port - * @adev: device - * @offset: offset from mmio base - */ -static inline void* dev_mmio(struct ata_port *ap, struct ata_device *adev, unsigned int offset) -{ - u8 adj = (adev->devno) ? 0x08 : 0x00; - return port_mmio(ap, offset) + adj; -} - -/** - * pdc2027x_pata_cbl_detect - Probe host controller cable detect info - * @ap: Port for which cable detect info is desired - * - * Read 80c cable indicator from Promise extended register. - * This register is latched when the system is reset. - * - * LOCKING: - * None (inherited from caller). - */ -static void pdc2027x_cbl_detect(struct ata_port *ap) -{ - u32 cgcr; - - /* check cable detect results */ - cgcr = readl(port_mmio(ap, PDC_GLOBAL_CTL)); - if (cgcr & (1 << 26)) - goto cbl40; - - PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); - - ap->cbl = ATA_CBL_PATA80; - return; - -cbl40: - printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", ap->port_no); - ap->cbl = ATA_CBL_PATA40; - ap->udma_mask &= ATA_UDMA_MASK_40C; -} - -/** - * pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled. - * @ap: Port to check - */ -static inline int pdc2027x_port_enabled(struct ata_port *ap) -{ - return readb(port_mmio(ap, PDC_ATA_CTL)) & 0x02; -} - -/** - * pdc2027x_prereset - prereset for PATA host controller - * @ap: Target port - * - * Probeinit including cable detection. - * - * LOCKING: - * None (inherited from caller). - */ - -static int pdc2027x_prereset(struct ata_port *ap) -{ - /* Check whether port enabled */ - if (!pdc2027x_port_enabled(ap)) { - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - pdc2027x_cbl_detect(ap); - return ata_std_prereset(ap); -} - -/** - * pdc2027x_error_handler - Perform reset on PATA port and classify - * @ap: Port to reset - * - * Reset PATA phy and classify attached devices. - * - * LOCKING: - * None (inherited from caller). - */ - -static void pdc2027x_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, pdc2027x_prereset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * pdc2027x_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port to configure - * @adev: um - * @pio: PIO mode, 0 - 4 - * - * Set PIO mode for device. - * - * LOCKING: - * None (inherited from caller). - */ - -static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio = adev->pio_mode - XFER_PIO_0; - u32 ctcr0, ctcr1; - - PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode); - - /* Sanity check */ - if (pio > 4) { - printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); - return; - - } - - /* Set the PIO timing registers using value table for 133MHz */ - PDPRINTK("Set pio regs... \n"); - - ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); - ctcr0 &= 0xffff0000; - ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | - (pdc2027x_pio_timing_tbl[pio].value1 << 8); - writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); - - ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); - ctcr1 &= 0x00ffffff; - ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); - writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); - - PDPRINTK("Set pio regs done\n"); - - PDPRINTK("Set to pio mode[%u] \n", pio); -} - -/** - * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings - * @ap: Port to configure - * @adev: um - * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 - * - * Set UDMA mode for device. - * - * LOCKING: - * None (inherited from caller). - */ -static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - unsigned int dma_mode = adev->dma_mode; - u32 ctcr0, ctcr1; - - if ((dma_mode >= XFER_UDMA_0) && - (dma_mode <= XFER_UDMA_6)) { - /* Set the UDMA timing registers with value table for 133MHz */ - unsigned int udma_mode = dma_mode & 0x07; - - if (dma_mode == XFER_UDMA_2) { - /* - * Turn off tHOLD. - * If tHOLD is '1', the hardware will add half clock for data hold time. - * This code segment seems to be no effect. tHOLD will be overwritten below. - */ - ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); - writel(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); - } - - PDPRINTK("Set udma regs... \n"); - - ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); - ctcr1 &= 0xff000000; - ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | - (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | - (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); - writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); - - PDPRINTK("Set udma regs done\n"); - - PDPRINTK("Set to udma mode[%u] \n", udma_mode); - - } else if ((dma_mode >= XFER_MW_DMA_0) && - (dma_mode <= XFER_MW_DMA_2)) { - /* Set the MDMA timing registers with value table for 133MHz */ - unsigned int mdma_mode = dma_mode & 0x07; - - PDPRINTK("Set mdma regs... \n"); - ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); - - ctcr0 &= 0x0000ffff; - ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | - (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); - - writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); - PDPRINTK("Set mdma regs done\n"); - - PDPRINTK("Set to mdma mode[%u] \n", mdma_mode); - } else { - printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode); - } -} - -/** - * pdc2027x_post_set_mode - Set the timing registers back to correct values. - * @ap: Port to configure - * - * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers - * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL. - * This function overwrites the possibly incorrect values set by the hardware to be correct. - */ -static void pdc2027x_post_set_mode(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - - if (ata_dev_enabled(dev)) { - - pdc2027x_set_piomode(ap, dev); - - /* - * Enable prefetch if the device support PIO only. - */ - if (dev->xfer_shift == ATA_SHIFT_PIO) { - u32 ctcr1 = readl(dev_mmio(ap, dev, PDC_CTCR1)); - ctcr1 |= (1 << 25); - writel(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); - - PDPRINTK("Turn on prefetch\n"); - } else { - pdc2027x_set_dmamode(ap, dev); - } - } - } -} - -/** - * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command - * @qc: Metadata associated with taskfile to check - * - * LOCKING: - * None (inherited from caller). - * - * RETURNS: 0 when ATAPI DMA can be used - * 1 otherwise - */ -static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *cmd = qc->scsicmd; - u8 *scsicmd = cmd->cmnd; - int rc = 1; /* atapi dma off by default */ - - /* - * This workaround is from Promise's GPL driver. - * If ATAPI DMA is used for commands not in the - * following white list, say MODE_SENSE and REQUEST_SENSE, - * pdc2027x might hit the irq lost problem. - */ - switch (scsicmd[0]) { - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - case READ_6: - case WRITE_6: - case 0xad: /* READ_DVD_STRUCTURE */ - case 0xbe: /* READ_CD */ - /* ATAPI DMA is ok */ - rc = 0; - break; - default: - ; - } - - return rc; -} - -/** - * pdc_read_counter - Read the ctr counter - * @probe_ent: for the port address - */ - -static long pdc_read_counter(struct ata_probe_ent *probe_ent) -{ - long counter; - int retry = 1; - u32 bccrl, bccrh, bccrlv, bccrhv; - -retry: - bccrl = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; - bccrh = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; - rmb(); - - /* Read the counter values again for verification */ - bccrlv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; - bccrhv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; - rmb(); - - counter = (bccrh << 15) | bccrl; - - PDPRINTK("bccrh [%X] bccrl [%X]\n", bccrh, bccrl); - PDPRINTK("bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv); - - /* - * The 30-bit decreasing counter are read by 2 pieces. - * Incorrect value may be read when both bccrh and bccrl are changing. - * Ex. When 7900 decrease to 78FF, wrong value 7800 might be read. - */ - if (retry && !(bccrh == bccrhv && bccrl >= bccrlv)) { - retry--; - PDPRINTK("rereading counter\n"); - goto retry; - } - - return counter; -} - -/** - * adjust_pll - Adjust the PLL input clock in Hz. - * - * @pdc_controller: controller specific information - * @probe_ent: For the port address - * @pll_clock: The input of PLL in HZ - */ -static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx) -{ - - u16 pll_ctl; - long pll_clock_khz = pll_clock / 1000; - long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ; - long ratio = pout_required / pll_clock_khz; - int F, R; - - /* Sanity check */ - if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { - printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n", pll_clock_khz); - return; - } - -#ifdef PDC_DEBUG - PDPRINTK("pout_required is %ld\n", pout_required); - - /* Show the current clock value of PLL control register - * (maybe already configured by the firmware) - */ - pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); - - PDPRINTK("pll_ctl[%X]\n", pll_ctl); -#endif - - /* - * Calculate the ratio of F, R and OD - * POUT = (F + 2) / (( R + 2) * NO) - */ - if (ratio < 8600L) { /* 8.6x */ - /* Using NO = 0x01, R = 0x0D */ - R = 0x0d; - } else if (ratio < 12900L) { /* 12.9x */ - /* Using NO = 0x01, R = 0x08 */ - R = 0x08; - } else if (ratio < 16100L) { /* 16.1x */ - /* Using NO = 0x01, R = 0x06 */ - R = 0x06; - } else if (ratio < 64000L) { /* 64x */ - R = 0x00; - } else { - /* Invalid ratio */ - printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio); - return; - } - - F = (ratio * (R+2)) / 1000 - 2; - - if (unlikely(F < 0 || F > 127)) { - /* Invalid F */ - printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F); - return; - } - - PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); - - pll_ctl = (R << 8) | F; - - PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl); - - writew(pll_ctl, probe_ent->mmio_base + PDC_PLL_CTL); - readw(probe_ent->mmio_base + PDC_PLL_CTL); /* flush */ - - /* Wait the PLL circuit to be stable */ - mdelay(30); - -#ifdef PDC_DEBUG - /* - * Show the current clock value of PLL control register - * (maybe configured by the firmware) - */ - pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); - - PDPRINTK("pll_ctl[%X]\n", pll_ctl); -#endif - - return; -} - -/** - * detect_pll_input_clock - Detect the PLL input clock in Hz. - * @probe_ent: for the port address - * Ex. 16949000 on 33MHz PCI bus for pdc20275. - * Half of the PCI clock. - */ -static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent) -{ - u32 scr; - long start_count, end_count; - long pll_clock; - - /* Read current counter value */ - start_count = pdc_read_counter(probe_ent); - - /* Start the test mode */ - scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); - PDPRINTK("scr[%X]\n", scr); - writel(scr | (0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); - readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ - - /* Let the counter run for 100 ms. */ - mdelay(100); - - /* Read the counter values again */ - end_count = pdc_read_counter(probe_ent); - - /* Stop the test mode */ - scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); - PDPRINTK("scr[%X]\n", scr); - writel(scr & ~(0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); - readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ - - /* calculate the input clock in Hz */ - pll_clock = (start_count - end_count) * 10; - - PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count); - PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock); - - return pll_clock; -} - -/** - * pdc_hardware_init - Initialize the hardware. - * @pdev: instance of pci_dev found - * @pdc_controller: controller specific information - * @pe: for the port address - */ -static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, unsigned int board_idx) -{ - long pll_clock; - - /* - * Detect PLL input clock rate. - * On some system, where PCI bus is running at non-standard clock rate. - * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. - * The pdc20275 controller employs PLL circuit to help correct timing registers setting. - */ - pll_clock = pdc_detect_pll_input_clock(pe); - - if (pll_clock < 0) /* counter overflow? Try again. */ - pll_clock = pdc_detect_pll_input_clock(pe); - - dev_printk(KERN_INFO, &pdev->dev, "PLL input clock %ld kHz\n", pll_clock/1000); - - /* Adjust PLL control register */ - pdc_adjust_pll(pe, pll_clock, board_idx); - - return 0; -} - -/** - * pdc_ata_setup_port - setup the mmio address - * @port: ata ioports to setup - * @base: base address - */ -static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) -{ - port->cmd_addr = - port->data_addr = base; - port->feature_addr = - port->error_addr = base + 0x05; - port->nsect_addr = base + 0x0a; - port->lbal_addr = base + 0x0f; - port->lbam_addr = base + 0x10; - port->lbah_addr = base + 0x15; - port->device_addr = base + 0x1a; - port->command_addr = - port->status_addr = base + 0x1f; - port->altstatus_addr = - port->ctl_addr = base + 0x81a; -} - -/** - * pdc2027x_init_one - PCI probe function - * Called when an instance of PCI adapter is inserted. - * This function checks whether the hardware is supported, - * initialize hardware and register an instance of ata_host to - * libata by providing struct ata_probe_ent and ata_device_add(). - * (implements struct pci_driver.probe() ) - * - * @pdev: instance of pci_dev found - * @ent: matching entry in the id_tbl[] - */ -static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - unsigned int board_idx = (unsigned int) ent->driver_data; - - struct ata_probe_ent *probe_ent = NULL; - unsigned long base; - void *mmio_base; - int rc; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - - rc = pci_enable_device(pdev); - if (rc) - return rc; - - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) - goto err_out; - - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - - /* Prepare the probe entry */ - probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); - if (probe_ent == NULL) { - rc = -ENOMEM; - goto err_out_regions; - } - - probe_ent->dev = pci_dev_to_dev(pdev); - INIT_LIST_HEAD(&probe_ent->node); - - mmio_base = pci_iomap(pdev, 5, 0); - if (!mmio_base) { - rc = -ENOMEM; - goto err_out_free_ent; - } - - base = (unsigned long) mmio_base; - - probe_ent->sht = pdc2027x_port_info[board_idx].sht; - probe_ent->port_flags = pdc2027x_port_info[board_idx].flags; - probe_ent->pio_mask = pdc2027x_port_info[board_idx].pio_mask; - probe_ent->mwdma_mask = pdc2027x_port_info[board_idx].mwdma_mask; - probe_ent->udma_mask = pdc2027x_port_info[board_idx].udma_mask; - probe_ent->port_ops = pdc2027x_port_info[board_idx].port_ops; - - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - probe_ent->mmio_base = mmio_base; - - pdc_ata_setup_port(&probe_ent->port[0], base + 0x17c0); - probe_ent->port[0].bmdma_addr = base + 0x1000; - pdc_ata_setup_port(&probe_ent->port[1], base + 0x15c0); - probe_ent->port[1].bmdma_addr = base + 0x1008; - - probe_ent->n_ports = 2; - - pci_set_master(pdev); - //pci_enable_intx(pdev); - - /* initialize adapter */ - if (pdc_hardware_init(pdev, probe_ent, board_idx) != 0) - goto err_out_free_ent; - - ata_device_add(probe_ent); - kfree(probe_ent); - - return 0; - -err_out_free_ent: - kfree(probe_ent); -err_out_regions: - pci_release_regions(pdev); -err_out: - pci_disable_device(pdev); - return rc; -} - -/** - * pdc2027x_remove_one - Called to remove a single instance of the - * adapter. - * - * @dev: The PCI device to remove. - * FIXME: module load/unload not working yet - */ -static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) -{ - ata_pci_remove_one(pdev); -} - -/** - * pdc2027x_init - Called after this module is loaded into the kernel. - */ -static int __init pdc2027x_init(void) -{ - return pci_module_init(&pdc2027x_pci_driver); -} - -/** - * pdc2027x_exit - Called before this module unloaded from the kernel - */ -static void __exit pdc2027x_exit(void) -{ - pci_unregister_driver(&pdc2027x_pci_driver); -} - -module_init(pdc2027x_init); -module_exit(pdc2027x_exit); diff --git a/trunk/drivers/ata/pata_pdc202xx_old.c b/trunk/drivers/ata/pata_pdc202xx_old.c deleted file mode 100644 index 48f43432764e..000000000000 --- a/trunk/drivers/ata/pata_pdc202xx_old.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * pata_pdc202xx_old.c - Promise PDC202xx PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based in part on linux/drivers/ide/pci/pdc202xx_old.c - * - * First cut with LBA48/ATAPI - * - * TODO: - * Channel interlock/reset on both required ? - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_pdc202xx_old" -#define DRV_VERSION "0.2.1" - -/** - * pdc2024x_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int pdc2024x_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - - -static void pdc2024x_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, pdc2024x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - - -static int pdc2026x_pre_reset(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u16 cis; - - pci_read_config_word(pdev, 0x50, &cis); - if (cis & (1 << (10 + ap->port_no))) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - - return ata_std_prereset(ap); -} - -static void pdc2026x_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, pdc2026x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * pdc_configure_piomode - set chip PIO timing - * @ap: ATA interface - * @adev: ATA device - * @pio: PIO mode - * - * Called to do the PIO mode setup. Our timing registers are shared - * so a configure_dmamode call will undo any work we do here and vice - * versa - */ - -static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; - static u16 pio_timing[5] = { - 0x0913, 0x050C , 0x0308, 0x0206, 0x0104 - }; - u8 r_ap, r_bp; - - pci_read_config_byte(pdev, port, &r_ap); - pci_read_config_byte(pdev, port + 1, &r_bp); - r_ap &= ~0x3F; /* Preserve ERRDY_EN, SYNC_IN */ - r_bp &= ~0x07; - r_ap |= (pio_timing[pio] >> 8); - r_bp |= (pio_timing[pio] & 0xFF); - - if (ata_pio_need_iordy(adev)) - r_ap |= 0x20; /* IORDY enable */ - if (adev->class == ATA_DEV_ATA) - r_ap |= 0x10; /* FIFO enable */ - pci_write_config_byte(pdev, port, r_ap); - pci_write_config_byte(pdev, port + 1, r_bp); -} - -/** - * pdc_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. Our timing registers are shared - * but we want to set the PIO timing by default. - */ - -static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - pdc_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -} - -/** - * pdc_configure_dmamode - set DMA mode in chip - * @ap: ATA interface - * @adev: ATA device - * - * Load DMA cycle times into the chip ready for a DMA transfer - * to occur. - */ - -static void pdc_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; - static u8 udma_timing[6][2] = { - { 0x60, 0x03 }, /* 33 Mhz Clock */ - { 0x40, 0x02 }, - { 0x20, 0x01 }, - { 0x40, 0x02 }, /* 66 Mhz Clock */ - { 0x20, 0x01 }, - { 0x20, 0x01 } - }; - u8 r_bp, r_cp; - - pci_read_config_byte(pdev, port + 1, &r_bp); - pci_read_config_byte(pdev, port + 2, &r_cp); - - r_bp &= ~0xF0; - r_cp &= ~0x0F; - - if (adev->dma_mode >= XFER_UDMA_0) { - int speed = adev->dma_mode - XFER_UDMA_0; - r_bp |= udma_timing[speed][0]; - r_cp |= udma_timing[speed][1]; - - } else { - int speed = adev->dma_mode - XFER_MW_DMA_0; - r_bp |= 0x60; - r_cp |= (5 - speed); - } - pci_write_config_byte(pdev, port + 1, r_bp); - pci_write_config_byte(pdev, port + 2, r_cp); - -} - -/** - * pdc2026x_bmdma_start - DMA engine begin - * @qc: ATA command - * - * In UDMA3 or higher we have to clock switch for the duration of the - * DMA transfer sequence. - */ - -static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct ata_taskfile *tf = &qc->tf; - int sel66 = ap->port_no ? 0x08: 0x02; - - unsigned long master = ap->host->ports[0]->ioaddr.bmdma_addr; - unsigned long clock = master + 0x11; - unsigned long atapi_reg = master + 0x20 + (4 * ap->port_no); - - u32 len; - - /* Check we keep host level locking here */ - if (adev->dma_mode >= XFER_UDMA_2) - outb(inb(clock) | sel66, clock); - else - outb(inb(clock) & ~sel66, clock); - - /* The DMA clocks may have been trashed by a reset. FIXME: make conditional - and move to qc_issue ? */ - pdc_set_dmamode(ap, qc->dev); - - /* Cases the state machine will not complete correctly without help */ - if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) - { - if (tf->flags & ATA_TFLAG_LBA48) - len = qc->nsect * 512; - else - len = qc->nbytes; - - if (tf->flags & ATA_TFLAG_WRITE) - len |= 0x06000000; - else - len |= 0x05000000; - - outl(len, atapi_reg); - } - - /* Activate DMA */ - ata_bmdma_start(qc); -} - -/** - * pdc2026x_bmdma_end - DMA engine stop - * @qc: ATA command - * - * After a DMA completes we need to put the clock back to 33MHz for - * PIO timings. - */ - -static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct ata_taskfile *tf = &qc->tf; - - int sel66 = ap->port_no ? 0x08: 0x02; - /* The clock bits are in the same register for both channels */ - unsigned long master = ap->host->ports[0]->ioaddr.bmdma_addr; - unsigned long clock = master + 0x11; - unsigned long atapi_reg = master + 0x20 + (4 * ap->port_no); - - /* Cases the state machine will not complete correctly */ - if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) { - outl(0, atapi_reg); - outb(inb(clock) & ~sel66, clock); - } - /* Check we keep host level locking here */ - /* Flip back to 33Mhz for PIO */ - if (adev->dma_mode >= XFER_UDMA_2) - outb(inb(clock) & ~sel66, clock); - - ata_bmdma_stop(qc); -} - -/** - * pdc2026x_dev_config - device setup hook - * @ap: ATA port - * @adev: newly found device - * - * Perform chip specific early setup. We need to lock the transfer - * sizes to 8bit to avoid making the state engine on the 2026x cards - * barf. - */ - -static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev) -{ - adev->max_sectors = 256; -} - -static struct scsi_host_template pdc_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations pdc2024x_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = pdc_set_piomode, - .set_dmamode = pdc_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = pdc2024x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations pdc2026x_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = pdc_set_piomode, - .set_dmamode = pdc_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - .dev_config = pdc2026x_dev_config, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = pdc2026x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = pdc2026x_bmdma_start, - .bmdma_stop = pdc2026x_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info[3] = { - { - .sht = &pdc_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, - .port_ops = &pdc2024x_port_ops - }, - { - .sht = &pdc_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, - .port_ops = &pdc2026x_port_ops - }, - { - .sht = &pdc_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, - .port_ops = &pdc2026x_port_ops - } - - }; - static struct ata_port_info *port_info[2]; - - port_info[0] = port_info[1] = &info[id->driver_data]; - - if (dev->device == PCI_DEVICE_ID_PROMISE_20265) { - struct pci_dev *bridge = dev->bus->self; - /* Don't grab anything behind a Promise I2O RAID */ - if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) { - if( bridge->device == PCI_DEVICE_ID_INTEL_I960) - return -ENODEV; - if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM) - return -ENODEV; - } - } - return ata_pci_init_one(dev, port_info, 2); -} - -static struct pci_device_id pdc[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0}, - { PCI_DEVICE(PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1}, - { PCI_DEVICE(PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1}, - { PCI_DEVICE(PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2}, - { PCI_DEVICE(PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2}, - { 0, }, -}; - -static struct pci_driver pdc_pci_driver = { - .name = DRV_NAME, - .id_table = pdc, - .probe = pdc_init_one, - .remove = ata_pci_remove_one -}; - -static int __init pdc_init(void) -{ - return pci_register_driver(&pdc_pci_driver); -} - - -static void __exit pdc_exit(void) -{ - pci_unregister_driver(&pdc_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pdc); -MODULE_VERSION(DRV_VERSION); - -module_init(pdc_init); -module_exit(pdc_exit); diff --git a/trunk/drivers/ata/pata_qdi.c b/trunk/drivers/ata/pata_qdi.c deleted file mode 100644 index 35cfdf0ac3f0..000000000000 --- a/trunk/drivers/ata/pata_qdi.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * pata_qdi.c - QDI VLB ATA controllers - * (C) 2006 Red Hat - * - * This driver mostly exists as a proof of concept for non PCI devices under - * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly - * useful. - * - * Tuning code written from the documentation at - * http://www.ryston.cz/petr/vlb/qd6500.html - * http://www.ryston.cz/petr/vlb/qd6580.html - * - * Probe code based on drivers/ide/legacy/qd65xx.c - * Rewritten from the work of Colten Edwards by - * Samuel Thibault - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_qdi" -#define DRV_VERSION "0.2.4" - -#define NR_HOST 4 /* Two 6580s */ - -struct qdi_data { - unsigned long timing; - u8 clock[2]; - u8 last; - int fast; - struct platform_device *platform_dev; - -}; - -static struct ata_host *qdi_host[NR_HOST]; -static struct qdi_data qdi_data[NR_HOST]; -static int nr_qdi_host; - -#ifdef MODULE -static int probe_qdi = 1; -#else -static int probe_qdi; -#endif - -static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct ata_timing t; - struct qdi_data *qdi = ap->host->private_data; - int active, recovery; - u8 timing; - - /* Get the timing data in cycles */ - ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - - if (qdi->fast) { - active = 8 - FIT(t.active, 1, 8); - recovery = 18 - FIT(t.recover, 3, 18); - } else { - active = 9 - FIT(t.active, 2, 9); - recovery = 15 - FIT(t.recover, 0, 15); - } - timing = (recovery << 4) | active | 0x08; - - qdi->clock[adev->devno] = timing; - - outb(timing, qdi->timing); -} - -static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct ata_timing t; - struct qdi_data *qdi = ap->host->private_data; - int active, recovery; - u8 timing; - - /* Get the timing data in cycles */ - ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - - if (qdi->fast) { - active = 8 - FIT(t.active, 1, 8); - recovery = 18 - FIT(t.recover, 3, 18); - } else { - active = 9 - FIT(t.active, 2, 9); - recovery = 15 - FIT(t.recover, 0, 15); - } - timing = (recovery << 4) | active | 0x08; - - qdi->clock[adev->devno] = timing; - - outb(timing, qdi->timing); - - /* Clear the FIFO */ - if (adev->class != ATA_DEV_ATA) - outb(0x5F, (qdi->timing & 0xFFF0) + 3); -} - -/** - * qdi_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings. - */ - -static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct qdi_data *qdi = ap->host->private_data; - - if (qdi->clock[adev->devno] != qdi->last) { - if (adev->pio_mode) { - qdi->last = qdi->clock[adev->devno]; - outb(qdi->clock[adev->devno], qdi->timing); - } - } - return ata_qc_issue_prot(qc); -} - -static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) -{ - struct ata_port *ap = adev->ap; - int slop = buflen & 3; - - if (ata_id_has_dword_io(adev->id)) { - if (write_data) - outsl(ap->ioaddr.data_addr, buf, buflen >> 2); - else - insl(ap->ioaddr.data_addr, buf, buflen >> 2); - - if (unlikely(slop)) { - u32 pad; - if (write_data) { - memcpy(&pad, buf + buflen - slop, slop); - outl(le32_to_cpu(pad), ap->ioaddr.data_addr); - } else { - pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); - memcpy(buf + buflen - slop, &pad, slop); - } - } - } else - ata_pio_data_xfer(adev, buf, buflen, write_data); -} - -static struct scsi_host_template qdi_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations qdi6500_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = qdi6500_set_piomode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = qdi_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = qdi_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations qdi6580_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = qdi6580_set_piomode, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = qdi_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = qdi_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * qdi_init_one - attach a qdi interface - * @type: Type to display - * @io: I/O port start - * @irq: interrupt line - * @fast: True if on a > 33Mhz VLB - * - * Register an ISA bus IDE interface. Such interfaces are PIO and we - * assume do not support IRQ sharing. - */ - -static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast) -{ - struct ata_probe_ent ae; - struct platform_device *pdev; - int ret; - - unsigned long ctrl = io + 0x206; - - /* - * Fill in a probe structure first of all - */ - - pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0); - if (pdev == NULL) - return -ENOMEM; - - memset(&ae, 0, sizeof(struct ata_probe_ent)); - INIT_LIST_HEAD(&ae.node); - ae.dev = &pdev->dev; - - if (type == 6580) { - ae.port_ops = &qdi6580_port_ops; - ae.pio_mask = 0x1F; - } else { - ae.port_ops = &qdi6500_port_ops; - ae.pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */ - } - - ae.sht = &qdi_sht; - ae.n_ports = 1; - ae.irq = irq; - ae.irq_flags = 0; - ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; - ae.port[0].cmd_addr = io; - ae.port[0].altstatus_addr = ctrl; - ae.port[0].ctl_addr = ctrl; - ata_std_ports(&ae.port[0]); - - /* - * Hook in a private data structure per channel - */ - ae.private_data = &qdi_data[nr_qdi_host]; - - qdi_data[nr_qdi_host].timing = port; - qdi_data[nr_qdi_host].fast = fast; - qdi_data[nr_qdi_host].platform_dev = pdev; - - printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io); - ret = ata_device_add(&ae); - if (ret == 0) { - platform_device_unregister(pdev); - return -ENODEV; - } - - qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev); - return 0; -} - -/** - * qdi_init - attach qdi interfaces - * - * Attach qdi IDE interfaces by scanning the ports it may occupy. - */ - -static __init int qdi_init(void) -{ - unsigned long flags; - static const unsigned long qd_port[2] = { 0x30, 0xB0 }; - static const unsigned long ide_port[2] = { 0x170, 0x1F0 }; - static const int ide_irq[2] = { 14, 15 }; - - int ct = 0; - int i; - - if (probe_qdi == 0) - return -ENODEV; - - /* - * Check each possible QD65xx base address - */ - - for (i = 0; i < 2; i++) { - unsigned long port = qd_port[i]; - u8 r, res; - - - if (request_region(port, 2, "pata_qdi")) { - /* Check for a card */ - local_irq_save(flags); - r = inb_p(port); - outb_p(0x19, port); - res = inb_p(port); - outb_p(r, port); - local_irq_restore(flags); - - /* Fail */ - if (res == 0x19) - { - release_region(port, 2); - continue; - } - - /* Passes the presence test */ - r = inb_p(port + 1); /* Check port agrees with port set */ - if ((r & 2) >> 1 != i) { - release_region(port, 2); - continue; - } - - /* Check card type */ - if ((r & 0xF0) == 0xC0) { - /* QD6500: single channel */ - if (r & 8) { - /* Disabled ? */ - release_region(port, 2); - continue; - } - ct += qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); - } - if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) { - /* QD6580: dual channel */ - if (!request_region(port + 2 , 2, "pata_qdi")) - { - release_region(port, 2); - continue; - } - res = inb(port + 3); - if (res & 1) { - /* Single channel mode */ - ct += qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); - } else { - /* Dual channel mode */ - ct += qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04); - ct += qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04); - } - } - } - } - if (ct != 0) - return 0; - return -ENODEV; -} - -static __exit void qdi_exit(void) -{ - int i; - - for (i = 0; i < nr_qdi_host; i++) { - ata_host_remove(qdi_host[i]); - /* Free the control resource. The 6580 dual channel has the resources - * claimed as a pair of 2 byte resources so we need no special cases... - */ - release_region(qdi_data[i].timing, 2); - platform_device_unregister(qdi_data[i].platform_dev); - } -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for qdi ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(qdi_init); -module_exit(qdi_exit); - -module_param(probe_qdi, int, 0); - diff --git a/trunk/drivers/ata/pata_radisys.c b/trunk/drivers/ata/pata_radisys.c deleted file mode 100644 index 277f8411b521..000000000000 --- a/trunk/drivers/ata/pata_radisys.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * pata_radisys.c - Intel PATA/SATA controllers - * - * (C) 2006 Red Hat - * - * Some parts based on ata_piix.c by Jeff Garzik and others. - * - * A PIIX relative, this device has a single ATA channel and no - * slave timings, SITRE or PPE. In that sense it is a close relative - * of the original PIIX. It does however support UDMA 33/66 per channel - * although no other modes/timings. Also lacking is 32bit I/O on the ATA - * port. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_radisys" -#define DRV_VERSION "0.4.1" - -/** - * radisys_probe_init - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int radisys_pre_reset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); -} - - -/** - * radisys_pata_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * @classes: - * - * LOCKING: - * None (inherited from caller). - */ - -static void radisys_pata_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, radisys_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * radisys_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set PIO mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - unsigned int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *dev = to_pci_dev(ap->host->dev); - u16 idetm_data; - int control = 0; - - /* - * See Intel Document 298600-004 for the timing programing rules - * for PIIX/ICH. Note that the early PIIX does not have the slave - * timing port at 0x44. The Radisys is a relative of the PIIX - * but not the same so be careful. - */ - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, /* Check me */ - { 0, 0 }, - { 1, 1 }, - { 2, 2 }, - { 3, 3 }, }; - - if (pio > 0) - control |= 1; /* TIME1 enable */ - if (ata_pio_need_iordy(adev)) - control |= 2; /* IE IORDY */ - - pci_read_config_word(dev, 0x40, &idetm_data); - - /* Enable IE and TIME as appropriate. Clear the other - drive timing bits */ - idetm_data &= 0xCCCC; - idetm_data |= (control << (4 * adev->devno)); - idetm_data |= (timings[pio][0] << 12) | - (timings[pio][1] << 8); - pci_write_config_word(dev, 0x40, idetm_data); - - /* Track which port is configured */ - ap->private_data = adev; -} - -/** - * radisys_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers - * - * Set MWDMA mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ - -static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *dev = to_pci_dev(ap->host->dev); - u16 idetm_data; - u8 udma_enable; - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 1 }, - { 2, 2 }, - { 3, 3 }, }; - - /* - * MWDMA is driven by the PIO timings. We must also enable - * IORDY unconditionally. - */ - - pci_read_config_word(dev, 0x40, &idetm_data); - pci_read_config_byte(dev, 0x48, &udma_enable); - - if (adev->dma_mode < XFER_UDMA_0) { - unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; - const unsigned int needed_pio[3] = { - XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 - }; - int pio = needed_pio[mwdma] - XFER_PIO_0; - int control = 3; /* IORDY|TIME0 */ - - /* If the drive MWDMA is faster than it can do PIO then - we must force PIO0 for PIO cycles. */ - - if (adev->pio_mode < needed_pio[mwdma]) - control = 1; - - /* Mask out the relevant control and timing bits we will load. Also - clear the other drive TIME register as a precaution */ - - idetm_data &= 0xCCCC; - idetm_data |= control << (4 * adev->devno); - idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - - udma_enable &= ~(1 << adev->devno); - } else { - u8 udma_mode; - - /* UDMA66 on: UDMA 33 and 66 are switchable via register 0x4A */ - - pci_read_config_byte(dev, 0x4A, &udma_mode); - - if (adev->xfer_mode == XFER_UDMA_2) - udma_mode &= ~ (1 << adev->devno); - else /* UDMA 4 */ - udma_mode |= (1 << adev->devno); - - pci_write_config_byte(dev, 0x4A, udma_mode); - - udma_enable |= (1 << adev->devno); - } - pci_write_config_word(dev, 0x40, idetm_data); - pci_write_config_byte(dev, 0x48, udma_enable); - - /* Track which port is configured */ - ap->private_data = adev; -} - -/** - * radisys_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. Our logic also clears TIME0/TIME1 for the other device so - * that, even if we get this wrong, cycles to the other device will - * be made PIO0. - */ - -static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - - if (adev != ap->private_data) { - /* UDMA timing is not shared */ - if (adev->dma_mode < XFER_UDMA_0) { - if (adev->dma_mode) - radisys_set_dmamode(ap, adev); - else if (adev->pio_mode) - radisys_set_piomode(ap, adev); - } - } - return ata_qc_issue_prot(qc); -} - - -static struct scsi_host_template radisys_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations radisys_pata_ops = { - .port_disable = ata_port_disable, - .set_piomode = radisys_set_piomode, - .set_dmamode = radisys_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = radisys_pata_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = radisys_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - - -/** - * radisys_init_one - Register PIIX ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in radisys_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. We probe for combined mode (sigh), - * and then hand over control to libata, for it to do the rest. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - static struct ata_port_info info = { - .sht = &radisys_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x14, /* UDMA33/66 only */ - .port_ops = &radisys_pata_ops, - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id radisys_pci_tbl[] = { - { 0x1331, 0x8201, PCI_ANY_ID, PCI_ANY_ID, }, - { } /* terminate list */ -}; - -static struct pci_driver radisys_pci_driver = { - .name = DRV_NAME, - .id_table = radisys_pci_tbl, - .probe = radisys_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init radisys_init(void) -{ - return pci_register_driver(&radisys_pci_driver); -} - -static void __exit radisys_exit(void) -{ - pci_unregister_driver(&radisys_pci_driver); -} - - -module_init(radisys_init); -module_exit(radisys_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for Radisys R82600 controllers"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, radisys_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_rz1000.c b/trunk/drivers/ata/pata_rz1000.c deleted file mode 100644 index 3c6d84fd4312..000000000000 --- a/trunk/drivers/ata/pata_rz1000.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * RZ1000/1001 driver based upon - * - * linux/drivers/ide/pci/rz1000.c Version 0.06 January 12, 2003 - * Copyright (C) 1995-1998 Linus Torvalds & author (see below) - * Principal Author: mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for disabling the buggy read-ahead - * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_rz1000" -#define DRV_VERSION "0.2.2" - - -/** - * rz1000_prereset - probe begin - * @ap: ATA port - * - * Set up cable type and use generics - */ - -static int rz1000_prereset(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * rz1000_error_handler - probe reset - * @ap: ATA port - * - * Perform the ATA standard reset sequence - */ - -static void rz1000_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, rz1000_prereset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * rz1000_set_mode - mode setting function - * @ap: ATA interface - * - * Use a non standard set_mode function. We don't want to be tuned. We - * would prefer to be BIOS generic but for the fact our hardware is - * whacked out. - */ - -static void rz1000_set_mode(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } - } -} - - -static struct scsi_host_template rz1000_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations rz1000_port_ops = { - .set_mode = rz1000_set_mode, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = rz1000_error_handler, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = rz1000_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in rz1000_pci_tbl matching with @pdev - * - * Configure an RZ1000 interface. This doesn't require much special - * handling except that we *MUST* kill the chipset readahead or the - * user may experience data corruption. - */ - -static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - struct ata_port_info *port_info[2]; - u16 reg; - static struct ata_port_info info = { - .sht = &rz1000_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &rz1000_port_ops - }; - - if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); - - /* Be exceptionally paranoid as we must be sure to apply the fix */ - if (pci_read_config_word(pdev, 0x40, ®) != 0) - goto fail; - reg &= 0xDFFF; - if (pci_write_config_word(pdev, 0x40, reg) != 0) - goto fail; - printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); - - port_info[0] = &info; - port_info[1] = &info; - return ata_pci_init_one(pdev, port_info, 2); -fail: - printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); - /* Not safe to use so skip */ - return -ENODEV; -} - -static struct pci_device_id pata_rz1000[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, - { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, - { 0, }, -}; - -static struct pci_driver rz1000_pci_driver = { - .name = DRV_NAME, - .id_table = pata_rz1000, - .probe = rz1000_init_one, - .remove = ata_pci_remove_one -}; - - -static int __init rz1000_init(void) -{ - return pci_register_driver(&rz1000_pci_driver); -} - -static void __exit rz1000_exit(void) -{ - pci_unregister_driver(&rz1000_pci_driver); -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for RZ1000 PCI ATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pata_rz1000); -MODULE_VERSION(DRV_VERSION); - -module_init(rz1000_init); -module_exit(rz1000_exit); - diff --git a/trunk/drivers/ata/pata_sc1200.c b/trunk/drivers/ata/pata_sc1200.c deleted file mode 100644 index 4166c1a8a9e8..000000000000 --- a/trunk/drivers/ata/pata_sc1200.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * New ATA layer SC1200 driver Alan Cox - * - * TODO: Mode selection filtering - * TODO: Can't enable second channel until ATA core has serialize - * TODO: Needs custom DMA cleanup code - * - * Based very heavily on - * - * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 - * - * Copyright (C) 2000-2002 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - * - * Development of this chipset driver was funded - * by the nice folks at National Semiconductor. - * - * 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 program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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 - -#define DRV_NAME "sc1200" -#define DRV_VERSION "0.2.3" - -#define SC1200_REV_A 0x00 -#define SC1200_REV_B1 0x01 -#define SC1200_REV_B3 0x02 -#define SC1200_REV_C1 0x03 -#define SC1200_REV_D1 0x04 - -/** - * sc1200_clock - PCI clock - * - * Return the PCI bus clocking for the SC1200 chipset configuration - * in use. We return 0 for 33MHz 1 for 48MHz and 2 for 66Mhz - */ - -static int sc1200_clock(void) -{ - /* Magic registers that give us the chipset data */ - u8 chip_id = inb(0x903C); - u8 silicon_rev = inb(0x903D); - u16 pci_clock; - - if (chip_id == 0x04 && silicon_rev < SC1200_REV_B1) - return 0; /* 33 MHz mode */ - - /* Clock generator configuration 0x901E its 8/9 are the PCI clocking - 0/3 is 33Mhz 1 is 48 2 is 66 */ - - pci_clock = inw(0x901E); - pci_clock >>= 8; - pci_clock &= 0x03; - if (pci_clock == 3) - pci_clock = 0; - return pci_clock; -} - -/** - * sc1200_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Set our PIO requirements. This is fairly simple on the SC1200 - */ - -static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static const u32 pio_timings[4][5] = { - {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz - {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz - {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131} // format1, 66Mhz - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 format; - unsigned int reg = 0x40 + 0x10 * ap->port_no; - int mode = adev->pio_mode - XFER_PIO_0; - - pci_read_config_dword(pdev, reg + 4, &format); - format >>= 31; - format += sc1200_clock(); - pci_write_config_dword(pdev, reg + 8 * adev->devno, - pio_timings[format][mode]); -} - -/** - * sc1200_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - * We cannot mix MWDMA and UDMA without reloading timings each switch - * master to slave. - */ - -static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u32 udma_timing[3][3] = { - { 0x00921250, 0x00911140, 0x00911030 }, - { 0x00932470, 0x00922260, 0x00922140 }, - { 0x009436A1, 0x00933481, 0x00923261 } - }; - - static const u32 mwdma_timing[3][3] = { - { 0x00077771, 0x00012121, 0x00002020 }, - { 0x000BBBB2, 0x00024241, 0x00013131 }, - { 0x000FFFF3, 0x00035352, 0x00015151 } - }; - - int clock = sc1200_clock(); - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int reg = 0x40 + 0x10 * ap->port_no; - int mode = adev->dma_mode; - u32 format; - - if (mode >= XFER_UDMA_0) - format = udma_timing[clock][mode - XFER_UDMA_0]; - else - format = mwdma_timing[clock][mode - XFER_MW_DMA_0]; - - if (adev->devno == 0) { - u32 timings; - - pci_read_config_dword(pdev, reg + 4, &timings); - timings &= 0x80000000UL; - timings |= format; - pci_write_config_dword(pdev, reg + 4, timings); - } else - pci_write_config_dword(pdev, reg + 12, format); -} - -/** - * sc1200_qc_issue_prot - command issue - * @qc: command pending - * - * Called when the libata layer is about to issue a command. We wrap - * this interface so that we can load the correct ATA timings if - * neccessary. Specifically we have a problem that there is only - * one MWDMA/UDMA bit. - */ - -static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_device *adev = qc->dev; - struct ata_device *prev = ap->private_data; - - /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { - /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) - /* Switch the mode bits */ - sc1200_set_dmamode(ap, adev); - } - - return ata_qc_issue_prot(qc); -} - -static struct scsi_host_template sc1200_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations sc1200_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = sc1200_set_piomode, - .set_dmamode = sc1200_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = ata_bmdma_error_handler, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = sc1200_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * sc1200_init_one - Initialise an SC1200 - * @dev: PCI device - * @id: Entry in match table - * - * Just throw the needed data at the libata helper and it does all - * our work. - */ - -static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &sc1200_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &sc1200_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - - /* Can't enable port 2 yet, see top comments */ - return ata_pci_init_one(dev, port_info, 1); -} - -static struct pci_device_id sc1200[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE), }, - { 0, }, -}; - -static struct pci_driver sc1200_pci_driver = { - .name = DRV_NAME, - .id_table = sc1200, - .probe = sc1200_init_one, - .remove = ata_pci_remove_one -}; - -static int __init sc1200_init(void) -{ - return pci_register_driver(&sc1200_pci_driver); -} - - -static void __exit sc1200_exit(void) -{ - pci_unregister_driver(&sc1200_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox, Mark Lord"); -MODULE_DESCRIPTION("low-level driver for the NS/AMD SC1200"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, sc1200); -MODULE_VERSION(DRV_VERSION); - -module_init(sc1200_init); -module_exit(sc1200_exit); diff --git a/trunk/drivers/ata/pata_serverworks.c b/trunk/drivers/ata/pata_serverworks.c deleted file mode 100644 index af456113c55d..000000000000 --- a/trunk/drivers/ata/pata_serverworks.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * ata-serverworks.c - Serverworks PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based upon - * - * serverworks.c - * - * Copyright (C) 1998-2000 Michel Aubry - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz - * Copyright (C) 1998-2000 Andre Hedrick - * Portions copyright (c) 2001 Sun Microsystems - * - * - * RCC/ServerWorks IDE driver for Linux - * - * OSB4: `Open South Bridge' IDE Interface (fn 1) - * supports UDMA mode 2 (33 MB/s) - * - * CSB5: `Champion South Bridge' IDE Interface (fn 1) - * all revisions support UDMA mode 4 (66 MB/s) - * revision A2.0 and up support UDMA mode 5 (100 MB/s) - * - * *** The CSB5 does not provide ANY register *** - * *** to detect 80-conductor cable presence. *** - * - * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) - * - * Documentation: - * Available under NDA only. Errata info very hard to get. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_serverworks" -#define DRV_VERSION "0.3.6" - -#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ -#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ - -/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 - * can overrun their FIFOs when used with the CSB5 */ - -static const char *csb_bad_ata100[] = { - "ST320011A", - "ST340016A", - "ST360021A", - "ST380021A", - NULL -}; - -/** - * dell_cable - Dell serverworks cable detection - * @ap: ATA port to do cable detect - * - * Dell hide the 40/80 pin select for their interfaces in the top two - * bits of the subsystem ID. - */ - -static int dell_cable(struct ata_port *ap) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (pdev->subsystem_device & (1 << (ap->port_no + 14))) - return ATA_CBL_PATA80; - return ATA_CBL_PATA40; -} - -/** - * sun_cable - Sun Cobalt 'Alpine' cable detection - * @ap: ATA port to do cable select - * - * Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the - * subsystem ID the same as dell. We could use one function but we may - * need to extend the Dell one in future - */ - -static int sun_cable(struct ata_port *ap) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (pdev->subsystem_device & (1 << (ap->port_no + 14))) - return ATA_CBL_PATA80; - return ATA_CBL_PATA40; -} - -/** - * osb4_cable - OSB4 cable detect - * @ap: ATA port to check - * - * The OSB4 isn't UDMA66 capable so this is easy - */ - -static int osb4_cable(struct ata_port *ap) { - return ATA_CBL_PATA40; -} - -/** - * csb4_cable - CSB5/6 cable detect - * @ap: ATA port to check - * - * Serverworks default arrangement is to use the drive side detection - * only. - */ - -static int csb_cable(struct ata_port *ap) { - return ATA_CBL_PATA80; -} - -struct sv_cable_table { - int device; - int subvendor; - int (*cable_detect)(struct ata_port *ap); -}; - -/* - * Note that we don't copy the old serverworks code because the old - * code contains obvious mistakes - */ - -static struct sv_cable_table cable_detect[] = { - { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable }, - { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable }, - { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, sun_cable }, - { PCI_DEVICE_ID_SERVERWORKS_OSB4, PCI_ANY_ID, osb4_cable }, - { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable }, - { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable }, - { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable }, - { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable }, - { } -}; - -/** - * serverworks_pre_reset - cable detection - * @ap: ATA port - * - * Perform cable detection according to the device and subvendor - * identifications - */ - -static int serverworks_pre_reset(struct ata_port *ap) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct sv_cable_table *cb = cable_detect; - - while(cb->device) { - if (cb->device == pdev->device && - (cb->subvendor == pdev->subsystem_vendor || - cb->subvendor == PCI_ANY_ID)) { - ap->cbl = cb->cable_detect(ap); - return ata_std_prereset(ap); - } - cb++; - } - - BUG(); - return -1; /* kill compiler warning */ -} - -static void serverworks_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, serverworks_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * serverworks_is_csb - Check for CSB or OSB - * @pdev: PCI device to check - * - * Returns true if the device being checked is known to be a CSB - * series device. - */ - -static u8 serverworks_is_csb(struct pci_dev *pdev) -{ - switch (pdev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: - case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: - return 1; - default: - break; - } - return 0; -} - -/** - * serverworks_osb4_filter - mode selection filter - * @ap: ATA interface - * @adev: ATA device - * - * Filter the offered modes for the device to apply controller - * specific rules. OSB4 requires no UDMA for disks due to a FIFO - * bug we hit. - */ - -static unsigned long serverworks_osb4_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - if (adev->class == ATA_DEV_ATA) - mask &= ~ATA_MASK_UDMA; - return ata_pci_default_filter(ap, adev, mask); -} - - -/** - * serverworks_csb_filter - mode selection filter - * @ap: ATA interface - * @adev: ATA device - * - * Check the blacklist and disable UDMA5 if matched - */ - -static unsigned long serverworks_csb_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) -{ - const char *p; - char model_num[40]; - int len, i; - - /* Disk, UDMA */ - if (adev->class != ATA_DEV_ATA) - return ata_pci_default_filter(ap, adev, mask); - - /* Actually do need to check */ - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - /* Precuationary - why not do this in the libata core ?? */ - - len = strlen(model_num); - while ((len > 0) && (model_num[len - 1] == ' ')) { - len--; - model_num[len] = 0; - } - - for(i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { - if (!strncmp(p, model_num, len)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); - } - return ata_pci_default_filter(ap, adev, mask); -} - - -/** - * serverworks_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the OSB4/CSB5 timing registers for PIO. The PIO register - * load is done as a simple lookup. - */ -static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - int offset = 1 + (2 * ap->port_no) - adev->devno; - int devbits = (2 * ap->port_no + adev->devno) * 4; - u16 csb5_pio; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int pio = adev->pio_mode - XFER_PIO_0; - - pci_write_config_byte(pdev, 0x40 + offset, pio_mode[pio]); - - /* The OSB4 just requires the timing but the CSB series want the - mode number as well */ - if (serverworks_is_csb(pdev)) { - pci_read_config_word(pdev, 0x4A, &csb5_pio); - csb5_pio &= ~(0x0F << devbits); - pci_write_config_byte(pdev, 0x4A, csb5_pio | (pio << devbits)); - } -} - -/** - * serverworks_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the MWDMA/UDMA modes for the serverworks OSB4/CSB5 - * chipset. The MWDMA mode values are pulled from a lookup table - * while the chipset uses mode number for UDMA. - */ - -static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u8 dma_mode[] = { 0x77, 0x21, 0x20 }; - int offset = 1 + 2 * ap->port_no - adev->devno; - int devbits = (2 * ap->port_no + adev->devno); - u8 ultra; - u8 ultra_cfg; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - pci_read_config_byte(pdev, 0x54, &ultra_cfg); - - if (adev->dma_mode >= XFER_UDMA_0) { - pci_write_config_byte(pdev, 0x44 + offset, 0x20); - - pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra); - ultra &= ~(0x0F << (ap->port_no * 4)); - ultra |= (adev->dma_mode - XFER_UDMA_0) - << (ap->port_no * 4); - pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra); - - ultra_cfg |= (1 << devbits); - } else { - pci_write_config_byte(pdev, 0x44 + offset, - dma_mode[adev->dma_mode - XFER_MW_DMA_0]); - ultra_cfg &= ~(1 << devbits); - } - pci_write_config_byte(pdev, 0x54, ultra_cfg); -} - -static struct scsi_host_template serverworks_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations serverworks_osb4_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = serverworks_set_piomode, - .set_dmamode = serverworks_set_dmamode, - .mode_filter = serverworks_osb4_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = serverworks_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations serverworks_csb_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = serverworks_set_piomode, - .set_dmamode = serverworks_set_dmamode, - .mode_filter = serverworks_csb_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = serverworks_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int serverworks_fixup_osb4(struct pci_dev *pdev) -{ - u32 reg; - struct pci_dev *isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); - if (isa_dev) { - pci_read_config_dword(isa_dev, 0x64, ®); - reg &= ~0x00002000; /* disable 600ns interrupt mask */ - if (!(reg & 0x00004000)) - printk(KERN_DEBUG DRV_NAME ": UDMA not BIOS enabled.\n"); - reg |= 0x00004000; /* enable UDMA/33 support */ - pci_write_config_dword(isa_dev, 0x64, reg); - pci_dev_put(isa_dev); - return 0; - } - printk(KERN_WARNING "ata_serverworks: Unable to find bridge.\n"); - return -ENODEV; -} - -static int serverworks_fixup_csb(struct pci_dev *pdev) -{ - u8 rev; - u8 btr; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - - /* Third Channel Test */ - if (!(PCI_FUNC(pdev->devfn) & 1)) { - struct pci_dev * findev = NULL; - u32 reg4c = 0; - findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); - if (findev) { - pci_read_config_dword(findev, 0x4C, ®4c); - reg4c &= ~0x000007FF; - reg4c |= 0x00000040; - reg4c |= 0x00000020; - pci_write_config_dword(findev, 0x4C, reg4c); - pci_dev_put(findev); - } - } else { - struct pci_dev * findev = NULL; - u8 reg41 = 0; - - findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL); - if (findev) { - pci_read_config_byte(findev, 0x41, ®41); - reg41 &= ~0x40; - pci_write_config_byte(findev, 0x41, reg41); - pci_dev_put(findev); - } - } - /* setup the UDMA Control register - * - * 1. clear bit 6 to enable DMA - * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 - */ - pci_read_config_byte(pdev, 0x5A, &btr); - btr &= ~0x40; - if (!(PCI_FUNC(pdev->devfn) & 1)) - btr |= 0x2; - else - btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; - pci_write_config_byte(pdev, 0x5A, btr); - - return btr; -} - -static void serverworks_fixup_ht1000(struct pci_dev *pdev) -{ - u8 btr; - /* Setup HT1000 SouthBridge Controller - Single Channel Only */ - pci_read_config_byte(pdev, 0x5A, &btr); - btr &= ~0x40; - btr |= 0x3; - pci_write_config_byte(pdev, 0x5A, btr); -} - - -static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int ports = 2; - static struct ata_port_info info[4] = { - { /* OSB4 */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &serverworks_osb4_port_ops - }, { /* OSB4 no UDMA */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x00, - .port_ops = &serverworks_osb4_port_ops - }, { /* CSB5 */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, - .port_ops = &serverworks_csb_port_ops - }, { /* CSB5 - later revisions*/ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &serverworks_csb_port_ops - } - }; - static struct ata_port_info *port_info[2]; - struct ata_port_info *devinfo = &info[id->driver_data]; - - /* Force master latency timer to 64 PCI clocks */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); - - /* OSB4 : South Bridge and IDE */ - if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - /* Select non UDMA capable OSB4 if we can't do fixups */ - if ( serverworks_fixup_osb4(pdev) < 0) - devinfo = &info[1]; - } - /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ - else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || - (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || - (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { - - /* If the returned btr is the newer revision then - select the right info block */ - if (serverworks_fixup_csb(pdev) == 3) - devinfo = &info[3]; - - /* Is this the 3rd channel CSB6 IDE ? */ - if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) - ports = 1; - } - /* setup HT1000E */ - else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) - serverworks_fixup_ht1000(pdev); - - if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - ata_pci_clear_simplex(pdev); - - port_info[0] = port_info[1] = devinfo; - return ata_pci_init_one(pdev, port_info, ports); -} - -static struct pci_device_id serverworks[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2}, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2}, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 2}, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 2}, - { 0, }, -}; - -static struct pci_driver serverworks_pci_driver = { - .name = DRV_NAME, - .id_table = serverworks, - .probe = serverworks_init_one, - .remove = ata_pci_remove_one -}; - -static int __init serverworks_init(void) -{ - return pci_register_driver(&serverworks_pci_driver); -} - - -static void __exit serverworks_exit(void) -{ - pci_unregister_driver(&serverworks_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Serverworks OSB4/CSB5/CSB6"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, serverworks); -MODULE_VERSION(DRV_VERSION); - -module_init(serverworks_init); -module_exit(serverworks_exit); diff --git a/trunk/drivers/ata/pata_sil680.c b/trunk/drivers/ata/pata_sil680.c deleted file mode 100644 index 8f7db9638d0a..000000000000 --- a/trunk/drivers/ata/pata_sil680.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * pata_sil680.c - SIL680 PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based upon - * - * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003 - * - * Copyright (C) 2001-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat - * - * May be copied or modified under the terms of the GNU General Public License - * - * Documentation publically available. - * - * If you have strange problems with nVidia chipset systems please - * see the SI support documentation and update your system BIOS - * if neccessary - * - * TODO - * If we know all our devices are LBA28 (or LBA28 sized) we could use - * the command fifo mode. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_sil680" -#define DRV_VERSION "0.3.2" - -/** - * sil680_selreg - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * Thankfully this is a configuration operation so isnt performance - * criticial. - */ - -static unsigned long sil680_selreg(struct ata_port *ap, int r) -{ - unsigned long base = 0xA0 + r; - base += (ap->port_no << 4); - return base; -} - -/** - * sil680_seldev - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * including accounting for the unit shift. - */ - -static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) -{ - unsigned long base = 0xA0 + r; - base += (ap->port_no << 4); - base |= adev->devno ? 2 : 0; - return base; -} - - -/** - * sil680_cable_detect - cable detection - * @ap: ATA port - * - * Perform cable detection. The SIL680 stores this in PCI config - * space for us. - */ - -static int sil680_cable_detect(struct ata_port *ap) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long addr = sil680_selreg(ap, 0); - u8 ata66; - pci_read_config_byte(pdev, addr, &ata66); - if (ata66 & 1) - return ATA_CBL_PATA80; - else - return ATA_CBL_PATA40; -} - -static int sil680_pre_reset(struct ata_port *ap) -{ - ap->cbl = sil680_cable_detect(ap); - return ata_std_prereset(ap); -} - -/** - * sil680_bus_reset - reset the SIL680 bus - * @ap: ATA port to reset - * - * Perform the SIL680 housekeeping when doing an ATA bus reset - */ - -static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long addr = sil680_selreg(ap, 0); - u8 reset; - - pci_read_config_byte(pdev, addr, &reset); - pci_write_config_byte(pdev, addr, reset | 0x03); - udelay(25); - pci_write_config_byte(pdev, addr, reset); - return ata_std_softreset(ap, classes); -} - -static void sil680_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, sil680_pre_reset, sil680_bus_reset, NULL, ata_std_postreset); -} - -/** - * sil680_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the SIL680 registers for PIO mode. Note that the task speed - * registers are shared between the devices so we must pick the lowest - * mode for command work. - */ - -static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; - static u16 speed_t[5] = { 0x328A, 0x1281, 0x1281, 0x10C3, 0x10C1 }; - - unsigned long tfaddr = sil680_selreg(ap, 0x02); - unsigned long addr = sil680_seldev(ap, adev, 0x04); - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int pio = adev->pio_mode - XFER_PIO_0; - int lowest_pio = pio; - u16 reg; - - struct ata_device *pair = ata_dev_pair(adev); - - if (pair != NULL && adev->pio_mode > pair->pio_mode) - lowest_pio = pair->pio_mode - XFER_PIO_0; - - pci_write_config_word(pdev, addr, speed_p[pio]); - pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]); - - pci_read_config_word(pdev, tfaddr-2, ®); - reg &= ~0x0200; /* Clear IORDY */ - if (ata_pio_need_iordy(adev)) - reg |= 0x0200; /* Enable IORDY */ - pci_write_config_word(pdev, tfaddr-2, reg); -} - -/** - * sil680_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the MWDMA/UDMA modes for the sil680 k - * chipset. The MWDMA mode values are pulled from a lookup table - * while the chipset uses mode number for UDMA. - */ - -static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static u8 ultra_table[2][7] = { - { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ - { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ - }; - static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long ma = sil680_seldev(ap, adev, 0x08); - unsigned long ua = sil680_seldev(ap, adev, 0x0C); - unsigned long addr_mask = 0x80 + 4 * ap->port_no; - int port_shift = adev->devno * 4; - u8 scsc, mode; - u16 multi, ultra; - - pci_read_config_byte(pdev, 0x8A, &scsc); - pci_read_config_byte(pdev, addr_mask, &mode); - pci_read_config_word(pdev, ma, &multi); - pci_read_config_word(pdev, ua, &ultra); - - /* Mask timing bits */ - ultra &= ~0x3F; - mode &= ~(0x03 << port_shift); - - /* Extract scsc */ - scsc = (scsc & 0x30) ? 1: 0; - - if (adev->dma_mode >= XFER_UDMA_0) { - multi = 0x10C1; - ultra |= ultra_table[scsc][adev->dma_mode - XFER_UDMA_0]; - mode |= (0x03 << port_shift); - } else { - multi = dma_table[adev->dma_mode - XFER_MW_DMA_0]; - mode |= (0x02 << port_shift); - } - pci_write_config_byte(pdev, addr_mask, mode); - pci_write_config_word(pdev, ma, multi); - pci_write_config_word(pdev, ua, ultra); -} - -static struct scsi_host_template sil680_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations sil680_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = sil680_set_piomode, - .set_dmamode = sil680_set_dmamode, - .mode_filter = ata_pci_default_filter, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sil680_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &sil680_port_ops - }; - static struct ata_port_info info_slow = { - .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &sil680_port_ops - }; - static struct ata_port_info *port_info[2] = {&info, &info}; - static int printed_version; - u32 class_rev = 0; - u8 tmpbyte = 0; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - /* FIXME: double check */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255); - - pci_write_config_byte(pdev, 0x80, 0x00); - pci_write_config_byte(pdev, 0x84, 0x00); - - pci_read_config_byte(pdev, 0x8A, &tmpbyte); - - printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); - - switch(tmpbyte & 0x30) { - case 0x00: - /* 133 clock attempt to force it on */ - pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); - break; - case 0x30: - /* if clocking is disabled */ - /* 133 clock attempt to force it on */ - pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); - break; - case 0x10: - /* 133 already */ - break; - case 0x20: - /* BIOS set PCI x2 clocking */ - break; - } - - pci_read_config_byte(pdev, 0x8A, &tmpbyte); - printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); - if ((tmpbyte & 0x30) == 0) - port_info[0] = port_info[1] = &info_slow; - - pci_write_config_byte(pdev, 0xA1, 0x72); - pci_write_config_word(pdev, 0xA2, 0x328A); - pci_write_config_dword(pdev, 0xA4, 0x62DD62DD); - pci_write_config_dword(pdev, 0xA8, 0x43924392); - pci_write_config_dword(pdev, 0xAC, 0x40094009); - pci_write_config_byte(pdev, 0xB1, 0x72); - pci_write_config_word(pdev, 0xB2, 0x328A); - pci_write_config_dword(pdev, 0xB4, 0x62DD62DD); - pci_write_config_dword(pdev, 0xB8, 0x43924392); - pci_write_config_dword(pdev, 0xBC, 0x40094009); - - switch(tmpbyte & 0x30) { - case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break; - case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break; - case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; - /* This last case is _NOT_ ok */ - case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); - return -EIO; - } - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id sil680[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680), }, - { 0, }, -}; - -static struct pci_driver sil680_pci_driver = { - .name = DRV_NAME, - .id_table = sil680, - .probe = sil680_init_one, - .remove = ata_pci_remove_one -}; - -static int __init sil680_init(void) -{ - return pci_register_driver(&sil680_pci_driver); -} - - -static void __exit sil680_exit(void) -{ - pci_unregister_driver(&sil680_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for SI680 PATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, sil680); -MODULE_VERSION(DRV_VERSION); - -module_init(sil680_init); -module_exit(sil680_exit); diff --git a/trunk/drivers/ata/pata_sis.c b/trunk/drivers/ata/pata_sis.c deleted file mode 100644 index 1cf5cf0a5365..000000000000 --- a/trunk/drivers/ata/pata_sis.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * pata_sis.c - SiS ATA driver - * - * (C) 2005 Red Hat - * - * Based upon linux/drivers/ide/pci/sis5513.c - * Copyright (C) 1999-2000 Andre Hedrick - * Copyright (C) 2002 Lionel Bouton , Maintainer - * Copyright (C) 2003 Vojtech Pavlik - * SiS Taiwan : for direct support and hardware. - * Daniela Engert : for initial ATA100 advices and numerous others. - * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : - * for checking code correctness, providing patches. - * Original tests and design on the SiS620 chipset. - * ATA100 tests and design on the SiS735 chipset. - * ATA16/33 support from specs - * ATA133 support for SiS961/962 by L.C. Chang - * - * - * TODO - * Check MWDMA on drives that don't support MWDMA speed pio cycles ? - * More Testing - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_sis" -#define DRV_VERSION "0.4.2" - -struct sis_chipset { - u16 device; /* PCI host ID */ - struct ata_port_info *info; /* Info block */ - /* Probably add family, cable detect type etc here to clean - up code later */ -}; - -/** - * sis_port_base - return PCI configuration base for dev - * @adev: device - * - * Returns the base of the PCI configuration registers for this port - * number. - */ - -static int sis_port_base(struct ata_device *adev) -{ - return 0x40 + (4 * adev->ap->port_no) + (2 * adev->devno); -} - -/** - * sis_133_pre_reset - check for 40/80 pin - * @ap: Port - * - * Perform cable detection for the later UDMA133 capable - * SiS chipset. - */ - -static int sis_133_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits sis_enable_bits[] = { - { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ - { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u16 tmp; - - if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - /* The top bit of this register is the cable detect bit */ - pci_read_config_word(pdev, 0x50 + 2 * ap->port_no, &tmp); - if (tmp & 0x8000) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - - return ata_std_prereset(ap); -} - -/** - * sis_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_133_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, sis_133_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - - -/** - * sis_66_pre_reset - check for 40/80 pin - * @ap: Port - * - * Perform cable detection on the UDMA66, UDMA100 and early UDMA133 - * SiS IDE controllers. - */ - -static int sis_66_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits sis_enable_bits[] = { - { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ - { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 tmp; - - if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - /* Older chips keep cable detect in bits 4/5 of reg 0x48 */ - pci_read_config_byte(pdev, 0x48, &tmp); - tmp >>= ap->port_no; - if (tmp & 0x10) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - - return ata_std_prereset(ap); -} - -/** - * sis_66_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * @classes: - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_66_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, sis_66_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * sis_old_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int sis_old_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits sis_enable_bits[] = { - { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ - { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - - -/** - * sis_old_error_handler - Probe specified port on PATA host controller - * @ap: Port to probe - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_old_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, sis_old_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * sis_set_fifo - Set RWP fifo bits for this device - * @ap: Port - * @adev: Device - * - * SIS chipsets implement prefetch/postwrite bits for each device - * on both channels. This functionality is not ATAPI compatible and - * must be configured according to the class of device present - */ - -static void sis_set_fifo(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 fifoctrl; - u8 mask = 0x11; - - mask <<= (2 * ap->port_no); - mask <<= adev->devno; - - /* This holds various bits including the FIFO control */ - pci_read_config_byte(pdev, 0x4B, &fifoctrl); - fifoctrl &= ~mask; - - /* Enable for ATA (disk) only */ - if (adev->class == ATA_DEV_ATA) - fifoctrl |= mask; - pci_write_config_byte(pdev, 0x4B, fifoctrl); -} - -/** - * sis_old_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring for. - * - * Set PIO mode for device, in host controller PCI config space. This - * function handles PIO set up for all chips that are pre ATA100 and - * also early ATA100 devices. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = sis_port_base(adev); - u8 t1, t2; - int speed = adev->pio_mode - XFER_PIO_0; - - const u8 active[] = { 0x00, 0x07, 0x04, 0x03, 0x01 }; - const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 }; - - sis_set_fifo(ap, adev); - - pci_read_config_byte(pdev, port, &t1); - pci_read_config_byte(pdev, port + 1, &t2); - - t1 &= ~0x0F; /* Clear active/recovery timings */ - t2 &= ~0x07; - - t1 |= active[speed]; - t2 |= recovery[speed]; - - pci_write_config_byte(pdev, port, t1); - pci_write_config_byte(pdev, port + 1, t2); -} - -/** - * sis_100_set_pioode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring for. - * - * Set PIO mode for device, in host controller PCI config space. This - * function handles PIO set up for ATA100 devices and early ATA133. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = sis_port_base(adev); - int speed = adev->pio_mode - XFER_PIO_0; - - const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; - - sis_set_fifo(ap, adev); - - pci_write_config_byte(pdev, port, actrec[speed]); -} - -/** - * sis_133_set_pioode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: Device we are configuring for. - * - * Set PIO mode for device, in host controller PCI config space. This - * function handles PIO set up for the later ATA133 devices. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int port = 0x40; - u32 t1; - u32 reg54; - int speed = adev->pio_mode - XFER_PIO_0; - - const u32 timing133[] = { - 0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */ - 0x0C266000, - 0x04263000, - 0x0C0A3000, - 0x05093000 - }; - const u32 timing100[] = { - 0x1E1C6000, /* Recovery << 24 | Act << 16 | Ini << 12 */ - 0x091C4000, - 0x031C2000, - 0x09072000, - 0x04062000 - }; - - sis_set_fifo(ap, adev); - - /* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */ - pci_read_config_dword(pdev, 0x54, ®54); - if (reg54 & 0x40000000) - port = 0x70; - port += 8 * ap->port_no + 4 * adev->devno; - - pci_read_config_dword(pdev, port, &t1); - t1 &= 0xC0C00FFF; /* Mask out timing */ - - if (t1 & 0x08) /* 100 or 133 ? */ - t1 |= timing133[speed]; - else - t1 |= timing100[speed]; - pci_write_config_byte(pdev, port, t1); -} - -/** - * sis_old_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * Handles pre UDMA and UDMA33 devices. Supports MWDMA as well unlike - * the old ide/pci driver. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int speed = adev->dma_mode - XFER_MW_DMA_0; - int drive_pci = sis_port_base(adev); - u16 timing; - - const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 }; - const u16 udma_bits[] = { 0xE000, 0xC000, 0xA000 }; - - pci_read_config_word(pdev, drive_pci, &timing); - - if (adev->dma_mode < XFER_UDMA_0) { - /* bits 3-0 hold recovery timing bits 8-10 active timing and - the higer bits are dependant on the device */ - timing &= ~ 0x870F; - timing |= mwdma_bits[speed]; - pci_write_config_word(pdev, drive_pci, timing); - } else { - /* Bit 15 is UDMA on/off, bit 13-14 are cycle time */ - speed = adev->dma_mode - XFER_UDMA_0; - timing &= ~0x6000; - timing |= udma_bits[speed]; - } -} - -/** - * sis_66_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * Handles UDMA66 and early UDMA100 devices. Supports MWDMA as well unlike - * the old ide/pci driver. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int speed = adev->dma_mode - XFER_MW_DMA_0; - int drive_pci = sis_port_base(adev); - u16 timing; - - const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 }; - const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000}; - - pci_read_config_word(pdev, drive_pci, &timing); - - if (adev->dma_mode < XFER_UDMA_0) { - /* bits 3-0 hold recovery timing bits 8-10 active timing and - the higer bits are dependant on the device, bit 15 udma */ - timing &= ~ 0x870F; - timing |= mwdma_bits[speed]; - } else { - /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ - speed = adev->dma_mode - XFER_UDMA_0; - timing &= ~0x6000; - timing |= udma_bits[speed]; - } - pci_write_config_word(pdev, drive_pci, timing); -} - -/** - * sis_100_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * Handles UDMA66 and early UDMA100 devices. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int speed = adev->dma_mode - XFER_MW_DMA_0; - int drive_pci = sis_port_base(adev); - u16 timing; - - const u16 udma_bits[] = { 0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100}; - - pci_read_config_word(pdev, drive_pci, &timing); - - if (adev->dma_mode < XFER_UDMA_0) { - /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */ - } else { - /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ - speed = adev->dma_mode - XFER_UDMA_0; - timing &= ~0x0F00; - timing |= udma_bits[speed]; - } - pci_write_config_word(pdev, drive_pci, timing); -} - -/** - * sis_133_early_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * Handles early SiS 961 bridges. Supports MWDMA as well unlike - * the old ide/pci driver. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int speed = adev->dma_mode - XFER_MW_DMA_0; - int drive_pci = sis_port_base(adev); - u16 timing; - - const u16 udma_bits[] = { 0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100}; - - pci_read_config_word(pdev, drive_pci, &timing); - - if (adev->dma_mode < XFER_UDMA_0) { - /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */ - } else { - /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ - speed = adev->dma_mode - XFER_UDMA_0; - timing &= ~0x0F00; - timing |= udma_bits[speed]; - } - pci_write_config_word(pdev, drive_pci, timing); -} - -/** - * sis_133_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: Device to program - * - * Set UDMA/MWDMA mode for device, in host controller PCI config space. - * Handles early SiS 961 bridges. Supports MWDMA as well unlike - * the old ide/pci driver. - * - * LOCKING: - * None (inherited from caller). - */ - -static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int speed = adev->dma_mode - XFER_MW_DMA_0; - int port = 0x40; - u32 t1; - u32 reg54; - - /* bits 4- cycle time 8 - cvs time */ - const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 }; - const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 }; - - /* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */ - pci_read_config_dword(pdev, 0x54, ®54); - if (reg54 & 0x40000000) - port = 0x70; - port += (8 * ap->port_no) + (4 * adev->devno); - - pci_read_config_dword(pdev, port, &t1); - - if (adev->dma_mode < XFER_UDMA_0) { - t1 &= ~0x00000004; - /* FIXME: need data sheet to add MWDMA here. Also lacking on - ide/pci driver */ - } else { - speed = adev->dma_mode - XFER_UDMA_0; - /* if & 8 no UDMA133 - need info for ... */ - t1 &= ~0x00000FF0; - t1 |= 0x00000004; - if (t1 & 0x08) - t1 |= timing_u133[speed]; - else - t1 |= timing_u100[speed]; - } - pci_write_config_dword(pdev, port, t1); -} - -static struct scsi_host_template sis_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static const struct ata_port_operations sis_133_ops = { - .port_disable = ata_port_disable, - .set_piomode = sis_133_set_piomode, - .set_dmamode = sis_133_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sis_133_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations sis_133_early_ops = { - .port_disable = ata_port_disable, - .set_piomode = sis_100_set_piomode, - .set_dmamode = sis_133_early_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sis_66_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations sis_100_ops = { - .port_disable = ata_port_disable, - .set_piomode = sis_100_set_piomode, - .set_dmamode = sis_100_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sis_66_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations sis_66_ops = { - .port_disable = ata_port_disable, - .set_piomode = sis_old_set_piomode, - .set_dmamode = sis_66_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sis_66_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations sis_old_ops = { - .port_disable = ata_port_disable, - .set_piomode = sis_old_set_piomode, - .set_dmamode = sis_old_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = sis_old_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static struct ata_port_info sis_info = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = 0, - .port_ops = &sis_old_ops, -}; -static struct ata_port_info sis_info33 = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, /* UDMA 33 */ - .port_ops = &sis_old_ops, -}; -static struct ata_port_info sis_info66 = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA4, /* UDMA 66 */ - .port_ops = &sis_66_ops, -}; -static struct ata_port_info sis_info100 = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA5, - .port_ops = &sis_100_ops, -}; -static struct ata_port_info sis_info100_early = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .udma_mask = ATA_UDMA5, - .pio_mask = 0x1f, /* pio0-4 */ - .port_ops = &sis_66_ops, -}; -static struct ata_port_info sis_info133 = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, - .port_ops = &sis_133_ops, -}; -static struct ata_port_info sis_info133_early = { - .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, - .port_ops = &sis_133_early_ops, -}; - - -static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis) -{ - u16 regw; - u8 reg; - - if (sis->info == &sis_info133) { - pci_read_config_word(pdev, 0x50, ®w); - if (regw & 0x08) - pci_write_config_word(pdev, 0x50, regw & ~0x08); - pci_read_config_word(pdev, 0x52, ®w); - if (regw & 0x08) - pci_write_config_word(pdev, 0x52, regw & ~0x08); - return; - } - - if (sis->info == &sis_info133_early || sis->info == &sis_info100) { - /* Fix up latency */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); - /* Set compatibility bit */ - pci_read_config_byte(pdev, 0x49, ®); - if (!(reg & 0x01)) - pci_write_config_byte(pdev, 0x49, reg | 0x01); - return; - } - - if (sis->info == &sis_info66 || sis->info == &sis_info100_early) { - /* Fix up latency */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); - /* Set compatibility bit */ - pci_read_config_byte(pdev, 0x52, ®); - if (!(reg & 0x04)) - pci_write_config_byte(pdev, 0x52, reg | 0x04); - return; - } - - if (sis->info == &sis_info33) { - pci_read_config_byte(pdev, PCI_CLASS_PROG, ®); - if (( reg & 0x0F ) != 0x00) - pci_write_config_byte(pdev, PCI_CLASS_PROG, reg & 0xF0); - /* Fall through to ATA16 fixup below */ - } - - if (sis->info == &sis_info || sis->info == &sis_info33) { - /* force per drive recovery and active timings - needed on ATA_33 and below chips */ - pci_read_config_byte(pdev, 0x52, ®); - if (!(reg & 0x08)) - pci_write_config_byte(pdev, 0x52, reg|0x08); - return; - } - - BUG(); -} - -/** - * sis_init_one - Register SiS ATA PCI device with kernel services - * @pdev: PCI device to register - * @ent: Entry in sis_pci_tbl matching with @pdev - * - * Called from kernel PCI layer. We probe for combined mode (sigh), - * and then hand over control to libata, for it to do the rest. - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, or -ERRNO value. - */ - -static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - static struct ata_port_info *port_info[2]; - struct ata_port_info *port; - struct pci_dev *host = NULL; - struct sis_chipset *chipset = NULL; - - static struct sis_chipset sis_chipsets[] = { - { 0x0745, &sis_info100 }, - { 0x0735, &sis_info100 }, - { 0x0733, &sis_info100 }, - { 0x0635, &sis_info100 }, - { 0x0633, &sis_info100 }, - - { 0x0730, &sis_info100_early }, /* 100 with ATA 66 layout */ - { 0x0550, &sis_info100_early }, /* 100 with ATA 66 layout */ - - { 0x0640, &sis_info66 }, - { 0x0630, &sis_info66 }, - { 0x0620, &sis_info66 }, - { 0x0540, &sis_info66 }, - { 0x0530, &sis_info66 }, - - { 0x5600, &sis_info33 }, - { 0x5598, &sis_info33 }, - { 0x5597, &sis_info33 }, - { 0x5591, &sis_info33 }, - { 0x5582, &sis_info33 }, - { 0x5581, &sis_info33 }, - - { 0x5596, &sis_info }, - { 0x5571, &sis_info }, - { 0x5517, &sis_info }, - { 0x5511, &sis_info }, - - {0} - }; - static struct sis_chipset sis133_early = { - 0x0, &sis_info133_early - }; - static struct sis_chipset sis133 = { - 0x0, &sis_info133 - }; - static struct sis_chipset sis100_early = { - 0x0, &sis_info100_early - }; - static struct sis_chipset sis100 = { - 0x0, &sis_info100 - }; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); - - /* We have to find the bridge first */ - - for (chipset = &sis_chipsets[0]; chipset->device; chipset++) { - host = pci_get_device(PCI_VENDOR_ID_SI, chipset->device, NULL); - if (host != NULL) { - if (chipset->device == 0x630) { /* SIS630 */ - u8 host_rev; - pci_read_config_byte(host, PCI_REVISION_ID, &host_rev); - if (host_rev >= 0x30) /* 630 ET */ - chipset = &sis100_early; - } - break; - } - } - - /* Look for concealed bridges */ - if (host == NULL) { - /* Second check */ - u32 idemisc; - u16 trueid; - - /* Disable ID masking and register remapping then - see what the real ID is */ - - pci_read_config_dword(pdev, 0x54, &idemisc); - pci_write_config_dword(pdev, 0x54, idemisc & 0x7fffffff); - pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid); - pci_write_config_dword(pdev, 0x54, idemisc); - - switch(trueid) { - case 0x5518: /* SIS 962/963 */ - chipset = &sis133; - if ((idemisc & 0x40000000) == 0) { - pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000); - printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n"); - } - break; - case 0x0180: /* SIS 965/965L */ - chipset = &sis133; - break; - case 0x1180: /* SIS 966/966L */ - chipset = &sis133; - break; - } - } - - /* Further check */ - if (chipset == NULL) { - struct pci_dev *lpc_bridge; - u16 trueid; - u8 prefctl; - u8 idecfg; - u8 sbrev; - - /* Try the second unmasking technique */ - pci_read_config_byte(pdev, 0x4a, &idecfg); - pci_write_config_byte(pdev, 0x4a, idecfg | 0x10); - pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid); - pci_write_config_byte(pdev, 0x4a, idecfg); - - switch(trueid) { - case 0x5517: - lpc_bridge = pci_get_slot(pdev->bus, 0x10); /* Bus 0 Dev 2 Fn 0 */ - if (lpc_bridge == NULL) - break; - pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); - pci_read_config_byte(pdev, 0x49, &prefctl); - pci_dev_put(lpc_bridge); - - if (sbrev == 0x10 && (prefctl & 0x80)) { - chipset = &sis133_early; - break; - } - chipset = &sis100; - break; - } - } - pci_dev_put(host); - - /* No chipset info, no support */ - if (chipset == NULL) - return -ENODEV; - - port = chipset->info; - port->private_data = chipset; - - sis_fixup(pdev, chipset); - - port_info[0] = port_info[1] = port; - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id sis_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x5513), }, /* SiS 5513 */ - { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x5518), }, /* SiS 5518 */ - { } -}; - -static struct pci_driver sis_pci_driver = { - .name = DRV_NAME, - .id_table = sis_pci_tbl, - .probe = sis_init_one, - .remove = ata_pci_remove_one, -}; - -static int __init sis_init(void) -{ - return pci_register_driver(&sis_pci_driver); -} - -static void __exit sis_exit(void) -{ - pci_unregister_driver(&sis_pci_driver); -} - - -module_init(sis_init); -module_exit(sis_exit); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("SCSI low-level driver for SiS ATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, sis_pci_tbl); -MODULE_VERSION(DRV_VERSION); - diff --git a/trunk/drivers/ata/pata_sl82c105.c b/trunk/drivers/ata/pata_sl82c105.c deleted file mode 100644 index f8499786917a..000000000000 --- a/trunk/drivers/ata/pata_sl82c105.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * pata_sl82c105.c - SL82C105 PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * Based in part on linux/drivers/ide/pci/sl82c105.c - * SL82C105/Winbond 553 IDE driver - * - * and in part on the documentation and errata sheet - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_sl82c105" -#define DRV_VERSION "0.2.2" - -enum { - /* - * SL82C105 PCI config register 0x40 bits. - */ - CTRL_IDE_IRQB = (1 << 30), - CTRL_IDE_IRQA = (1 << 28), - CTRL_LEGIRQ = (1 << 11), - CTRL_P1F16 = (1 << 5), - CTRL_P1EN = (1 << 4), - CTRL_P0F16 = (1 << 1), - CTRL_P0EN = (1 << 0) -}; - -/** - * sl82c105_pre_reset - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int sl82c105_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits sl82c105_enable_bits[] = { - { 0x40, 1, 0x01, 0x01 }, - { 0x40, 1, 0x10, 0x10 } - }; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no])) { - ata_port_disable(ap); - dev_printk(KERN_INFO, &pdev->dev, "port disabled. ignoring.\n"); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - - -static void sl82c105_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, sl82c105_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - - -/** - * sl82c105_configure_piomode - set chip PIO timing - * @ap: ATA interface - * @adev: ATA device - * @pio: PIO mode - * - * Called to do the PIO mode setup. Our timing registers are shared - * so a configure_dmamode call will undo any work we do here and vice - * versa - */ - -static void sl82c105_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static u16 pio_timing[5] = { - 0x50D, 0x407, 0x304, 0x242, 0x240 - }; - u16 dummy; - int timing = 0x44 + (8 * ap->port_no) + (4 * adev->devno); - - pci_write_config_word(pdev, timing, pio_timing[pio]); - /* Can we lose this oddity of the old driver */ - pci_read_config_word(pdev, timing, &dummy); -} - -/** - * sl82c105_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the PIO mode setup. Our timing registers are shared - * but we want to set the PIO timing by default. - */ - -static void sl82c105_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - sl82c105_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -} - -/** - * sl82c105_configure_dmamode - set DMA mode in chip - * @ap: ATA interface - * @adev: ATA device - * - * Load DMA cycle times into the chip ready for a DMA transfer - * to occur. - */ - -static void sl82c105_configure_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static u16 dma_timing[3] = { - 0x707, 0x201, 0x200 - }; - u16 dummy; - int timing = 0x44 + (8 * ap->port_no) + (4 * adev->devno); - int dma = adev->dma_mode - XFER_MW_DMA_0; - - pci_write_config_word(pdev, timing, dma_timing[dma]); - /* Can we lose this oddity of the old driver */ - pci_read_config_word(pdev, timing, &dummy); -} - -/** - * sl82c105_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Called to do the DMA mode setup. This replaces the PIO timings - * for the device in question. Set appropriate PIO timings not DMA - * timings at this point. - */ - -static void sl82c105_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - switch(adev->dma_mode) { - case XFER_MW_DMA_0: - sl82c105_configure_piomode(ap, adev, 1); - break; - case XFER_MW_DMA_1: - sl82c105_configure_piomode(ap, adev, 3); - break; - case XFER_MW_DMA_2: - sl82c105_configure_piomode(ap, adev, 3); - break; - default: - BUG(); - } -} - -/** - * sl82c105_reset_engine - Reset the DMA engine - * @ap: ATA interface - * - * The sl82c105 has some serious problems with the DMA engine - * when transfers don't run as expected or ATAPI is used. The - * recommended fix is to reset the engine each use using a chip - * test register. - */ - -static void sl82c105_reset_engine(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u16 val; - - pci_read_config_word(pdev, 0x7E, &val); - pci_write_config_word(pdev, 0x7E, val | 4); - pci_write_config_word(pdev, 0x7E, val & ~4); -} - -/** - * sl82c105_bmdma_start - DMA engine begin - * @qc: ATA command - * - * Reset the DMA engine each use as recommended by the errata - * document. - * - * FIXME: if we switch clock at BMDMA start/end we might get better - * PIO performance on DMA capable devices. - */ - -static void sl82c105_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - - sl82c105_reset_engine(ap); - - /* Set the clocks for DMA */ - sl82c105_configure_dmamode(ap, qc->dev); - /* Activate DMA */ - ata_bmdma_start(qc); -} - -/** - * sl82c105_bmdma_end - DMA engine stop - * @qc: ATA command - * - * Reset the DMA engine each use as recommended by the errata - * document. - * - * This function is also called to turn off DMA when a timeout occurs - * during DMA operation. In both cases we need to reset the engine, - * so no actual eng_timeout handler is required. - * - * We assume bmdma_stop is always called if bmdma_start as called. If - * not then we may need to wrap qc_issue. - */ - -static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - - ata_bmdma_stop(qc); - sl82c105_reset_engine(ap); - - /* This will redo the initial setup of the DMA device to matching - PIO timings */ - sl82c105_set_dmamode(ap, qc->dev); -} - -static struct scsi_host_template sl82c105_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations sl82c105_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = sl82c105_set_piomode, - .set_dmamode = sl82c105_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .error_handler = sl82c105_error_handler, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = sl82c105_bmdma_start, - .bmdma_stop = sl82c105_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * sl82c105_bridge_revision - find bridge version - * @pdev: PCI device for the ATA function - * - * Locates the PCI bridge associated with the ATA function and - * providing it is a Winbond 553 reports the revision. If it cannot - * find a revision or the right device it returns -1 - */ - -static int sl82c105_bridge_revision(struct pci_dev *pdev) -{ - struct pci_dev *bridge; - u8 rev; - - /* - * The bridge should be part of the same device, but function 0. - */ - bridge = pci_get_slot(pdev->bus, - PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); - if (!bridge) - return -1; - - /* - * Make sure it is a Winbond 553 and is an ISA bridge. - */ - if (bridge->vendor != PCI_VENDOR_ID_WINBOND || - bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || - bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { - pci_dev_put(bridge); - return -1; - } - /* - * We need to find function 0's revision, not function 1 - */ - pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); - - pci_dev_put(bridge); - return rev; -} - - -static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info_dma = { - .sht = &sl82c105_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &sl82c105_port_ops - }; - static struct ata_port_info info_early = { - .sht = &sl82c105_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &sl82c105_port_ops - }; - static struct ata_port_info *port_info[2] = { &info_early, &info_early }; - u32 val; - int rev; - - rev = sl82c105_bridge_revision(dev); - - if (rev == -1) - dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n"); - else if (rev <= 5) - dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n"); - else { - port_info[0] = &info_dma; - port_info[1] = &info_dma; - } - - pci_read_config_dword(dev, 0x40, &val); - val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; - pci_write_config_dword(dev, 0x40, val); - - - return ata_pci_init_one(dev, port_info, 1); /* For now */ -} - -static struct pci_device_id sl82c105[] = { - { PCI_DEVICE(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105), }, - { 0, }, -}; - -static struct pci_driver sl82c105_pci_driver = { - .name = DRV_NAME, - .id_table = sl82c105, - .probe = sl82c105_init_one, - .remove = ata_pci_remove_one -}; - -static int __init sl82c105_init(void) -{ - return pci_register_driver(&sl82c105_pci_driver); -} - - -static void __exit sl82c105_exit(void) -{ - pci_unregister_driver(&sl82c105_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Sl82c105"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, sl82c105); -MODULE_VERSION(DRV_VERSION); - -module_init(sl82c105_init); -module_exit(sl82c105_exit); diff --git a/trunk/drivers/ata/pata_triflex.c b/trunk/drivers/ata/pata_triflex.c deleted file mode 100644 index 36f788728f3f..000000000000 --- a/trunk/drivers/ata/pata_triflex.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * pata_triflex.c - Compaq PATA for new ATA layer - * (C) 2005 Red Hat Inc - * Alan Cox - * - * based upon - * - * triflex.c - * - * IDE Chipset driver for the Compaq TriFlex IDE controller. - * - * Known to work with the Compaq Workstation 5x00 series. - * - * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. - * Author: Torben Mathiasen - * - * 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 program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Loosely based on the piix & svwks drivers. - * - * Documentation: - * Not publically available. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_triflex" -#define DRV_VERSION "0.2.5" - -/** - * triflex_probe_init - probe begin - * @ap: ATA port - * - * Set up cable type and use generic probe init - */ - -static int triflex_probe_init(struct ata_port *ap) -{ - static const struct pci_bits triflex_enable_bits[] = { - { 0x80, 1, 0x01, 0x01 }, - { 0x80, 1, 0x02, 0x02 } - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - - - -static void triflex_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, triflex_probe_init, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * triflex_load_timing - timing configuration - * @ap: ATA interface - * @adev: Device on the bus - * @speed: speed to configure - * - * The Triflex has one set of timings per device per channel. This - * means we must do some switching. As the PIO and DMA timings don't - * match we have to do some reloading unlike PIIX devices where tuning - * tricks can avoid it. - */ - -static void triflex_load_timing(struct ata_port *ap, struct ata_device *adev, int speed) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 timing = 0; - u32 triflex_timing, old_triflex_timing; - int channel_offset = ap->port_no ? 0x74: 0x70; - unsigned int is_slave = (adev->devno != 0); - - - pci_read_config_dword(pdev, channel_offset, &old_triflex_timing); - triflex_timing = old_triflex_timing; - - switch(speed) - { - case XFER_MW_DMA_2: - timing = 0x0103;break; - case XFER_MW_DMA_1: - timing = 0x0203;break; - case XFER_MW_DMA_0: - timing = 0x0808;break; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - timing = 0x0F0F;break; - case XFER_PIO_4: - timing = 0x0202;break; - case XFER_PIO_3: - timing = 0x0204;break; - case XFER_PIO_2: - timing = 0x0404;break; - case XFER_PIO_1: - timing = 0x0508;break; - case XFER_PIO_0: - timing = 0x0808;break; - default: - BUG(); - } - triflex_timing &= ~ (0xFFFF << (16 * is_slave)); - triflex_timing |= (timing << (16 * is_slave)); - - if (triflex_timing != old_triflex_timing) - pci_write_config_dword(pdev, channel_offset, triflex_timing); -} - -/** - * triflex_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Use the timing loader to set up the PIO mode. We have to do this - * because DMA start/stop will only be called once DMA occurs. If there - * has been no DMA then the PIO timings are still needed. - */ -static void triflex_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - triflex_load_timing(ap, adev, adev->pio_mode); -} - -/** - * triflex_dma_start - DMA start callback - * @qc: Command in progress - * - * Usually drivers set the DMA timing at the point the set_dmamode call - * is made. Triflex however requires we load new timings on the - * transition or keep matching PIO/DMA pairs (ie MWDMA2/PIO4 etc). - * We load the DMA timings just before starting DMA and then restore - * the PIO timing when the DMA is finished. - */ - -static void triflex_bmdma_start(struct ata_queued_cmd *qc) -{ - triflex_load_timing(qc->ap, qc->dev, qc->dev->dma_mode); - ata_bmdma_start(qc); -} - -/** - * triflex_dma_stop - DMA stop callback - * @ap: ATA interface - * @adev: ATA device - * - * We loaded new timings in dma_start, as a result we need to restore - * the PIO timings in dma_stop so that the next command issue gets the - * right clock values. - */ - -static void triflex_bmdma_stop(struct ata_queued_cmd *qc) -{ - ata_bmdma_stop(qc); - triflex_load_timing(qc->ap, qc->dev, qc->dev->pio_mode); -} - -static struct scsi_host_template triflex_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations triflex_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = triflex_set_piomode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = triflex_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = triflex_bmdma_start, - .bmdma_stop = triflex_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static struct ata_port_info info = { - .sht = &triflex_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &triflex_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; - static int printed_version; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - - return ata_pci_init_one(dev, port_info, 2); -} - -static const struct pci_device_id triflex[] = { - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, }, -}; - -static struct pci_driver triflex_pci_driver = { - .name = DRV_NAME, - .id_table = triflex, - .probe = triflex_init_one, - .remove = ata_pci_remove_one -}; - -static int __init triflex_init(void) -{ - return pci_register_driver(&triflex_pci_driver); -} - - -static void __exit triflex_exit(void) -{ - pci_unregister_driver(&triflex_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Compaq Triflex"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, triflex); -MODULE_VERSION(DRV_VERSION); - -module_init(triflex_init); -module_exit(triflex_exit); diff --git a/trunk/drivers/ata/pata_via.c b/trunk/drivers/ata/pata_via.c deleted file mode 100644 index 1b2ff133b163..000000000000 --- a/trunk/drivers/ata/pata_via.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * pata_via.c - VIA PATA for new ATA layer - * (C) 2005-2006 Red Hat Inc - * Alan Cox - * - * Documentation - * Most chipset documentation available under NDA only - * - * VIA version guide - * VIA VT82C561 - early design, uses ata_generic currently - * VIA VT82C576 - MWDMA, 33Mhz - * VIA VT82C586 - MWDMA, 33Mhz - * VIA VT82C586a - Added UDMA to 33Mhz - * VIA VT82C586b - UDMA33 - * VIA VT82C596a - Nonfunctional UDMA66 - * VIA VT82C596b - Working UDMA66 - * VIA VT82C686 - Nonfunctional UDMA66 - * VIA VT82C686a - Working UDMA66 - * VIA VT82C686b - Updated to UDMA100 - * VIA VT8231 - UDMA100 - * VIA VT8233 - UDMA100 - * VIA VT8233a - UDMA133 - * VIA VT8233c - UDMA100 - * VIA VT8235 - UDMA133 - * VIA VT8237 - UDMA133 - * - * Most registers remain compatible across chips. Others start reserved - * and acquire sensible semantics if set to 1 (eg cable detect). A few - * exceptions exist, notably around the FIFO settings. - * - * One additional quirk of the VIA design is that like ALi they use few - * PCI IDs for a lot of chips. - * - * Based heavily on: - * - * Version 3.38 - * - * VIA IDE driver for Linux. Supported southbridges: - * - * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, - * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235, vt8237 - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_via" -#define DRV_VERSION "0.1.13" - -/* - * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx - * driver. - */ - -enum { - VIA_UDMA = 0x007, - VIA_UDMA_NONE = 0x000, - VIA_UDMA_33 = 0x001, - VIA_UDMA_66 = 0x002, - VIA_UDMA_100 = 0x003, - VIA_UDMA_133 = 0x004, - VIA_BAD_PREQ = 0x010, /* Crashes if PREQ# till DDACK# set */ - VIA_BAD_CLK66 = 0x020, /* 66 MHz clock doesn't work correctly */ - VIA_SET_FIFO = 0x040, /* Needs to have FIFO split set */ - VIA_NO_UNMASK = 0x080, /* Doesn't work with IRQ unmasking on */ - VIA_BAD_ID = 0x100, /* Has wrong vendor ID (0x1107) */ - VIA_BAD_AST = 0x200, /* Don't touch Address Setup Timing */ - VIA_NO_ENABLES = 0x400, /* Has no enablebits */ -}; - -/* - * VIA SouthBridge chips. - */ - -static const struct via_isa_bridge { - const char *name; - u16 id; - u8 rev_min; - u8 rev_max; - u16 flags; -} via_isa_bridges[] = { - { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, - { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, - { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, - { NULL } -}; - -/** - * via_cable_detect - cable detection - * @ap: ATA port - * - * Perform cable detection. Actually for the VIA case the BIOS - * already did this for us. We read the values provided by the - * BIOS. If you are using an 8235 in a non-PC configuration you - * may need to update this code. - * - * Hotplug also impacts on this. - */ - -static int via_cable_detect(struct ata_port *ap) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 ata66; - - pci_read_config_dword(pdev, 0x50, &ata66); - /* Check both the drive cable reporting bits, we might not have - two drives */ - if (ata66 & (0x10100000 >> (16 * ap->port_no))) - return ATA_CBL_PATA80; - else - return ATA_CBL_PATA40; -} - -static int via_pre_reset(struct ata_port *ap) -{ - const struct via_isa_bridge *config = ap->host->private_data; - - if (!(config->flags & VIA_NO_ENABLES)) { - static const struct pci_bits via_enable_bits[] = { - { 0x40, 1, 0x02, 0x02 }, - { 0x40, 1, 0x01, 0x01 } - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no])) { - ata_port_disable(ap); - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return 0; - } - } - - if ((config->flags & VIA_UDMA) >= VIA_UDMA_66) - ap->cbl = via_cable_detect(ap); - else - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - - -/** - * via_error_handler - reset for VIA chips - * @ap: ATA port - * - * Handle the reset callback for the later chips with cable detect - */ - -static void via_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -/** - * via_do_set_mode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * @mode: ATA mode being programmed - * @tdiv: Clocks per PCI clock - * @set_ast: Set to program address setup - * @udma_type: UDMA mode/format of registers - * - * Program the VIA registers for DMA and PIO modes. Uses the ata timing - * support in order to compute modes. - * - * FIXME: Hotplug will require we serialize multiple mode changes - * on the two channels. - */ - -static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mode, int tdiv, int set_ast, int udma_type) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_device *peer = ata_dev_pair(adev); - struct ata_timing t, p; - static int via_clock = 33333; /* Bus clock in kHZ - ought to be tunable one day */ - unsigned long T = 1000000000 / via_clock; - unsigned long UT = T/tdiv; - int ut; - int offset = 3 - (2*ap->port_no) - adev->devno; - - - /* Calculate the timing values we require */ - ata_timing_compute(adev, mode, &t, T, UT); - - /* We share 8bit timing so we must merge the constraints */ - if (peer) { - if (peer->pio_mode) { - ata_timing_compute(peer, peer->pio_mode, &p, T, UT); - ata_timing_merge(&p, &t, &t, ATA_TIMING_8BIT); - } - } - - /* Address setup is programmable but breaks on UDMA133 setups */ - if (set_ast) { - u8 setup; /* 2 bits per drive */ - int shift = 2 * offset; - - pci_read_config_byte(pdev, 0x4C, &setup); - setup &= ~(3 << shift); - setup |= FIT(t.setup, 1, 4) << shift; /* 1,4 or 1,4 - 1 FIXME */ - pci_write_config_byte(pdev, 0x4C, setup); - } - - /* Load the PIO mode bits */ - pci_write_config_byte(pdev, 0x4F - ap->port_no, - ((FIT(t.act8b, 1, 16) - 1) << 4) | (FIT(t.rec8b, 1, 16) - 1)); - pci_write_config_byte(pdev, 0x48 + offset, - ((FIT(t.active, 1, 16) - 1) << 4) | (FIT(t.recover, 1, 16) - 1)); - - /* Load the UDMA bits according to type */ - switch(udma_type) { - default: - /* BUG() ? */ - /* fall through */ - case 33: - ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 5) - 2)) : 0x03; - break; - case 66: - ut = t.udma ? (0xe8 | (FIT(t.udma, 2, 9) - 2)) : 0x0f; - break; - case 100: - ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; - break; - case 133: - ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; - break; - } - /* Set UDMA unless device is not UDMA capable */ - if (udma_type) - pci_write_config_byte(pdev, 0x50 + offset, ut); -} - -static void via_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - const struct via_isa_bridge *config = ap->host->private_data; - int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; - int mode = config->flags & VIA_UDMA; - static u8 tclock[5] = { 1, 1, 2, 3, 4 }; - static u8 udma[5] = { 0, 33, 66, 100, 133 }; - - via_do_set_mode(ap, adev, adev->pio_mode, tclock[mode], set_ast, udma[mode]); -} - -static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - const struct via_isa_bridge *config = ap->host->private_data; - int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; - int mode = config->flags & VIA_UDMA; - static u8 tclock[5] = { 1, 1, 2, 3, 4 }; - static u8 udma[5] = { 0, 33, 66, 100, 133 }; - - via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); -} - -static struct scsi_host_template via_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations via_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = via_set_piomode, - .set_dmamode = via_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = via_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -static struct ata_port_operations via_port_ops_noirq = { - .port_disable = ata_port_disable, - .set_piomode = via_set_piomode, - .set_dmamode = via_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = via_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .data_xfer = ata_pio_data_xfer_noirq, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; - -/** - * via_init_one - discovery callback - * @pdev: PCI device ID - * @id: PCI table info - * - * A VIA IDE interface has been discovered. Figure out what revision - * and perform configuration work before handing it to the ATA layer - */ - -static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - /* Early VIA without UDMA support */ - static struct ata_port_info via_mwdma_info = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &via_port_ops - }; - /* Ditto with IRQ masking required */ - static struct ata_port_info via_mwdma_info_borked = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .port_ops = &via_port_ops_noirq, - }; - /* VIA UDMA 33 devices (and borked 66) */ - static struct ata_port_info via_udma33_info = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7, - .port_ops = &via_port_ops - }; - /* VIA UDMA 66 devices */ - static struct ata_port_info via_udma66_info = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, - .port_ops = &via_port_ops - }; - /* VIA UDMA 100 devices */ - static struct ata_port_info via_udma100_info = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &via_port_ops - }; - /* UDMA133 with bad AST (All current 133) */ - static struct ata_port_info via_udma133_info = { - .sht = &via_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, /* FIXME: should check north bridge */ - .port_ops = &via_port_ops - }; - struct ata_port_info *port_info[2], *type; - struct pci_dev *isa = NULL; - const struct via_isa_bridge *config; - static int printed_version; - u8 t; - u8 enable; - u32 timing; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - - /* To find out how the IDE will behave and what features we - actually have to look at the bridge not the IDE controller */ - for (config = via_isa_bridges; config->id; config++) - if ((isa = pci_get_device(PCI_VENDOR_ID_VIA + - !!(config->flags & VIA_BAD_ID), - config->id, NULL))) { - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - if (t >= config->rev_min && - t <= config->rev_max) - break; - pci_dev_put(isa); - } - - if (!config->id) { - printk(KERN_WARNING "via: Unknown VIA SouthBridge, disabling.\n"); - return -ENODEV; - } - pci_dev_put(isa); - - /* 0x40 low bits indicate enabled channels */ - pci_read_config_byte(pdev, 0x40 , &enable); - enable &= 3; - if (enable == 0) { - return -ENODEV; - } - - /* Initialise the FIFO for the enabled channels. */ - if (config->flags & VIA_SET_FIFO) { - u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; - u8 fifo; - - pci_read_config_byte(pdev, 0x43, &fifo); - - /* Clear PREQ# until DDACK# for errata */ - if (config->flags & VIA_BAD_PREQ) - fifo &= 0x7F; - else - fifo &= 0x9f; - /* Turn on FIFO for enabled channels */ - fifo |= fifo_setting[enable]; - pci_write_config_byte(pdev, 0x43, fifo); - } - /* Clock set up */ - switch(config->flags & VIA_UDMA) { - case VIA_UDMA_NONE: - if (config->flags & VIA_NO_UNMASK) - type = &via_mwdma_info_borked; - else - type = &via_mwdma_info; - break; - case VIA_UDMA_33: - type = &via_udma33_info; - break; - case VIA_UDMA_66: - type = &via_udma66_info; - /* The 66 MHz devices require we enable the clock */ - pci_read_config_dword(pdev, 0x50, &timing); - timing |= 0x80008; - pci_write_config_dword(pdev, 0x50, timing); - break; - case VIA_UDMA_100: - type = &via_udma100_info; - break; - case VIA_UDMA_133: - type = &via_udma133_info; - break; - default: - WARN_ON(1); - return -ENODEV; - } - - if (config->flags & VIA_BAD_CLK66) { - /* Disable the 66MHz clock on problem devices */ - pci_read_config_dword(pdev, 0x50, &timing); - timing &= ~0x80008; - pci_write_config_dword(pdev, 0x50, timing); - } - - /* We have established the device type, now fire it up */ - type->private_data = (void *)config; - - port_info[0] = port_info[1] = type; - return ata_pci_init_one(pdev, port_info, 2); -} - -static const struct pci_device_id via[] = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1), }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1), }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410), }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), }, - { 0, }, -}; - -static struct pci_driver via_pci_driver = { - .name = DRV_NAME, - .id_table = via, - .probe = via_init_one, - .remove = ata_pci_remove_one -}; - -static int __init via_init(void) -{ - return pci_register_driver(&via_pci_driver); -} - - -static void __exit via_exit(void) -{ - pci_unregister_driver(&via_pci_driver); -} - - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for VIA PATA"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, via); -MODULE_VERSION(DRV_VERSION); - -module_init(via_init); -module_exit(via_exit); diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 5109fa37c662..ad1d7065a1b2 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4177,6 +4177,11 @@ static int __init floppy_init(void) int i, unit, drive; int err, dr; +#if defined(CONFIG_PPC_MERGE) + if (check_legacy_ioport(FDC1)) + return -ENODEV; +#endif + raw_cmd = NULL; for (dr = 0; dr < N_DRIVE; dr++) { @@ -4234,13 +4239,6 @@ static int __init floppy_init(void) } use_virtual_dma = can_use_virtual_dma & 1; -#if defined(CONFIG_PPC_MERGE) - if (check_legacy_ioport(FDC1)) { - del_timer(&fd_timeout); - err = -ENODEV; - goto out_unreg_region; - } -#endif fdc_state[0].address = FDC1; if (fdc_state[0].address == -1) { del_timer(&fd_timeout); diff --git a/trunk/drivers/char/drm/radeon_state.c b/trunk/drivers/char/drm/radeon_state.c index 5bb2234a9094..39a7f685e3fd 100644 --- a/trunk/drivers/char/drm/radeon_state.c +++ b/trunk/drivers/char/drm/radeon_state.c @@ -175,6 +175,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * } break; + case R200_EMIT_VAP_CTL:{ + RING_LOCALS; + BEGIN_RING(2); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + ADVANCE_RING(); + } + break; + case RADEON_EMIT_RB3D_COLORPITCH: case RADEON_EMIT_RE_LINE_PATTERN: case RADEON_EMIT_SE_LINE_WIDTH: @@ -202,7 +210,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: case R200_EMIT_TFACTOR_0: case R200_EMIT_VTX_FMT_0: - case R200_EMIT_VAP_CTL: case R200_EMIT_MATRIX_SELECT_0: case R200_EMIT_TEX_PROC_CTL_2: case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 0aa5d608fe6f..843d34c8627c 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -3428,6 +3428,7 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC); if (rv) { + rv->user = NULL; rv->done = free_recv_msg; atomic_inc(&recv_msg_inuse_count); } diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c index b2dbbdb1bf81..2f07b085536b 100644 --- a/trunk/drivers/char/synclink_gt.c +++ b/trunk/drivers/char/synclink_gt.c @@ -391,8 +391,8 @@ static MGSL_PARAMS default_params = { #define DESC_LIST_SIZE 4096 #define MASK_PARITY BIT1 -#define MASK_FRAMING BIT2 -#define MASK_BREAK BIT3 +#define MASK_FRAMING BIT0 +#define MASK_BREAK BIT14 #define MASK_OVERRUN BIT4 #define GSR 0x00 /* global status */ @@ -1800,17 +1800,17 @@ static void rx_async(struct slgt_info *info) stat = 0; - if ((status = *(p+1) & (BIT9 + BIT8))) { - if (status & BIT9) + if ((status = *(p+1) & (BIT1 + BIT0))) { + if (status & BIT1) icount->parity++; - else if (status & BIT8) + else if (status & BIT0) icount->frame++; /* discard char if tty control flags say so */ if (status & info->ignore_status_mask) continue; - if (status & BIT9) + if (status & BIT1) stat = TTY_PARITY; - else if (status & BIT8) + else if (status & BIT0) stat = TTY_FRAME; } if (tty) { diff --git a/trunk/drivers/char/watchdog/sbc8360.c b/trunk/drivers/char/watchdog/sbc8360.c index 1035be5b5019..41fc6f80c493 100644 --- a/trunk/drivers/char/watchdog/sbc8360.c +++ b/trunk/drivers/char/watchdog/sbc8360.c @@ -200,7 +200,7 @@ static int wd_margin = 0xB; static int wd_multiplier = 2; static int nowayout = WATCHDOG_NOWAYOUT; -module_param(timeout, int, 27); +module_param(timeout, int, 0); MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, @@ -407,7 +407,7 @@ module_exit(sbc8360_exit); MODULE_AUTHOR("Ian E. Morgan "); MODULE_DESCRIPTION("SBC8360 watchdog driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0"); +MODULE_VERSION("1.01"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of sbc8360.c */ diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c index e125032bb403..d8a0d87df734 100644 --- a/trunk/drivers/ide/pci/sgiioc4.c +++ b/trunk/drivers/ide/pci/sgiioc4.c @@ -367,12 +367,13 @@ sgiioc4_INB(unsigned long port) static void __devinit ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) { + void __iomem *virt_dma_base; int num_ports = sizeof (ioc4_dma_regs_t); printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, dma_base, dma_base + num_ports - 1); - if (!request_region(dma_base, num_ports, hwif->name)) { + if (!request_mem_region(dma_base, num_ports, hwif->name)) { printk(KERN_ERR "%s(%s) -- ERROR, Addresses 0x%p to 0x%p " "ALREADY in use\n", @@ -381,13 +382,21 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) goto dma_alloc_failure; } - hwif->dma_base = dma_base; + virt_dma_base = ioremap(dma_base, num_ports); + if (virt_dma_base == NULL) { + printk(KERN_ERR + "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n", + __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1); + goto dma_remap_failure; + } + hwif->dma_base = (unsigned long) virt_dma_base; + hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, &hwif->dmatable_dma); if (!hwif->dmatable_cpu) - goto dma_alloc_failure; + goto dma_pci_alloc_failure; hwif->sg_max_nents = IOC4_PRD_ENTRIES; @@ -411,6 +420,12 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) printk(KERN_INFO "Changing from DMA to PIO mode for Drive %s\n", hwif->name); +dma_pci_alloc_failure: + iounmap(virt_dma_base); + +dma_remap_failure: + release_mem_region(dma_base, num_ports); + dma_alloc_failure: /* Disable DMA because we couldnot allocate any DMA maps */ hwif->autodma = 0; @@ -607,18 +622,15 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; hwif->ide_dma_timeout = &__ide_dma_timeout; - /* - * The IOC4 uses MMIO rather than Port IO. - * It also needs special workarounds for INB. - */ - default_hwif_mmiops(hwif); hwif->INB = &sgiioc4_INB; } static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) { - unsigned long base, ctl, dma_base, irqport; + unsigned long cmd_base, dma_base, irqport; + unsigned long bar0, cmd_phys_base, ctl; + void __iomem *virt_base; ide_hwif_t *hwif; int h; @@ -636,23 +648,32 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) } /* Get the CmdBlk and CtrlBlk Base Registers */ - base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET; - ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET; - irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET; + bar0 = pci_resource_start(dev, 0); + virt_base = ioremap(bar0, pci_resource_len(dev, 0)); + if (virt_base == NULL) { + printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", + d->name, bar0); + return -ENOMEM; + } + cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; + ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; + irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; - if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) { + cmd_phys_base = bar0 + IOC4_CMD_OFFSET; + if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, + hwif->name)) { printk(KERN_ERR - "%s : %s -- ERROR, Port Addresses " + "%s : %s -- ERROR, Addresses " "0x%p to 0x%p ALREADY in use\n", - __FUNCTION__, hwif->name, (void *) base, - (void *) base + IOC4_CMD_CTL_BLK_SIZE); + __FUNCTION__, hwif->name, (void *) cmd_phys_base, + (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); return -ENOMEM; } - if (hwif->io_ports[IDE_DATA_OFFSET] != base) { + if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) { /* Initialize the IO registers */ - sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport); + sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof (hwif->io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; @@ -665,6 +686,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) hwif->cds = (struct ide_pci_device_s *) d; hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */ + /* The IOC4 uses MMIO rather than Port IO. */ + default_hwif_mmiops(hwif); + /* Initializing chipset IRQ Registers */ hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4); diff --git a/trunk/drivers/ide/pci/via82cxxx.c b/trunk/drivers/ide/pci/via82cxxx.c index afdaee3c15c9..9b7589e8e93e 100644 --- a/trunk/drivers/ide/pci/via82cxxx.c +++ b/trunk/drivers/ide/pci/via82cxxx.c @@ -6,7 +6,7 @@ * * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235, vt8237 + * vt8235, vt8237, vt8237a * * Copyright (c) 2000-2002 Vojtech Pavlik * @@ -81,6 +81,7 @@ static struct via_isa_bridge { { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c b/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c index 25157f57a6d0..f930e55b58fc 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c @@ -41,9 +41,11 @@ /* Trivial bitmap-based allocator */ u32 mthca_alloc(struct mthca_alloc *alloc) { + unsigned long flags; u32 obj; - spin_lock(&alloc->lock); + spin_lock_irqsave(&alloc->lock, flags); + obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last); if (obj >= alloc->max) { alloc->top = (alloc->top + alloc->max) & alloc->mask; @@ -56,19 +58,24 @@ u32 mthca_alloc(struct mthca_alloc *alloc) } else obj = -1; - spin_unlock(&alloc->lock); + spin_unlock_irqrestore(&alloc->lock, flags); return obj; } void mthca_free(struct mthca_alloc *alloc, u32 obj) { + unsigned long flags; + obj &= alloc->max - 1; - spin_lock(&alloc->lock); + + spin_lock_irqsave(&alloc->lock, flags); + clear_bit(obj, alloc->table); alloc->last = min(alloc->last, obj); alloc->top = (alloc->top + alloc->max) & alloc->mask; - spin_unlock(&alloc->lock); + + spin_unlock_irqrestore(&alloc->lock, flags); } int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask, diff --git a/trunk/drivers/macintosh/via-pmu-backlight.c b/trunk/drivers/macintosh/via-pmu-backlight.c index d3f8d75bcbb4..a82f313d9dc9 100644 --- a/trunk/drivers/macintosh/via-pmu-backlight.c +++ b/trunk/drivers/macintosh/via-pmu-backlight.c @@ -18,17 +18,48 @@ static struct backlight_properties pmu_backlight_data; static spinlock_t pmu_backlight_lock; static int sleeping; +static u8 bl_curve[FB_BACKLIGHT_LEVELS]; -static int pmu_backlight_get_level_brightness(struct fb_info *info, - int level) +static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) +{ + unsigned int i, flat, count, range = (max - min); + + bl_curve[0] = off; + + for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) + bl_curve[flat] = min; + + count = FB_BACKLIGHT_LEVELS * 15 / 16; + for (i = 0; i < count; ++i) + bl_curve[flat + i] = min + (range * (i + 1) / count); +} + +static int pmu_backlight_curve_lookup(int value) +{ + int level = (FB_BACKLIGHT_LEVELS - 1); + int i, max = 0; + + /* Look for biggest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) + max = max((int)bl_curve[i], max); + + /* Look for nearest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { + int diff = abs(bl_curve[i] - value); + if (diff < max) { + max = diff; + level = i; + } + } + return level; +} + +static int pmu_backlight_get_level_brightness(int level) { int pmulevel; /* Get and convert the value */ - mutex_lock(&info->bl_mutex); - pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; - mutex_unlock(&info->bl_mutex); - + pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; if (pmulevel < 0) pmulevel = 0; else if (pmulevel > MAX_PMU_LEVEL) @@ -39,7 +70,6 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info, static int pmu_backlight_update_status(struct backlight_device *bd) { - struct fb_info *info = class_get_devdata(&bd->class_dev); struct adb_request req; unsigned long flags; int level = bd->props->brightness; @@ -55,7 +85,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd) level = 0; if (level > 0) { - int pmulevel = pmu_backlight_get_level_brightness(info, level); + int pmulevel = pmu_backlight_get_level_brightness(level); pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); pmu_wait_complete(&req); @@ -88,35 +118,19 @@ static struct backlight_properties pmu_backlight_data = { }; #ifdef CONFIG_PM -static int pmu_backlight_sleep_call(struct pmu_sleep_notifier *self, int when) +void pmu_backlight_set_sleep(int sleep) { unsigned long flags; spin_lock_irqsave(&pmu_backlight_lock, flags); - - switch (when) { - case PBOOK_SLEEP_REQUEST: - sleeping = 1; - break; - case PBOOK_WAKE: - sleeping = 0; - break; - } - + sleeping = sleep; spin_unlock_irqrestore(&pmu_backlight_lock, flags); - - return PBOOK_SLEEP_OK; } - -static struct pmu_sleep_notifier pmu_backlight_sleep_notif = { - .notifier_call = pmu_backlight_sleep_call, -}; -#endif +#endif /* CONFIG_PM */ void __init pmu_backlight_init() { struct backlight_device *bd; - struct fb_info *info; char name[10]; int level, autosave; @@ -131,27 +145,14 @@ void __init pmu_backlight_init() !machine_is_compatible("PowerBook1,1")) return; - /* Actually, this is a hack, but I don't know of a better way - * to get the first framebuffer device. - */ - info = registered_fb[0]; - if (!info) { - printk("pmubl: No framebuffer found\n"); - goto error; - } - - snprintf(name, sizeof(name), "pmubl%d", info->node); + snprintf(name, sizeof(name), "pmubl"); - bd = backlight_device_register(name, info, &pmu_backlight_data); + bd = backlight_device_register(name, NULL, &pmu_backlight_data); if (IS_ERR(bd)) { printk("pmubl: Backlight registration failed\n"); goto error; } - - mutex_lock(&info->bl_mutex); - info->bl_dev = bd; - fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); - mutex_unlock(&info->bl_mutex); + pmu_backlight_init_curve(0x7F, 0x46, 0x0E); level = pmu_backlight_data.max_brightness; @@ -161,28 +162,22 @@ void __init pmu_backlight_init() pmu_request(&req, NULL, 2, 0xd9, 0); pmu_wait_complete(&req); - mutex_lock(&info->bl_mutex); - level = pmac_backlight_curve_lookup(info, + level = pmu_backlight_curve_lookup( (req.reply[0] >> 4) * pmu_backlight_data.max_brightness / 15); - mutex_unlock(&info->bl_mutex); } - up(&bd->sem); + down(&bd->sem); bd->props->brightness = level; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); mutex_lock(&pmac_backlight_mutex); if (!pmac_backlight) pmac_backlight = bd; mutex_unlock(&pmac_backlight_mutex); -#ifdef CONFIG_PM - pmu_register_sleep_notifier(&pmu_backlight_sleep_notif); -#endif - printk("pmubl: Backlight initialized (%s)\n", name); return; diff --git a/trunk/drivers/macintosh/via-pmu.c b/trunk/drivers/macintosh/via-pmu.c index ea386801e215..14610a63f580 100644 --- a/trunk/drivers/macintosh/via-pmu.c +++ b/trunk/drivers/macintosh/via-pmu.c @@ -1995,6 +1995,8 @@ restore_via_state(void) out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } +extern void pmu_backlight_set_sleep(int sleep); + static int pmac_suspend_devices(void) { @@ -2032,6 +2034,11 @@ pmac_suspend_devices(void) return -EBUSY; } +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code not to muck around with the chip anymore */ + pmu_backlight_set_sleep(1); +#endif + /* Call platform functions marked "on sleep" */ pmac_pfunc_i2c_suspend(); pmac_pfunc_base_suspend(); @@ -2090,6 +2097,11 @@ pmac_wakeup_devices(void) { mdelay(100); +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code it can use the chip again */ + pmu_backlight_set_sleep(0); +#endif + /* Power back up system devices (including the PIC) */ device_power_up(); diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 87bfe9e7d8ca..3b4d69c05623 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -930,10 +930,13 @@ static void status(struct seq_file *seq, mddev_t *mddev) seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); - for (i = 0; i < conf->raid_disks; i++) + rcu_read_lock(); + for (i = 0; i < conf->raid_disks; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); seq_printf(seq, "%s", - conf->mirrors[i].rdev && - test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); + rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_"); + } + rcu_read_unlock(); seq_printf(seq, "]"); } @@ -975,7 +978,6 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) static void print_conf(conf_t *conf) { int i; - mirror_info_t *tmp; printk("RAID1 conf printout:\n"); if (!conf) { @@ -985,14 +987,17 @@ static void print_conf(conf_t *conf) printk(" --- wd:%d rd:%d\n", conf->working_disks, conf->raid_disks); + rcu_read_lock(); for (i = 0; i < conf->raid_disks; i++) { char b[BDEVNAME_SIZE]; - tmp = conf->mirrors + i; - if (tmp->rdev) + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); + if (rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags), - bdevname(tmp->rdev->bdev,b)); + i, !test_bit(In_sync, &rdev->flags), + !test_bit(Faulty, &rdev->flags), + bdevname(rdev->bdev,b)); } + rcu_read_unlock(); } static void close_sync(conf_t *conf) @@ -1008,20 +1013,20 @@ static int raid1_spare_active(mddev_t *mddev) { int i; conf_t *conf = mddev->private; - mirror_info_t *tmp; /* * Find all failed disks within the RAID1 configuration - * and mark them readable + * and mark them readable. + * Called under mddev lock, so rcu protection not needed. */ for (i = 0; i < conf->raid_disks; i++) { - tmp = conf->mirrors + i; - if (tmp->rdev - && !test_bit(Faulty, &tmp->rdev->flags) - && !test_bit(In_sync, &tmp->rdev->flags)) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev + && !test_bit(Faulty, &rdev->flags) + && !test_bit(In_sync, &rdev->flags)) { conf->working_disks++; mddev->degraded--; - set_bit(In_sync, &tmp->rdev->flags); + set_bit(In_sync, &rdev->flags); } } @@ -1237,7 +1242,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) /* ouch - failed to read all of that. * Try some synchronous reads of other devices to get * good data, much like with normal read errors. Only - * read into the pages we already have so they we don't + * read into the pages we already have so we don't * need to re-issue the read request. * We don't need to freeze the array, because being in an * active sync request, there is no normal IO, and @@ -1257,6 +1262,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) s = PAGE_SIZE >> 9; do { if (r1_bio->bios[d]->bi_end_io == end_sync_read) { + /* No rcu protection needed here devices + * can only be removed when no resync is + * active, and resync is currently active + */ rdev = conf->mirrors[d].rdev; if (sync_page_io(rdev->bdev, sect + rdev->data_offset, @@ -1463,6 +1472,11 @@ static void raid1d(mddev_t *mddev) s = PAGE_SIZE >> 9; do { + /* Note: no rcu protection needed here + * as this is synchronous in the raid1d thread + * which is the thread that might remove + * a device. If raid1d ever becomes multi-threaded.... + */ rdev = conf->mirrors[d].rdev; if (rdev && test_bit(In_sync, &rdev->flags) && @@ -1486,7 +1500,6 @@ static void raid1d(mddev_t *mddev) d = conf->raid_disks; d--; rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); if (rdev && test_bit(In_sync, &rdev->flags)) { if (sync_page_io(rdev->bdev, @@ -1509,9 +1522,11 @@ static void raid1d(mddev_t *mddev) s<<9, conf->tmppage, READ) == 0) /* Well, this device is dead */ md_error(mddev, rdev); - else + else { + atomic_add(s, &rdev->corrected_errors); printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n", mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b)); + } } } } else { @@ -1787,19 +1802,17 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0; iraid_disks; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io == end_sync_read) { - md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors); + md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } } } else { atomic_set(&r1_bio->remaining, 1); bio = r1_bio->bios[r1_bio->read_disk]; - md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev, - nr_sectors); + md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } - return nr_sectors; } diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 91ef5f2fd768..ce850f1078b5 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -173,8 +173,11 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); static int debug = 3; +static int eeprom_bad_csum_allow = 0; module_param(debug, int, 0); +module_param(eeprom_bad_csum_allow, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); +MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); #define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ @@ -756,7 +759,8 @@ static int e100_eeprom_load(struct nic *nic) checksum = le16_to_cpu(0xBABA - checksum); if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - return -EAGAIN; + if (!eeprom_bad_csum_allow) + return -EAGAIN; } return 0; diff --git a/trunk/drivers/net/sunlance.c b/trunk/drivers/net/sunlance.c index 0e3fdf7c6dd3..ec0413609f36 100644 --- a/trunk/drivers/net/sunlance.c +++ b/trunk/drivers/net/sunlance.c @@ -1566,20 +1566,21 @@ static int __exit sunlance_sun4_remove(void) static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) { struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; int err; - if (!strcmp(dp->name, "le")) { - err = sparc_lance_probe_one(sdev, NULL, NULL); - } else if (!strcmp(dp->name, "ledma")) { - struct sbus_dma *ledma = find_ledma(sdev); + if (sdev->parent) { + struct of_device *parent = &sdev->parent->ofdev; - err = sparc_lance_probe_one(sdev->child, ledma, NULL); - } else { - BUG_ON(strcmp(dp->name, "lebuffer")); + if (!strcmp(parent->node->name, "ledma")) { + struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev)); - err = sparc_lance_probe_one(sdev->child, NULL, sdev); - } + err = sparc_lance_probe_one(sdev, ledma, NULL); + } else if (!strcmp(parent->node->name, "lebuffer")) { + err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev)); + } else + err = sparc_lance_probe_one(sdev, NULL, NULL); + } else + err = sparc_lance_probe_one(sdev, NULL, NULL); return err; } @@ -1604,12 +1605,6 @@ static struct of_device_id sunlance_sbus_match[] = { { .name = "le", }, - { - .name = "ledma", - }, - { - .name = "lebuffer", - }, {}, }; diff --git a/trunk/drivers/net/wireless/strip.c b/trunk/drivers/net/wireless/strip.c index fd31885c6844..ccaf28e8db0a 100644 --- a/trunk/drivers/net/wireless/strip.c +++ b/trunk/drivers/net/wireless/strip.c @@ -467,6 +467,7 @@ static int arp_query(unsigned char *haddr, u32 paddr, struct net_device *dev) { struct neighbour *neighbor_entry; + int ret = 0; neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); @@ -474,10 +475,11 @@ static int arp_query(unsigned char *haddr, u32 paddr, neighbor_entry->used = jiffies; if (neighbor_entry->nud_state & NUD_VALID) { memcpy(haddr, neighbor_entry->ha, dev->addr_len); - return 1; + ret = 1; } + neigh_release(neighbor_entry); } - return 0; + return ret; } static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr, diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index b4970387a16f..def78a2a7c15 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -667,6 +667,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_vi DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index d8e9b95f0a1a..25c1ef6dfd44 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -52,7 +52,7 @@ static void dasd_setup_queue(struct dasd_device * device); static void dasd_free_queue(struct dasd_device * device); static void dasd_flush_request_queue(struct dasd_device *); static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); -static void dasd_flush_ccw_queue(struct dasd_device *, int); +static int dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(void *data); @@ -60,6 +60,7 @@ static void do_kick_device(void *data); * SECTION: Operations on the device structure. */ static wait_queue_head_t dasd_init_waitq; +static wait_queue_head_t dasd_flush_wq; /* * Allocate memory for a new device structure. @@ -121,7 +122,7 @@ dasd_free_device(struct dasd_device *device) /* * Make a new device known to the system. */ -static inline int +static int dasd_state_new_to_known(struct dasd_device *device) { int rc; @@ -145,7 +146,7 @@ dasd_state_new_to_known(struct dasd_device *device) /* * Let the system forget about a device. */ -static inline void +static int dasd_state_known_to_new(struct dasd_device * device) { /* Disable extended error reporting for this device. */ @@ -163,12 +164,13 @@ dasd_state_known_to_new(struct dasd_device * device) /* Give up reference we took in dasd_state_new_to_known. */ dasd_put_device(device); + return 0; } /* * Request the irq line for the device. */ -static inline int +static int dasd_state_known_to_basic(struct dasd_device * device) { int rc; @@ -192,17 +194,23 @@ dasd_state_known_to_basic(struct dasd_device * device) /* * Release the irq line for the device. Terminate any running i/o. */ -static inline void +static int dasd_state_basic_to_known(struct dasd_device * device) { + int rc; + dasd_gendisk_free(device); - dasd_flush_ccw_queue(device, 1); + rc = dasd_flush_ccw_queue(device, 1); + if (rc) + return rc; + DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); if (device->debug_area != NULL) { debug_unregister(device->debug_area); device->debug_area = NULL; } device->state = DASD_STATE_KNOWN; + return 0; } /* @@ -219,7 +227,7 @@ dasd_state_basic_to_known(struct dasd_device * device) * In case the analysis returns an error, the device setup is stopped * (a fake disk was already added to allow formatting). */ -static inline int +static int dasd_state_basic_to_ready(struct dasd_device * device) { int rc; @@ -247,25 +255,31 @@ dasd_state_basic_to_ready(struct dasd_device * device) * Forget format information. Check if the target level is basic * and if it is create fake disk for formatting. */ -static inline void +static int dasd_state_ready_to_basic(struct dasd_device * device) { - dasd_flush_ccw_queue(device, 0); + int rc; + + rc = dasd_flush_ccw_queue(device, 0); + if (rc) + return rc; dasd_destroy_partitions(device); dasd_flush_request_queue(device); device->blocks = 0; device->bp_block = 0; device->s2b_shift = 0; device->state = DASD_STATE_BASIC; + return 0; } /* * Back to basic. */ -static inline void +static int dasd_state_unfmt_to_basic(struct dasd_device * device) { device->state = DASD_STATE_BASIC; + return 0; } /* @@ -273,7 +287,7 @@ dasd_state_unfmt_to_basic(struct dasd_device * device) * the requeueing of requests from the linux request queue to the * ccw queue. */ -static inline int +static int dasd_state_ready_to_online(struct dasd_device * device) { device->state = DASD_STATE_ONLINE; @@ -284,16 +298,17 @@ dasd_state_ready_to_online(struct dasd_device * device) /* * Stop the requeueing of requests again. */ -static inline void +static int dasd_state_online_to_ready(struct dasd_device * device) { device->state = DASD_STATE_READY; + return 0; } /* * Device startup state changes. */ -static inline int +static int dasd_increase_state(struct dasd_device *device) { int rc; @@ -329,30 +344,37 @@ dasd_increase_state(struct dasd_device *device) /* * Device shutdown state changes. */ -static inline int +static int dasd_decrease_state(struct dasd_device *device) { + int rc; + + rc = 0; if (device->state == DASD_STATE_ONLINE && device->target <= DASD_STATE_READY) - dasd_state_online_to_ready(device); + rc = dasd_state_online_to_ready(device); - if (device->state == DASD_STATE_READY && + if (!rc && + device->state == DASD_STATE_READY && device->target <= DASD_STATE_BASIC) - dasd_state_ready_to_basic(device); + rc = dasd_state_ready_to_basic(device); - if (device->state == DASD_STATE_UNFMT && + if (!rc && + device->state == DASD_STATE_UNFMT && device->target <= DASD_STATE_BASIC) - dasd_state_unfmt_to_basic(device); + rc = dasd_state_unfmt_to_basic(device); - if (device->state == DASD_STATE_BASIC && + if (!rc && + device->state == DASD_STATE_BASIC && device->target <= DASD_STATE_KNOWN) - dasd_state_basic_to_known(device); + rc = dasd_state_basic_to_known(device); - if (device->state == DASD_STATE_KNOWN && + if (!rc && + device->state == DASD_STATE_KNOWN && device->target <= DASD_STATE_NEW) - dasd_state_known_to_new(device); + rc = dasd_state_known_to_new(device); - return 0; + return rc; } /* @@ -701,6 +723,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr) cqr->retries--; cqr->status = DASD_CQR_CLEAR; cqr->stopclk = get_clock(); + cqr->starttime = 0; DBF_DEV_EVENT(DBF_DEBUG, device, "terminate cqr %p successful", cqr); @@ -978,6 +1001,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) { cqr->status = DASD_CQR_QUEUED; dasd_clear_timer(device); + wake_up(&dasd_flush_wq); dasd_schedule_bh(device); return; } @@ -1241,6 +1265,10 @@ __dasd_check_expire(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) { if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) { + DEV_MESSAGE(KERN_ERR, device, + "internal error - timeout (%is) expired " + "for cqr %p (%i retries left)", + (cqr->expires/HZ), cqr, cqr->retries); if (device->discipline->term_IO(cqr) != 0) /* Hmpf, try again in 1/10 sec */ dasd_set_timer(device, 10); @@ -1285,46 +1313,100 @@ __dasd_start_head(struct dasd_device * device) dasd_set_timer(device, 50); } +static inline int +_wait_for_clear(struct dasd_ccw_req *cqr) +{ + return (cqr->status == DASD_CQR_QUEUED); +} + /* - * Remove requests from the ccw queue. + * Remove all requests from the ccw queue (all = '1') or only block device + * requests in case all = '0'. + * Take care of the erp-chain (chained via cqr->refers) and remove either + * the whole erp-chain or none of the erp-requests. + * If a request is currently running, term_IO is called and the request + * is re-queued. Prior to removing the terminated request we need to wait + * for the clear-interrupt. + * In case termination is not possible we stop processing and just finishing + * the already moved requests. */ -static void +static int dasd_flush_ccw_queue(struct dasd_device * device, int all) { + struct dasd_ccw_req *cqr, *orig, *n; + int rc, i; + struct list_head flush_queue; - struct list_head *l, *n; - struct dasd_ccw_req *cqr; INIT_LIST_HEAD(&flush_queue); spin_lock_irq(get_ccwdev_lock(device->cdev)); - list_for_each_safe(l, n, &device->ccw_queue) { - cqr = list_entry(l, struct dasd_ccw_req, list); + rc = 0; +restart: + list_for_each_entry_safe(cqr, n, &device->ccw_queue, list) { + /* get original request of erp request-chain */ + for (orig = cqr; orig->refers != NULL; orig = orig->refers); + /* Flush all request or only block device requests? */ - if (all == 0 && cqr->callback == dasd_end_request_cb) + if (all == 0 && cqr->callback != dasd_end_request_cb && + orig->callback != dasd_end_request_cb) { continue; - if (cqr->status == DASD_CQR_IN_IO) - device->discipline->term_IO(cqr); - if (cqr->status != DASD_CQR_DONE || - cqr->status != DASD_CQR_FAILED) { - cqr->status = DASD_CQR_FAILED; + } + /* Check status and move request to flush_queue */ + switch (cqr->status) { + case DASD_CQR_IN_IO: + rc = device->discipline->term_IO(cqr); + if (rc) { + /* unable to terminate requeust */ + DEV_MESSAGE(KERN_ERR, device, + "dasd flush ccw_queue is unable " + " to terminate request %p", + cqr); + /* stop flush processing */ + goto finished; + } + break; + case DASD_CQR_QUEUED: + case DASD_CQR_ERROR: + /* set request to FAILED */ cqr->stopclk = get_clock(); + cqr->status = DASD_CQR_FAILED; + break; + default: /* do not touch the others */ + break; + } + /* Rechain request (including erp chain) */ + for (i = 0; cqr != NULL; cqr = cqr->refers, i++) { + cqr->endclk = get_clock(); + list_move_tail(&cqr->list, &flush_queue); + } + if (i > 1) + /* moved more than one request - need to restart */ + goto restart; + } + +finished: + spin_unlock_irq(get_ccwdev_lock(device->cdev)); + /* Now call the callback function of flushed requests */ +restart_cb: + list_for_each_entry_safe(cqr, n, &flush_queue, list) { + if (cqr->status == DASD_CQR_CLEAR) { + /* wait for clear interrupt! */ + wait_event(dasd_flush_wq, _wait_for_clear(cqr)); + cqr->status = DASD_CQR_FAILED; } /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); - continue; + /* restart list_for_xx loop since dasd_process_erp + * might remove multiple elements */ + goto restart_cb; } - /* Rechain request on device request queue */ + /* call the callback function */ cqr->endclk = get_clock(); - list_move_tail(&cqr->list, &flush_queue); - } - spin_unlock_irq(get_ccwdev_lock(device->cdev)); - /* Now call the callback function of flushed requests */ - list_for_each_safe(l, n, &flush_queue) { - cqr = list_entry(l, struct dasd_ccw_req, list); if (cqr->callback != NULL) (cqr->callback)(cqr, cqr->callback_data); } + return rc; } /* @@ -1510,10 +1592,8 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr) if (device->discipline->term_IO) { cqr->retries = -1; device->discipline->term_IO(cqr); - /*nished = - * wait (non-interruptible) for final status - * because signal ist still pending - */ + /* wait (non-interruptible) for final status + * because signal ist still pending */ spin_unlock_irq(get_ccwdev_lock(device->cdev)); wait_event(wait_q, _wait_for_wakeup(cqr)); spin_lock_irq(get_ccwdev_lock(device->cdev)); @@ -1546,19 +1626,11 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device) { struct dasd_ccw_req *cqr; - int rc; if (list_empty(&device->ccw_queue)) return 0; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); - rc = device->discipline->term_IO(cqr); - if (rc == 0) { - /* termination successful */ - cqr->status = DASD_CQR_QUEUED; - cqr->startclk = cqr->stopclk = 0; - cqr->starttime = 0; - } - return rc; + return device->discipline->term_IO(cqr); } int @@ -1726,10 +1798,7 @@ dasd_flush_request_queue(struct dasd_device * device) return; spin_lock_irq(&device->request_queue_lock); - while (!list_empty(&device->request_queue->queue_head)) { - req = elv_next_request(device->request_queue); - if (req == NULL) - break; + while ((req = elv_next_request(device->request_queue))) { blkdev_dequeue_request(req); dasd_end_request(req, 0); } @@ -2091,6 +2160,7 @@ dasd_init(void) int rc; init_waitqueue_head(&dasd_init_waitq); + init_waitqueue_head(&dasd_flush_wq); /* register 'common' DASD debug area, used for all DBF_XXX calls */ dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long)); diff --git a/trunk/drivers/s390/block/dasd_genhd.c b/trunk/drivers/s390/block/dasd_genhd.c index 4c272b70f41a..d163632101d2 100644 --- a/trunk/drivers/s390/block/dasd_genhd.c +++ b/trunk/drivers/s390/block/dasd_genhd.c @@ -83,10 +83,12 @@ dasd_gendisk_alloc(struct dasd_device *device) void dasd_gendisk_free(struct dasd_device *device) { - del_gendisk(device->gdp); - device->gdp->queue = NULL; - put_disk(device->gdp); - device->gdp = NULL; + if (device->gdp) { + del_gendisk(device->gdp); + device->gdp->queue = NULL; + put_disk(device->gdp); + device->gdp = NULL; + } } /* diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index 3cba6c9fab11..38954f5cd14c 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -183,11 +183,9 @@ ccwgroup_create(struct device *root, gdev->creator_id = creator_id; gdev->count = argc; - gdev->dev = (struct device ) { - .bus = &ccwgroup_bus_type, - .parent = root, - .release = ccwgroup_release, - }; + gdev->dev.bus = &ccwgroup_bus_type; + gdev->dev.parent = root; + gdev->dev.release = ccwgroup_release; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", gdev->cdev[0]->dev.bus_id); @@ -391,10 +389,8 @@ int ccwgroup_driver_register (struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ - cdriver->driver = (struct device_driver) { - .bus = &ccwgroup_bus_type, - .name = cdriver->name, - }; + cdriver->driver.bus = &ccwgroup_bus_type; + cdriver->driver.name = cdriver->name; return driver_register(&cdriver->driver); } diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 61ce3f1d5228..c28444af0919 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -238,8 +238,6 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) /* Check for single path devices. */ if (sch->schib.pmcw.pim == 0x80) goto out_unreg; - if (sch->vpm == mask) - goto out_unreg; if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && @@ -258,6 +256,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) /* trigger path verification. */ if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); + else if (sch->vpm == mask) + goto out_unreg; out_unlock: spin_unlock_irq(&sch->lock); return 0; @@ -1391,10 +1391,8 @@ new_channel_path(int chpid) /* fill in status, etc. */ chp->id = chpid; chp->state = 1; - chp->dev = (struct device) { - .parent = &css[0]->device, - .release = chp_release, - }; + chp->dev.parent = &css[0]->device; + chp->dev.release = chp_release; snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); /* Obtain channel path description and fill it in. */ diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index 585fa04233c3..646da5640401 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -556,12 +556,11 @@ get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid, struct ccw_device *sibling) { struct device *dev; - struct match_data data = { - .devno = devno, - .ssid = ssid, - .sibling = sibling, - }; + struct match_data data; + data.devno = devno; + data.ssid = ssid; + data.sibling = sibling; dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno); return dev ? to_ccwdev(dev) : NULL; @@ -835,10 +834,8 @@ io_subchannel_probe (struct subchannel *sch) return -ENOMEM; } atomic_set(&cdev->private->onoff, 0); - cdev->dev = (struct device) { - .parent = &sch->dev, - .release = ccw_device_release, - }; + cdev->dev.parent = &sch->dev; + cdev->dev.release = ccw_device_release; INIT_LIST_HEAD(&cdev->private->kick_work.entry); /* Do first half of device_register. */ device_initialize(&cdev->dev); @@ -977,9 +974,7 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) int rc; /* Initialize the ccw_device structure. */ - cdev->dev = (struct device) { - .parent = &sch->dev, - }; + cdev->dev.parent= &sch->dev; rc = io_subchannel_recog(cdev, sch); if (rc) return rc; diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index 6d91c2eb205b..35e162ba6d54 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -267,12 +267,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) notify = 1; } /* fill out sense information */ - cdev->id = (struct ccw_device_id) { - .cu_type = cdev->private->senseid.cu_type, - .cu_model = cdev->private->senseid.cu_model, - .dev_type = cdev->private->senseid.dev_type, - .dev_model = cdev->private->senseid.dev_model, - }; + cdev->id.cu_type = cdev->private->senseid.cu_type; + cdev->id.cu_model = cdev->private->senseid.cu_model; + cdev->id.dev_type = cdev->private->senseid.dev_type; + cdev->id.dev_model = cdev->private->senseid.dev_model; if (notify) { cdev->private->state = DEV_STATE_OFFLINE; if (same_dev) { @@ -566,12 +564,10 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) /* Deliver fake irb to device driver, if needed. */ if (cdev->private->flags.fake_irb) { memset(&cdev->private->irb, 0, sizeof(struct irb)); - cdev->private->irb.scsw = (struct scsw) { - .cc = 1, - .fctl = SCSW_FCTL_START_FUNC, - .actl = SCSW_ACTL_START_PEND, - .stctl = SCSW_STCTL_STATUS_PEND, - }; + cdev->private->irb.scsw.cc = 1; + cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC; + cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND; + cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND; cdev->private->flags.fake_irb = 0; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, diff --git a/trunk/drivers/s390/cio/device_pgid.c b/trunk/drivers/s390/cio/device_pgid.c index 32610fd8868e..1693a102dcfe 100644 --- a/trunk/drivers/s390/cio/device_pgid.c +++ b/trunk/drivers/s390/cio/device_pgid.c @@ -23,6 +23,21 @@ #include "device.h" #include "ioasm.h" +/* + * Helper function called from interrupt context to decide whether an + * operation should be tried again. + */ +static int __ccw_device_should_retry(struct scsw *scsw) +{ + /* CC is only valid if start function bit is set. */ + if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1) + return 1; + /* No more activity. For sense and set PGID we stubbornly try again. */ + if (!scsw->actl) + return 1; + return 0; +} + /* * Start Sense Path Group ID helper function. Used in ccw_device_recog * and ccw_device_sense_pgid. @@ -155,10 +170,10 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - /* Retry sense pgid for cc=1. */ + if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (irb->scsw.cc == 1) { + if (__ccw_device_should_retry(&irb->scsw)) { ret = __ccw_device_sense_pgid_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_pgid_done(cdev, ret); @@ -391,10 +406,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - /* Retry set pgid for cc=1. */ + if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (irb->scsw.cc == 1) + if (__ccw_device_should_retry(&irb->scsw)) __ccw_device_verify_start(cdev); return; } @@ -494,10 +509,10 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - /* Retry set pgid for cc=1. */ + if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (irb->scsw.cc == 1) + if (__ccw_device_should_retry(&irb->scsw)) __ccw_device_disband_start(cdev); return; } diff --git a/trunk/drivers/serial/8250_pci.c b/trunk/drivers/serial/8250_pci.c index a1d322f8a16c..851e4839d6d9 100644 --- a/trunk/drivers/serial/8250_pci.c +++ b/trunk/drivers/serial/8250_pci.c @@ -458,11 +458,11 @@ static int pci_siig_setup(struct serial_private *priv, * growing *huge*, we use this function to collapse some 70 entries * in the PCI table into one, for sanity's and compactness's sake. */ -static unsigned short timedia_single_port[] = { +static const unsigned short timedia_single_port[] = { 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; -static unsigned short timedia_dual_port[] = { +static const unsigned short timedia_dual_port[] = { 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, @@ -470,35 +470,34 @@ static unsigned short timedia_dual_port[] = { 0xD079, 0 }; -static unsigned short timedia_quad_port[] = { +static const unsigned short timedia_quad_port[] = { 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, 0xB157, 0 }; -static unsigned short timedia_eight_port[] = { +static const unsigned short timedia_eight_port[] = { 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; static const struct timedia_struct { int num; - unsigned short *ids; + const unsigned short *ids; } timedia_data[] = { { 1, timedia_single_port }, { 2, timedia_dual_port }, { 4, timedia_quad_port }, - { 8, timedia_eight_port }, - { 0, NULL } + { 8, timedia_eight_port } }; static int pci_timedia_init(struct pci_dev *dev) { - unsigned short *ids; + const unsigned short *ids; int i, j; - for (i = 0; timedia_data[i].num; i++) { + for (i = 0; i < ARRAY_SIZE(timedia_data); i++) { ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) if (dev->subsystem_device == ids[j]) @@ -936,6 +935,7 @@ enum pci_board_num_t { pbn_b1_8_1382400, pbn_b2_1_115200, + pbn_b2_2_115200, pbn_b2_8_115200, pbn_b2_1_460800, @@ -1243,6 +1243,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, + [pbn_b2_2_115200] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, [pbn_b2_8_115200] = { .flags = FL_BASE2, .num_ports = 8, @@ -2339,6 +2345,13 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_1_115200 }, + /* + * IntaShield IS-200 + */ + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */ + pbn_b2_2_115200 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index 80ef7d482756..372e47f7d596 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -2377,6 +2377,9 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) return (port1->iobase == port2->iobase) && (port1->hub6 == port2->hub6); case UPIO_MEM: + case UPIO_MEM32: + case UPIO_AU: + case UPIO_TSI: return (port1->mapbase == port2->mapbase); } return 0; diff --git a/trunk/drivers/usb/gadget/ether.c b/trunk/drivers/usb/gadget/ether.c index 4fe1bec1c255..30299c620d97 100644 --- a/trunk/drivers/usb/gadget/ether.c +++ b/trunk/drivers/usb/gadget/ether.c @@ -117,6 +117,8 @@ struct eth_dev { struct usb_ep *in_ep, *out_ep, *status_ep; const struct usb_endpoint_descriptor *in, *out, *status; + + spinlock_t req_lock; struct list_head tx_reqs, rx_reqs; struct net_device *net; @@ -1066,21 +1068,31 @@ static void eth_reset_config (struct eth_dev *dev) */ if (dev->in) { usb_ep_disable (dev->in_ep); + spin_lock(&dev->req_lock); while (likely (!list_empty (&dev->tx_reqs))) { req = container_of (dev->tx_reqs.next, struct usb_request, list); list_del (&req->list); + + spin_unlock(&dev->req_lock); usb_ep_free_request (dev->in_ep, req); + spin_lock(&dev->req_lock); } + spin_unlock(&dev->req_lock); } if (dev->out) { usb_ep_disable (dev->out_ep); + spin_lock(&dev->req_lock); while (likely (!list_empty (&dev->rx_reqs))) { req = container_of (dev->rx_reqs.next, struct usb_request, list); list_del (&req->list); + + spin_unlock(&dev->req_lock); usb_ep_free_request (dev->out_ep, req); + spin_lock(&dev->req_lock); } + spin_unlock(&dev->req_lock); } if (dev->status) { @@ -1659,9 +1671,9 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) if (retval) { DEBUG (dev, "rx submit --> %d\n", retval); dev_kfree_skb_any (skb); - spin_lock (&dev->lock); + spin_lock(&dev->req_lock); list_add (&req->list, &dev->rx_reqs); - spin_unlock (&dev->lock); + spin_unlock(&dev->req_lock); } return retval; } @@ -1730,8 +1742,9 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) dev_kfree_skb_any (skb); if (!netif_running (dev->net)) { clean: - /* nobody reading rx_reqs, so no dev->lock */ + spin_lock(&dev->req_lock); list_add (&req->list, &dev->rx_reqs); + spin_unlock(&dev->req_lock); req = NULL; } if (req) @@ -1782,15 +1795,18 @@ static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags) { int status; + spin_lock(&dev->req_lock); status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags); if (status < 0) goto fail; status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags); if (status < 0) goto fail; - return 0; + goto done; fail: DEBUG (dev, "can't alloc requests\n"); +done: + spin_unlock(&dev->req_lock); return status; } @@ -1800,21 +1816,21 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) unsigned long flags; /* fill unused rxq slots with some skb */ - spin_lock_irqsave (&dev->lock, flags); + spin_lock_irqsave(&dev->req_lock, flags); while (!list_empty (&dev->rx_reqs)) { req = container_of (dev->rx_reqs.next, struct usb_request, list); list_del_init (&req->list); - spin_unlock_irqrestore (&dev->lock, flags); + spin_unlock_irqrestore(&dev->req_lock, flags); if (rx_submit (dev, req, gfp_flags) < 0) { defer_kevent (dev, WORK_RX_MEMORY); return; } - spin_lock_irqsave (&dev->lock, flags); + spin_lock_irqsave(&dev->req_lock, flags); } - spin_unlock_irqrestore (&dev->lock, flags); + spin_unlock_irqrestore(&dev->req_lock, flags); } static void eth_work (void *_dev) @@ -1848,9 +1864,9 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req) } dev->stats.tx_packets++; - spin_lock (&dev->lock); + spin_lock(&dev->req_lock); list_add (&req->list, &dev->tx_reqs); - spin_unlock (&dev->lock); + spin_unlock(&dev->req_lock); dev_kfree_skb_any (skb); atomic_dec (&dev->tx_qlen); @@ -1896,12 +1912,12 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ } - spin_lock_irqsave (&dev->lock, flags); + spin_lock_irqsave(&dev->req_lock, flags); req = container_of (dev->tx_reqs.next, struct usb_request, list); list_del (&req->list); if (list_empty (&dev->tx_reqs)) netif_stop_queue (net); - spin_unlock_irqrestore (&dev->lock, flags); + spin_unlock_irqrestore(&dev->req_lock, flags); /* no buffer copies needed, unless the network stack did it * or the hardware can't use skb buffers. @@ -1955,11 +1971,11 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) drop: dev->stats.tx_dropped++; dev_kfree_skb_any (skb); - spin_lock_irqsave (&dev->lock, flags); + spin_lock_irqsave(&dev->req_lock, flags); if (list_empty (&dev->tx_reqs)) netif_start_queue (net); list_add (&req->list, &dev->tx_reqs); - spin_unlock_irqrestore (&dev->lock, flags); + spin_unlock_irqrestore(&dev->req_lock, flags); } return 0; } @@ -2378,6 +2394,7 @@ eth_bind (struct usb_gadget *gadget) return status; dev = netdev_priv(net); spin_lock_init (&dev->lock); + spin_lock_init (&dev->req_lock); INIT_WORK (&dev->work, eth_work, dev); INIT_LIST_HEAD (&dev->tx_reqs); INIT_LIST_HEAD (&dev->rx_reqs); diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index 66c3f61bc9d1..431e8f31f1a9 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -372,7 +372,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) * need to change any toggles in this URB */ td = list_entry(urbp->td_list.next, struct uhci_td, list); if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) { - td = list_entry(urbp->td_list.next, struct uhci_td, + td = list_entry(urbp->td_list.prev, struct uhci_td, list); toggle = uhci_toggle(td_token(td)) ^ 1; @@ -1348,7 +1348,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, } uhci_giveback_urb(uhci, qh, urb, regs); - if (status < 0) + if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC) break; } diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index 8ea9c915fbf9..acb24c6219d9 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -1411,17 +1411,54 @@ void hid_init_reports(struct hid_device *hid) warn("timeout initializing reports"); } +#define USB_VENDOR_ID_GTCO 0x078c +#define USB_DEVICE_ID_GTCO_90 0x0090 +#define USB_DEVICE_ID_GTCO_100 0x0100 +#define USB_DEVICE_ID_GTCO_101 0x0101 +#define USB_DEVICE_ID_GTCO_103 0x0103 +#define USB_DEVICE_ID_GTCO_104 0x0104 +#define USB_DEVICE_ID_GTCO_105 0x0105 +#define USB_DEVICE_ID_GTCO_106 0x0106 +#define USB_DEVICE_ID_GTCO_107 0x0107 +#define USB_DEVICE_ID_GTCO_108 0x0108 +#define USB_DEVICE_ID_GTCO_200 0x0200 +#define USB_DEVICE_ID_GTCO_201 0x0201 +#define USB_DEVICE_ID_GTCO_202 0x0202 +#define USB_DEVICE_ID_GTCO_203 0x0203 +#define USB_DEVICE_ID_GTCO_204 0x0204 +#define USB_DEVICE_ID_GTCO_205 0x0205 +#define USB_DEVICE_ID_GTCO_206 0x0206 +#define USB_DEVICE_ID_GTCO_207 0x0207 +#define USB_DEVICE_ID_GTCO_300 0x0300 +#define USB_DEVICE_ID_GTCO_301 0x0301 +#define USB_DEVICE_ID_GTCO_302 0x0302 +#define USB_DEVICE_ID_GTCO_303 0x0303 +#define USB_DEVICE_ID_GTCO_304 0x0304 +#define USB_DEVICE_ID_GTCO_305 0x0305 +#define USB_DEVICE_ID_GTCO_306 0x0306 +#define USB_DEVICE_ID_GTCO_307 0x0307 +#define USB_DEVICE_ID_GTCO_308 0x0308 +#define USB_DEVICE_ID_GTCO_309 0x0309 +#define USB_DEVICE_ID_GTCO_400 0x0400 +#define USB_DEVICE_ID_GTCO_401 0x0401 +#define USB_DEVICE_ID_GTCO_402 0x0402 +#define USB_DEVICE_ID_GTCO_403 0x0403 +#define USB_DEVICE_ID_GTCO_404 0x0404 +#define USB_DEVICE_ID_GTCO_404 0x0405 +#define USB_DEVICE_ID_GTCO_500 0x0500 +#define USB_DEVICE_ID_GTCO_501 0x0501 +#define USB_DEVICE_ID_GTCO_502 0x0502 +#define USB_DEVICE_ID_GTCO_503 0x0503 +#define USB_DEVICE_ID_GTCO_504 0x0504 +#define USB_DEVICE_ID_GTCO_1000 0x1000 +#define USB_DEVICE_ID_GTCO_1001 0x1001 +#define USB_DEVICE_ID_GTCO_1002 0x1002 +#define USB_DEVICE_ID_GTCO_1003 0x1003 +#define USB_DEVICE_ID_GTCO_1004 0x1004 +#define USB_DEVICE_ID_GTCO_1005 0x1005 +#define USB_DEVICE_ID_GTCO_1006 0x1006 + #define USB_VENDOR_ID_WACOM 0x056a -#define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000 -#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 -#define USB_DEVICE_ID_WACOM_INTUOS 0x0020 -#define USB_DEVICE_ID_WACOM_PL 0x0030 -#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040 -#define USB_DEVICE_ID_WACOM_VOLITO 0x0060 -#define USB_DEVICE_ID_WACOM_PTU 0x0003 -#define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 -#define USB_DEVICE_ID_WACOM_CINTIQ 0x003F -#define USB_DEVICE_ID_WACOM_DTF 0x00C0 #define USB_VENDOR_ID_ACECAD 0x0460 #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 @@ -1588,6 +1625,51 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, @@ -1617,49 +1699,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, @@ -1778,6 +1817,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) char *rdesc; int n, len, insize = 0; + /* Ignore all Wacom devices */ + if (dev->descriptor.idVendor == USB_VENDOR_ID_WACOM) + return NULL; + for (n = 0; hid_blacklist[n].idVendor; n++) if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) diff --git a/trunk/drivers/usb/net/pegasus.h b/trunk/drivers/usb/net/pegasus.h index a54752ce1493..006438069b66 100644 --- a/trunk/drivers/usb/net/pegasus.h +++ b/trunk/drivers/usb/net/pegasus.h @@ -131,6 +131,7 @@ struct usb_eth_dev { #define VENDOR_COREGA 0x07aa #define VENDOR_DLINK 0x2001 #define VENDOR_ELCON 0x0db7 +#define VENDOR_ELECOM 0x056e #define VENDOR_ELSA 0x05cc #define VENDOR_GIGABYTE 0x1044 #define VENDOR_HAWKING 0x0e66 @@ -233,6 +234,8 @@ PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) +PEGASUS_DEV( "ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM, 0x4010, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index bd09232ce13c..a72685b96061 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -972,6 +972,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) if (dev) { set_bit(RTL8150_UNPLUG, &dev->flags); tasklet_disable(&dev->tl); + tasklet_kill(&dev->tl); unregister_netdev(dev->netdev); unlink_all_urbs(dev); free_all_urbs(dev); diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index 4a803d69fa36..b130e170b4a8 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -241,16 +241,6 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, "Finecam S5", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), -/* Patch for Kyocera Finecam L3 - * Submitted by Michael Krauth - * and Alessandro Fracchetti - */ -UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, - "Kyocera", - "Finecam L3", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_FIX_INQUIRY), - /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, @@ -599,6 +589,13 @@ UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* floppy reports multiple luns */ +UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, + "SAMSUNG", + "SFD-321U [FW 0C]", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", @@ -1257,6 +1254,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), +/* Reported by Emmanuel Vasilakis */ +UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, + "Sony Ericsson", + "M600i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index 3e827e04a2aa..276a21530b95 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -1801,10 +1801,14 @@ static struct backlight_properties aty128_bl_data = { static void aty128_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty128_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -1828,7 +1832,7 @@ static void aty128_bl_init(struct aty128fb_par *par) bd = backlight_device_register(name, par, &aty128_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("aty128: Backlight registration failed\n"); + printk(KERN_WARNING "aty128: Backlight registration failed\n"); goto error; } @@ -1839,11 +1843,11 @@ static void aty128_bl_init(struct aty128fb_par *par) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = aty128_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 053ff63365b7..19a71f045784 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -2200,10 +2200,14 @@ static struct backlight_properties aty_bl_data = { static void aty_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -2223,7 +2227,7 @@ static void aty_bl_init(struct atyfb_par *par) bd = backlight_device_register(name, par, &aty_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("aty: Backlight registration failed\n"); + printk(KERN_WARNING "aty: Backlight registration failed\n"); goto error; } @@ -2234,11 +2238,11 @@ static void aty_bl_init(struct atyfb_par *par) 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = aty_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/aty/radeon_backlight.c b/trunk/drivers/video/aty/radeon_backlight.c index 1755dddf1899..585eb7b9e636 100644 --- a/trunk/drivers/video/aty/radeon_backlight.c +++ b/trunk/drivers/video/aty/radeon_backlight.c @@ -195,11 +195,11 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); mutex_unlock(&rinfo->info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = radeon_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/nvidia/nv_backlight.c b/trunk/drivers/video/nvidia/nv_backlight.c index b45f577094ac..5b75ae4e9457 100644 --- a/trunk/drivers/video/nvidia/nv_backlight.c +++ b/trunk/drivers/video/nvidia/nv_backlight.c @@ -113,10 +113,14 @@ static struct backlight_properties nvidia_bl_data = { void nvidia_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __nvidia_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __nvidia_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -140,7 +144,7 @@ void nvidia_bl_init(struct nvidia_par *par) bd = backlight_device_register(name, par, &nvidia_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("nvidia: Backlight registration failed\n"); + printk(KERN_WARNING "nvidia: Backlight registration failed\n"); goto error; } @@ -151,11 +155,11 @@ void nvidia_bl_init(struct nvidia_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = nvidia_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/riva/fbdev.c b/trunk/drivers/video/riva/fbdev.c index 76fc9d355eb7..8ddb47a56b07 100644 --- a/trunk/drivers/video/riva/fbdev.c +++ b/trunk/drivers/video/riva/fbdev.c @@ -355,10 +355,14 @@ static struct backlight_properties riva_bl_data = { static void riva_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __riva_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __riva_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -382,7 +386,7 @@ static void riva_bl_init(struct riva_par *par) bd = backlight_device_register(name, par, &riva_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("riva: Backlight registration failed\n"); + printk(KERN_WARNING "riva: Backlight registration failed\n"); goto error; } @@ -393,11 +397,11 @@ static void riva_bl_init(struct riva_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = riva_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/fs/cifs/CHANGES b/trunk/fs/cifs/CHANGES index a61d17ed1827..0feb3bd49cb8 100644 --- a/trunk/fs/cifs/CHANGES +++ b/trunk/fs/cifs/CHANGES @@ -1,3 +1,13 @@ +Version 1.45 +------------ +Do not time out lockw calls when using posix extensions. Do not +time out requests if server still responding reasonably fast +on requests on other threads. Improve POSIX locking emulation, +(lock cancel now works, and unlock of merged range works even +to Windows servers now). Fix oops on mount to lanman servers +(win9x, os/2 etc.) when null password. Do not send listxattr +(SMB to query all EAs) if nouser_xattr specified. + Version 1.44 ------------ Rewritten sessionsetup support, including support for legacy SMB diff --git a/trunk/fs/cifs/README b/trunk/fs/cifs/README index 7986d0d97ace..5f0e1bd64fee 100644 --- a/trunk/fs/cifs/README +++ b/trunk/fs/cifs/README @@ -408,7 +408,7 @@ A partial list of the supported mount options follows: user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended attributes) to the server (default) e.g. via setfattr and getfattr utilities. - nouser_xattr Do not allow getfattr/setfattr to get/set xattrs + nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs mapchars Translate six of the seven reserved characters (not backslash) *?<>|: to the remap range (above 0xF000), which also diff --git a/trunk/fs/cifs/cifsencrypt.c b/trunk/fs/cifs/cifsencrypt.c index a89efaf78a26..4bc250b2d9fc 100644 --- a/trunk/fs/cifs/cifsencrypt.c +++ b/trunk/fs/cifs/cifsencrypt.c @@ -277,7 +277,8 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) return; memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); - strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); + if(ses->password) + strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) if(extended_security & CIFSSEC_MAY_PLNTXT) { diff --git a/trunk/fs/cifs/cifsfs.c b/trunk/fs/cifs/cifsfs.c index c28ede599946..3cd750029be2 100644 --- a/trunk/fs/cifs/cifsfs.c +++ b/trunk/fs/cifs/cifsfs.c @@ -402,7 +402,6 @@ static struct quotactl_ops cifs_quotactl_ops = { }; #endif -#ifdef CONFIG_CIFS_EXPERIMENTAL static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) { struct cifs_sb_info *cifs_sb; @@ -422,7 +421,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) tcon->tidStatus = CifsExiting; up(&tcon->tconSem); - /* cancel_brl_requests(tcon); */ + /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ /* cancel_notify_requests(tcon); */ if(tcon->ses && tcon->ses->server) { @@ -438,7 +437,6 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) return; } -#endif static int cifs_remount(struct super_block *sb, int *flags, char *data) { @@ -457,9 +455,7 @@ struct super_operations cifs_super_ops = { unless later we add lazy close of inodes or unless the kernel forgets to call us with the same number of releases (closes) as opens */ .show_options = cifs_show_options, -#ifdef CONFIG_CIFS_EXPERIMENTAL .umount_begin = cifs_umount_begin, -#endif .remount_fs = cifs_remount, }; diff --git a/trunk/fs/cifs/cifsfs.h b/trunk/fs/cifs/cifsfs.h index 8f75c6f24701..39ee8ef3bdeb 100644 --- a/trunk/fs/cifs/cifsfs.h +++ b/trunk/fs/cifs/cifsfs.h @@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.44" +#define CIFS_VERSION "1.45" #endif /* _CIFSFS_H */ diff --git a/trunk/fs/cifs/cifsglob.h b/trunk/fs/cifs/cifsglob.h index 6d7cf5f3bc0b..b24006c47df1 100644 --- a/trunk/fs/cifs/cifsglob.h +++ b/trunk/fs/cifs/cifsglob.h @@ -3,6 +3,7 @@ * * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) + * Jeremy Allison (jra@samba.org) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -158,7 +159,8 @@ struct TCP_Server_Info { /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; __u32 sequence_number; /* needed for CIFS PDU signature */ - char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; + char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; + unsigned long lstrp; /* when we got last response from this server */ }; /* @@ -266,14 +268,14 @@ struct cifsTconInfo { }; /* - * This info hangs off the cifsFileInfo structure. This is used to track - * byte stream locks on the file + * This info hangs off the cifsFileInfo structure, pointed to by llist. + * This is used to track byte stream locks on the file */ struct cifsLockInfo { - struct cifsLockInfo *next; - int start; - int length; - int type; + struct list_head llist; /* pointer to next cifsLockInfo */ + __u64 offset; + __u64 length; + __u8 type; }; /* @@ -304,6 +306,8 @@ struct cifsFileInfo { /* lock scope id (0 if none) */ struct file * pfile; /* needed for writepage */ struct inode * pInode; /* needed for oplock break */ + struct semaphore lock_sem; + struct list_head llist; /* list of byte range locks we have. */ unsigned closePend:1; /* file is marked to close */ unsigned invalidHandle:1; /* file closed via session abend */ atomic_t wrtPending; /* handle in use - defer close */ diff --git a/trunk/fs/cifs/cifsproto.h b/trunk/fs/cifs/cifsproto.h index a5ddc62d6fe6..b35c55c3c8bb 100644 --- a/trunk/fs/cifs/cifsproto.h +++ b/trunk/fs/cifs/cifsproto.h @@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */ , const int long_op); +extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *, + struct smb_hdr * /* input */ , + struct smb_hdr * /* out */ , + int * /* bytes returned */); extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); diff --git a/trunk/fs/cifs/cifssmb.c b/trunk/fs/cifs/cifssmb.c index 19678c575dfc..075d8fb3d376 100644 --- a/trunk/fs/cifs/cifssmb.c +++ b/trunk/fs/cifs/cifssmb.c @@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) /* BB get server time for time conversions and add code to use it and timezone since this is not UTC */ - if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { + if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { memcpy(server->cryptKey, rsp->EncryptionKey, CIFS_CRYPTO_KEY_SIZE); } else if (server->secMode & SECMODE_PW_ENCRYPT) { @@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMB->hdr.smb_buf_length += count; pSMB->ByteCount = cpu_to_le16(count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + if (waitFlag) { + rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned); + } else { + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, timeout); + } cifs_stats_inc(&tcon->num_locks); if (rc) { cFYI(1, ("Send error in Lock = %d", rc)); @@ -1484,6 +1489,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, char *data_offset; struct cifs_posix_lock *parm_data; int rc = 0; + int timeout = 0; int bytes_returned = 0; __u16 params, param_offset, offset, byte_count, count; @@ -1503,7 +1509,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; - pSMB->Timeout = 0; pSMB->Reserved2 = 0; param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; @@ -1529,8 +1534,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, (((char *) &pSMB->hdr.Protocol) + offset); parm_data->lock_type = cpu_to_le16(lock_type); - if(waitFlag) + if(waitFlag) { + timeout = 3; /* blocking operation, no timeout */ parm_data->lock_flags = cpu_to_le16(1); + pSMB->Timeout = cpu_to_le32(-1); + } else + pSMB->Timeout = 0; + parm_data->pid = cpu_to_le32(current->tgid); parm_data->start = cpu_to_le64(pLockData->fl_start); parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ @@ -1541,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (waitFlag) { + rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned); + } else { + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, timeout); + } + if (rc) { cFYI(1, ("Send error in Posix Lock = %d", rc)); } else if (get_flag) { diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 876eb9ef85fe..5d394c726860 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -182,6 +182,7 @@ cifs_reconnect(struct TCP_Server_Info *server) while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) { + try_to_freeze(); if(server->protocolType == IPV6) { rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket); } else { @@ -612,6 +613,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) #ifdef CONFIG_CIFS_STATS2 mid_entry->when_received = jiffies; #endif + /* so we do not time out requests to server + which is still responding (since server could + be busy but not dead) */ + server->lstrp = jiffies; break; } } @@ -1266,33 +1271,35 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) read_lock(&GlobalSMBSeslock); list_for_each(tmp, &GlobalTreeConnectionList) { - cFYI(1, ("Next tcon - ")); + cFYI(1, ("Next tcon")); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); if (tcon->ses) { if (tcon->ses->server) { cFYI(1, - (" old ip addr: %x == new ip %x ?", + ("old ip addr: %x == new ip %x ?", tcon->ses->server->addr.sockAddr.sin_addr. s_addr, new_target_ip_addr)); if (tcon->ses->server->addr.sockAddr.sin_addr. s_addr == new_target_ip_addr) { - /* BB lock tcon and server and tcp session and increment use count here? */ + /* BB lock tcon, server and tcp session and increment use count here? */ /* found a match on the TCP session */ /* BB check if reconnection needed */ - cFYI(1,("Matched ip, old UNC: %s == new: %s ?", + cFYI(1,("IP match, old UNC: %s new: %s", tcon->treeName, uncName)); if (strncmp (tcon->treeName, uncName, MAX_TREE_SIZE) == 0) { cFYI(1, - ("Matched UNC, old user: %s == new: %s ?", + ("and old usr: %s new: %s", tcon->treeName, uncName)); if (strncmp (tcon->ses->userName, userName, MAX_USERNAME_SIZE) == 0) { read_unlock(&GlobalSMBSeslock); - return tcon;/* also matched user (smb session)*/ + /* matched smb session + (user name */ + return tcon; } } } @@ -1969,7 +1976,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } cFYI(1,("Negotiate caps 0x%x",(int)cap)); - +#ifdef CONFIG_CIFS_DEBUG2 + if(cap & CIFS_UNIX_FCNTL_CAP) + cFYI(1,("FCNTL cap")); + if(cap & CIFS_UNIX_EXTATTR_CAP) + cFYI(1,("EXTATTR cap")); + if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) + cFYI(1,("POSIX path cap")); + if(cap & CIFS_UNIX_XATTR_CAP) + cFYI(1,("XATTR cap")); + if(cap & CIFS_UNIX_POSIX_ACL_CAP) + cFYI(1,("POSIX ACL cap")); +#endif /* CIFS_DEBUG2 */ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { cFYI(1,("setting capabilities failed")); } diff --git a/trunk/fs/cifs/dir.c b/trunk/fs/cifs/dir.c index ba4cbe9b0684..914239d53634 100644 --- a/trunk/fs/cifs/dir.c +++ b/trunk/fs/cifs/dir.c @@ -267,6 +267,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pCifsFile->invalidHandle = FALSE; pCifsFile->closePend = FALSE; init_MUTEX(&pCifsFile->fh_sem); + init_MUTEX(&pCifsFile->lock_sem); + INIT_LIST_HEAD(&pCifsFile->llist); + atomic_set(&pCifsFile->wrtPending,0); + /* set the following in open now pCifsFile->pfile = file; */ write_lock(&GlobalSMBSeslock); diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index 944d2b9e092d..e9c5ba9084fc 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -5,6 +5,7 @@ * * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) + * Jeremy Allison (jra@samba.org) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private( private_data->netfid = netfid; private_data->pid = current->tgid; init_MUTEX(&private_data->fh_sem); + init_MUTEX(&private_data->lock_sem); + INIT_LIST_HEAD(&private_data->llist); private_data->pfile = file; /* needed for writepage */ private_data->pInode = inode; private_data->invalidHandle = FALSE; @@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; if (pSMBFile) { + struct cifsLockInfo *li, *tmp; + pSMBFile->closePend = TRUE; if (pTcon) { /* no sense reconnecting to close a file that is @@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file) pSMBFile->netfid); } } + + /* Delete any outstanding lock records. + We'll lose them when the file is closed anyway. */ + down(&pSMBFile->lock_sem); + list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { + list_del(&li->llist); + kfree(li); + } + up(&pSMBFile->lock_sem); + write_lock(&GlobalSMBSeslock); list_del(&pSMBFile->flist); list_del(&pSMBFile->tlist); @@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file) return rc; } +static int store_file_lock(struct cifsFileInfo *fid, __u64 len, + __u64 offset, __u8 lockType) +{ + struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); + if (li == NULL) + return -ENOMEM; + li->offset = offset; + li->length = len; + li->type = lockType; + down(&fid->lock_sem); + list_add(&li->llist, &fid->llist); + up(&fid->lock_sem); + return 0; +} + int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { int rc, xid; @@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) struct cifsTconInfo *pTcon; __u16 netfid; __u8 lockType = LOCKING_ANDX_LARGE_FILES; + int posix_locking; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -639,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) } netfid = ((struct cifsFileInfo *)file->private_data)->netfid; + posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); /* BB add code here to normalize offset and length to account for negative length which we can not accept over the wire */ if (IS_GETLK(cmd)) { - if(experimEnabled && - (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & - le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + if(posix_locking) { int posix_lock_type; if(lockType & LOCKING_ANDX_SHARED_LOCK) posix_lock_type = CIFS_RDLCK; @@ -683,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return rc; } - if (experimEnabled && - (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & - le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + + if (!numLock && !numUnlock) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } + + if (posix_locking) { int posix_lock_type; if(lockType & LOCKING_ANDX_SHARED_LOCK) posix_lock_type = CIFS_RDLCK; @@ -695,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) if(numUnlock == 1) posix_lock_type = CIFS_UNLCK; - else if(numLock == 0) { - /* if no lock or unlock then nothing - to do since we do not know what it is */ - FreeXid(xid); - return -EOPNOTSUPP; - } + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, length, pfLock, posix_lock_type, wait_flag); - } else - rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, - numUnlock, numLock, lockType, wait_flag); + } else { + struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data; + + if (numLock) { + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + 0, numLock, lockType, wait_flag); + + if (rc == 0) { + /* For Windows locks we must store them. */ + rc = store_file_lock(fid, length, + pfLock->fl_start, lockType); + } + } else if (numUnlock) { + /* For each stored lock that this unlock overlaps + completely, unlock it. */ + int stored_rc = 0; + struct cifsLockInfo *li, *tmp; + + down(&fid->lock_sem); + list_for_each_entry_safe(li, tmp, &fid->llist, llist) { + if (pfLock->fl_start <= li->offset && + length >= li->length) { + stored_rc = CIFSSMBLock(xid, pTcon, netfid, + li->length, li->offset, + 1, 0, li->type, FALSE); + if (stored_rc) + rc = stored_rc; + + list_del(&li->llist); + kfree(li); + } + } + up(&fid->lock_sem); + } + } + if (pfLock->fl_flags & FL_POSIX) posix_lock_file_wait(file, pfLock); FreeXid(xid); diff --git a/trunk/fs/cifs/netmisc.c b/trunk/fs/cifs/netmisc.c index b66eff5dc624..ce87550e918f 100644 --- a/trunk/fs/cifs/netmisc.c +++ b/trunk/fs/cifs/netmisc.c @@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ERRinvlevel,-EOPNOTSUPP}, {ERRdirnotempty, -ENOTEMPTY}, {ERRnotlocked, -ENOLCK}, + {ERRcancelviolation, -ENOLCK}, {ERRalreadyexists, -EEXIST}, {ERRmoredata, -EOVERFLOW}, {ERReasnotsupported,-EOPNOTSUPP}, diff --git a/trunk/fs/cifs/readdir.c b/trunk/fs/cifs/readdir.c index 03bbcb377913..105761e3ba0e 100644 --- a/trunk/fs/cifs/readdir.c +++ b/trunk/fs/cifs/readdir.c @@ -556,7 +556,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) FIND_FILE_STANDARD_INFO * pFindData = (FIND_FILE_STANDARD_INFO *)current_entry; filename = &pFindData->FileName[0]; - len = le32_to_cpu(pFindData->FileNameLength); + len = pFindData->FileNameLength; } else { cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); } diff --git a/trunk/fs/cifs/sess.c b/trunk/fs/cifs/sess.c index 7202d534ef0b..d1705ab8136e 100644 --- a/trunk/fs/cifs/sess.c +++ b/trunk/fs/cifs/sess.c @@ -372,7 +372,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* no capabilities flags in old lanman negotiation */ - pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; + pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); /* BB calculate hash with password */ /* and copy into bcc */ diff --git a/trunk/fs/cifs/smberr.h b/trunk/fs/cifs/smberr.h index cd41c67ff8d3..212c3c296409 100644 --- a/trunk/fs/cifs/smberr.h +++ b/trunk/fs/cifs/smberr.h @@ -95,6 +95,7 @@ #define ERRinvlevel 124 #define ERRdirnotempty 145 #define ERRnotlocked 158 +#define ERRcancelviolation 173 #define ERRalreadyexists 183 #define ERRbadpipe 230 #define ERRpipebusy 231 diff --git a/trunk/fs/cifs/transport.c b/trunk/fs/cifs/transport.c index 17ba329e2b3d..48d47b46b1fb 100644 --- a/trunk/fs/cifs/transport.c +++ b/trunk/fs/cifs/transport.c @@ -3,7 +3,8 @@ * * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) - * + * Jeremy Allison (jra@samba.org) 2006. + * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or @@ -36,7 +37,7 @@ extern mempool_t *cifs_mid_poolp; extern kmem_cache_t *cifs_oplock_cachep; static struct mid_q_entry * -AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) +AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) { struct mid_q_entry *temp; @@ -203,6 +204,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, rc = 0; } + /* Don't want to modify the buffer as a + side effect of this call. */ + smb_buffer->smb_buf_length = smb_buf_length; + return rc; } @@ -217,6 +222,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, unsigned int len = iov[0].iov_len; unsigned int total_len; int first_vec = 0; + unsigned int smb_buf_length = smb_buffer->smb_buf_length; if(ssocket == NULL) return -ENOTSOCK; /* BB eventually add reconnect code here */ @@ -293,36 +299,15 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, } else rc = 0; + /* Don't want to modify the buffer as a + side effect of this call. */ + smb_buffer->smb_buf_length = smb_buf_length; + return rc; } -int -SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, - struct kvec *iov, int n_vec, int * pRespBufType /* ret */, - const int long_op) +static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) { - int rc = 0; - unsigned int receive_len; - unsigned long timeout; - struct mid_q_entry *midQ; - struct smb_hdr *in_buf = iov[0].iov_base; - - *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ - - if ((ses == NULL) || (ses->server == NULL)) { - cifs_small_buf_release(in_buf); - cERROR(1,("Null session")); - return -EIO; - } - - if(ses->server->tcpStatus == CifsExiting) { - cifs_small_buf_release(in_buf); - return -ENOENT; - } - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ if(long_op == -1) { /* oplock breaks must not be held up */ atomic_inc(&ses->server->inFlight); @@ -345,53 +330,140 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } else { if(ses->server->tcpStatus == CifsExiting) { spin_unlock(&GlobalMid_Lock); - cifs_small_buf_release(in_buf); return -ENOENT; } - /* can not count locking commands against total since - they are allowed to block on server */ + /* can not count locking commands against total since + they are allowed to block on server */ - if(long_op < 3) { /* update # of requests on the wire to server */ + if (long_op < 3) atomic_inc(&ses->server->inFlight); - } spin_unlock(&GlobalMid_Lock); break; } } } - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - down(&ses->server->tcpSem); + return 0; +} +static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, + struct mid_q_entry **ppmidQ) +{ if (ses->server->tcpStatus == CifsExiting) { - rc = -ENOENT; - goto out_unlock2; + return -ENOENT; } else if (ses->server->tcpStatus == CifsNeedReconnect) { cFYI(1,("tcp session dead - return to caller to retry")); - rc = -EAGAIN; - goto out_unlock2; + return -EAGAIN; } else if (ses->status != CifsGood) { /* check if SMB session is bad because we are setting it up */ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && (in_buf->Command != SMB_COM_NEGOTIATE)) { - rc = -EAGAIN; - goto out_unlock2; + return -EAGAIN; } /* else ok - we are setting up session */ } - midQ = AllocMidQEntry(in_buf, ses); - if (midQ == NULL) { + *ppmidQ = AllocMidQEntry(in_buf, ses); + if (*ppmidQ == NULL) { + return -ENOMEM; + } + return 0; +} + +static int wait_for_response(struct cifsSesInfo *ses, + struct mid_q_entry *midQ, + unsigned long timeout, + unsigned long time_to_wait) +{ + unsigned long curr_timeout; + + for (;;) { + curr_timeout = timeout + jiffies; + wait_event(ses->server->response_q, + (!(midQ->midState == MID_REQUEST_SUBMITTED)) || + time_after(jiffies, curr_timeout) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + + if (time_after(jiffies, curr_timeout) && + (midQ->midState == MID_REQUEST_SUBMITTED) && + ((ses->server->tcpStatus == CifsGood) || + (ses->server->tcpStatus == CifsNew))) { + + unsigned long lrt; + + /* We timed out. Is the server still + sending replies ? */ + spin_lock(&GlobalMid_Lock); + lrt = ses->server->lstrp; + spin_unlock(&GlobalMid_Lock); + + /* Calculate time_to_wait past last receive time. + Although we prefer not to time out if the + server is still responding - we will time + out if the server takes more than 15 (or 45 + or 180) seconds to respond to this request + and has not responded to any request from + other threads on the client within 10 seconds */ + lrt += time_to_wait; + if (time_after(jiffies, lrt)) { + /* No replies for time_to_wait. */ + cERROR(1,("server not responding")); + return -1; + } + } else { + return 0; + } + } +} + +int +SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, + struct kvec *iov, int n_vec, int * pRespBufType /* ret */, + const int long_op) +{ + int rc = 0; + unsigned int receive_len; + unsigned long timeout; + struct mid_q_entry *midQ; + struct smb_hdr *in_buf = iov[0].iov_base; + + *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ + + if ((ses == NULL) || (ses->server == NULL)) { + cifs_small_buf_release(in_buf); + cERROR(1,("Null session")); + return -EIO; + } + + if(ses->server->tcpStatus == CifsExiting) { + cifs_small_buf_release(in_buf); + return -ENOENT; + } + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + + rc = wait_for_free_request(ses, long_op); + if (rc) { + cifs_small_buf_release(in_buf); + return rc; + } + + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + down(&ses->server->tcpSem); + + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { up(&ses->server->tcpSem); cifs_small_buf_release(in_buf); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } - return -ENOMEM; + /* Update # of requests on wire to server */ + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + return rc; } rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); @@ -406,32 +478,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, atomic_dec(&ses->server->inSend); midQ->when_sent = jiffies; #endif - if(rc < 0) { - DeleteMidQEntry(midQ); - up(&ses->server->tcpSem); - cifs_small_buf_release(in_buf); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } - return rc; - } else { - up(&ses->server->tcpSem); - cifs_small_buf_release(in_buf); - } + + up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + + if(rc < 0) + goto out; if (long_op == -1) - goto cifs_no_response_exit2; + goto out; else if (long_op == 2) /* writes past end of file can take loong time */ timeout = 180 * HZ; else if (long_op == 1) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else if (long_op > 2) { - timeout = MAX_SCHEDULE_TIMEOUT; - } else + else timeout = 15 * HZ; + /* wait for 15 seconds or until woken up due to response arriving or due to last connection to this server being unmounted */ if (signal_pending(current)) { @@ -441,19 +504,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } /* No user interrupts in wait - wreaks havoc with performance */ - if(timeout != MAX_SCHEDULE_TIMEOUT) { - timeout += jiffies; - wait_event(ses->server->response_q, - (!(midQ->midState & MID_REQUEST_SUBMITTED)) || - time_after(jiffies, timeout) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - } else { - wait_event(ses->server->response_q, - (!(midQ->midState & MID_REQUEST_SUBMITTED)) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - } + wait_for_response(ses, midQ, timeout, 10 * HZ); spin_lock(&GlobalMid_Lock); if (midQ->resp_buf) { @@ -481,11 +532,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } spin_unlock(&GlobalMid_Lock); DeleteMidQEntry(midQ); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } + /* Update # of requests on wire to server */ + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -536,24 +585,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, cFYI(1,("Bad MID state?")); } } -cifs_no_response_exit2: - DeleteMidQEntry(midQ); - - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } - return rc; +out: -out_unlock2: - up(&ses->server->tcpSem); - cifs_small_buf_release(in_buf); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } + DeleteMidQEntry(midQ); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -583,85 +620,34 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ - if(long_op == -1) { - /* oplock breaks must not be held up */ - atomic_inc(&ses->server->inFlight); - } else { - spin_lock(&GlobalMid_Lock); - while(1) { - if(atomic_read(&ses->server->inFlight) >= - cifs_max_pending){ - spin_unlock(&GlobalMid_Lock); -#ifdef CONFIG_CIFS_STATS2 - atomic_inc(&ses->server->num_waiters); -#endif - wait_event(ses->server->request_q, - atomic_read(&ses->server->inFlight) - < cifs_max_pending); -#ifdef CONFIG_CIFS_STATS2 - atomic_dec(&ses->server->num_waiters); -#endif - spin_lock(&GlobalMid_Lock); - } else { - if(ses->server->tcpStatus == CifsExiting) { - spin_unlock(&GlobalMid_Lock); - return -ENOENT; - } - /* can not count locking commands against total since - they are allowed to block on server */ - - if(long_op < 3) { - /* update # of requests on the wire to server */ - atomic_inc(&ses->server->inFlight); - } - spin_unlock(&GlobalMid_Lock); - break; - } - } - } + rc = wait_for_free_request(ses, long_op); + if (rc) + return rc; + /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ down(&ses->server->tcpSem); - if (ses->server->tcpStatus == CifsExiting) { - rc = -ENOENT; - goto out_unlock; - } else if (ses->server->tcpStatus == CifsNeedReconnect) { - cFYI(1,("tcp session dead - return to caller to retry")); - rc = -EAGAIN; - goto out_unlock; - } else if (ses->status != CifsGood) { - /* check if SMB session is bad because we are setting it up */ - if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && - (in_buf->Command != SMB_COM_NEGOTIATE)) { - rc = -EAGAIN; - goto out_unlock; - } /* else ok - we are setting up session */ - } - midQ = AllocMidQEntry(in_buf, ses); - if (midQ == NULL) { + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { up(&ses->server->tcpSem); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } - return -ENOMEM; + /* Update # of requests on wire to server */ + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + return rc; } if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - up(&ses->server->tcpSem); cERROR(1, ("Illegal length, greater than maximum frame, %d", in_buf->smb_buf_length)); DeleteMidQEntry(midQ); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } + up(&ses->server->tcpSem); + /* Update # of requests on wire to server */ + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return -EIO; } @@ -677,27 +663,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, atomic_dec(&ses->server->inSend); midQ->when_sent = jiffies; #endif - if(rc < 0) { - DeleteMidQEntry(midQ); - up(&ses->server->tcpSem); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } - return rc; - } else - up(&ses->server->tcpSem); + up(&ses->server->tcpSem); + + if(rc < 0) + goto out; + if (long_op == -1) - goto cifs_no_response_exit; + goto out; else if (long_op == 2) /* writes past end of file can take loong time */ timeout = 180 * HZ; else if (long_op == 1) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else if (long_op > 2) { - timeout = MAX_SCHEDULE_TIMEOUT; - } else + else timeout = 15 * HZ; /* wait for 15 seconds or until woken up due to response arriving or due to last connection to this server being unmounted */ @@ -708,19 +686,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } /* No user interrupts in wait - wreaks havoc with performance */ - if(timeout != MAX_SCHEDULE_TIMEOUT) { - timeout += jiffies; - wait_event(ses->server->response_q, - (!(midQ->midState & MID_REQUEST_SUBMITTED)) || - time_after(jiffies, timeout) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - } else { - wait_event(ses->server->response_q, - (!(midQ->midState & MID_REQUEST_SUBMITTED)) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - } + wait_for_response(ses, midQ, timeout, 10 * HZ); spin_lock(&GlobalMid_Lock); if (midQ->resp_buf) { @@ -748,11 +714,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } spin_unlock(&GlobalMid_Lock); DeleteMidQEntry(midQ); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } + /* Update # of requests on wire to server */ + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -799,23 +763,253 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, cERROR(1,("Bad MID state?")); } } -cifs_no_response_exit: + +out: + DeleteMidQEntry(midQ); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - } + return rc; +} + +/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */ + +static int +send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, + struct mid_q_entry *midQ) +{ + int rc = 0; + struct cifsSesInfo *ses = tcon->ses; + __u16 mid = in_buf->Mid; + header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); + in_buf->Mid = mid; + down(&ses->server->tcpSem); + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); + if (rc) { + up(&ses->server->tcpSem); + return rc; + } + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, + (struct sockaddr *) &(ses->server->addr.sockAddr)); + up(&ses->server->tcpSem); return rc; +} + +/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows + blocking lock to return. */ + +static int +send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, + struct smb_hdr *in_buf, + struct smb_hdr *out_buf) +{ + int bytes_returned; + struct cifsSesInfo *ses = tcon->ses; + LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; + + /* We just modify the current in_buf to change + the type of lock from LOCKING_ANDX_SHARED_LOCK + or LOCKING_ANDX_EXCLUSIVE_LOCK to + LOCKING_ANDX_CANCEL_LOCK. */ + + pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; + pSMB->Timeout = 0; + pSMB->hdr.Mid = GetNextMid(ses->server); + + return SendReceive(xid, ses, in_buf, out_buf, + &bytes_returned, 0); +} -out_unlock: +int +SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, + struct smb_hdr *in_buf, struct smb_hdr *out_buf, + int *pbytes_returned) +{ + int rc = 0; + int rstart = 0; + unsigned int receive_len; + struct mid_q_entry *midQ; + struct cifsSesInfo *ses; + + if (tcon == NULL || tcon->ses == NULL) { + cERROR(1,("Null smb session")); + return -EIO; + } + ses = tcon->ses; + + if(ses->server == NULL) { + cERROR(1,("Null tcp session")); + return -EIO; + } + + if(ses->server->tcpStatus == CifsExiting) + return -ENOENT; + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + + rc = wait_for_free_request(ses, 3); + if (rc) + return rc; + + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + down(&ses->server->tcpSem); + + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { + up(&ses->server->tcpSem); + return rc; + } + + if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + up(&ses->server->tcpSem); + cERROR(1, ("Illegal length, greater than maximum frame, %d", + in_buf->smb_buf_length)); + DeleteMidQEntry(midQ); + return -EIO; + } + + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); + + midQ->midState = MID_REQUEST_SUBMITTED; +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&ses->server->inSend); +#endif + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, + (struct sockaddr *) &(ses->server->addr.sockAddr)); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&ses->server->inSend); + midQ->when_sent = jiffies; +#endif up(&ses->server->tcpSem); - /* If not lock req, update # of requests on wire to server */ - if(long_op < 3) { - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); + + if(rc < 0) { + DeleteMidQEntry(midQ); + return rc; + } + + /* Wait for a reply - allow signals to interrupt. */ + rc = wait_event_interruptible(ses->server->response_q, + (!(midQ->midState == MID_REQUEST_SUBMITTED)) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + + /* Were we interrupted by a signal ? */ + if ((rc == -ERESTARTSYS) && + (midQ->midState == MID_REQUEST_SUBMITTED) && + ((ses->server->tcpStatus == CifsGood) || + (ses->server->tcpStatus == CifsNew))) { + + if (in_buf->Command == SMB_COM_TRANSACTION2) { + /* POSIX lock. We send a NT_CANCEL SMB to cause the + blocking lock to return. */ + + rc = send_nt_cancel(tcon, in_buf, midQ); + if (rc) { + DeleteMidQEntry(midQ); + return rc; + } + } else { + /* Windows lock. We send a LOCKINGX_CANCEL_LOCK + to cause the blocking lock to return. */ + + rc = send_lock_cancel(xid, tcon, in_buf, out_buf); + + /* If we get -ENOLCK back the lock may have + already been removed. Don't exit in this case. */ + if (rc && rc != -ENOLCK) { + DeleteMidQEntry(midQ); + return rc; + } + } + + /* Wait 5 seconds for the response. */ + if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) { + /* We got the response - restart system call. */ + rstart = 1; + } + } + + spin_lock(&GlobalMid_Lock); + if (midQ->resp_buf) { + spin_unlock(&GlobalMid_Lock); + receive_len = midQ->resp_buf->smb_buf_length; + } else { + cERROR(1,("No response for cmd %d mid %d", + midQ->command, midQ->mid)); + if(midQ->midState == MID_REQUEST_SUBMITTED) { + if(ses->server->tcpStatus == CifsExiting) + rc = -EHOSTDOWN; + else { + ses->server->tcpStatus = CifsNeedReconnect; + midQ->midState = MID_RETRY_NEEDED; + } + } + + if (rc != -EHOSTDOWN) { + if(midQ->midState == MID_RETRY_NEEDED) { + rc = -EAGAIN; + cFYI(1,("marking request for retry")); + } else { + rc = -EIO; + } + } + spin_unlock(&GlobalMid_Lock); + DeleteMidQEntry(midQ); + return rc; } + + if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { + cERROR(1, ("Frame too large received. Length: %d Xid: %d", + receive_len, xid)); + rc = -EIO; + } else { /* rcvd frame is ok */ + + if (midQ->resp_buf && out_buf + && (midQ->midState == MID_RESPONSE_RECEIVED)) { + out_buf->smb_buf_length = receive_len; + memcpy((char *)out_buf + 4, + (char *)midQ->resp_buf + 4, + receive_len); + + dump_smb(out_buf, 92); + /* convert the length into a more usable form */ + if((receive_len > 24) && + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | + SECMODE_SIGN_ENABLED))) { + rc = cifs_verify_signature(out_buf, + ses->server->mac_signing_key, + midQ->sequence_number+1); + if(rc) { + cERROR(1,("Unexpected SMB signature")); + /* BB FIXME add code to kill session */ + } + } + + *pbytes_returned = out_buf->smb_buf_length; + + /* BB special case reconnect tid and uid here? */ + rc = map_smb_to_linux_error(out_buf); + /* convert ByteCount if necessary */ + if (receive_len >= + sizeof (struct smb_hdr) - + 4 /* do not count RFC1001 header */ + + (2 * out_buf->WordCount) + 2 /* bcc */ ) + BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); + } else { + rc = -EIO; + cERROR(1,("Bad MID state?")); + } + } + DeleteMidQEntry(midQ); + if (rstart && rc == -EACCES) + return -ERESTARTSYS; return rc; } diff --git a/trunk/fs/cifs/xattr.c b/trunk/fs/cifs/xattr.c index 7754d641775e..067648b7179b 100644 --- a/trunk/fs/cifs/xattr.c +++ b/trunk/fs/cifs/xattr.c @@ -330,11 +330,15 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) sb = direntry->d_inode->i_sb; if(sb == NULL) return -EIO; - xid = GetXid(); cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + return -EOPNOTSUPP; + + xid = GetXid(); + full_path = build_path_from_dentry(direntry); if(full_path == NULL) { FreeXid(xid); diff --git a/trunk/fs/jbd/transaction.c b/trunk/fs/jbd/transaction.c index de2e4cbbf79a..f5169a96260e 100644 --- a/trunk/fs/jbd/transaction.c +++ b/trunk/fs/jbd/transaction.c @@ -727,7 +727,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, out: if (unlikely(frozen_buffer)) /* It's usually NULL */ - kfree(frozen_buffer); + jbd_slab_free(frozen_buffer, bh->b_size); JBUFFER_TRACE(jh, "exit"); return error; diff --git a/trunk/fs/xfs/xfs_bmap.c b/trunk/fs/xfs/xfs_bmap.c index 3a6137539064..bf46fae303af 100644 --- a/trunk/fs/xfs/xfs_bmap.c +++ b/trunk/fs/xfs/xfs_bmap.c @@ -4993,7 +4993,7 @@ xfs_bmapi( bma.firstblock = *firstblock; bma.alen = alen; bma.off = aoff; - bma.conv = (flags & XFS_BMAPI_CONVERT); + bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.minlen = minlen; bma.low = flist->xbf_low; diff --git a/trunk/include/asm-arm/arch-pxa/ssp.h b/trunk/include/asm-arm/arch-pxa/ssp.h index 949878c0d908..ea200551a75f 100644 --- a/trunk/include/asm-arm/arch-pxa/ssp.h +++ b/trunk/include/asm-arm/arch-pxa/ssp.h @@ -40,8 +40,8 @@ struct ssp_dev { }; int ssp_write_word(struct ssp_dev *dev, u32 data); -int ssp_read_word(struct ssp_dev *dev); -void ssp_flush(struct ssp_dev *dev); +int ssp_read_word(struct ssp_dev *dev, u32 *data); +int ssp_flush(struct ssp_dev *dev); void ssp_enable(struct ssp_dev *dev); void ssp_disable(struct ssp_dev *dev); void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); diff --git a/trunk/include/asm-arm/arch-s3c2410/dma.h b/trunk/include/asm-arm/arch-s3c2410/dma.h index 7463fd5252ce..3661e465b0a5 100644 --- a/trunk/include/asm-arm/arch-s3c2410/dma.h +++ b/trunk/include/asm-arm/arch-s3c2410/dma.h @@ -1,18 +1,13 @@ -/* linux/include/asm-arm/arch-bast/dma.h +/* linux/include/asm-arm/arch-s3c2410/dma.h * - * Copyright (C) 2003,2004 Simtec Electronics + * Copyright (C) 2003,2004,2006 Simtec Electronics * Ben Dooks * - * Samsung S3C2410X DMA support + * Samsung S3C241XX DMA support * * 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. - * - * Changelog: - * ??-May-2003 BJD Created file - * ??-Jun-2003 BJD Added more dma functionality to go with arch - * 10-Nov-2004 BJD Added sys_device support */ #ifndef __ASM_ARCH_DMA_H @@ -21,28 +16,26 @@ #include #include "hardware.h" - /* * This is the maximum DMA address(physical address) that can be DMAd to. * */ -#define MAX_DMA_ADDRESS 0x20000000 +#define MAX_DMA_ADDRESS 0x40000000 #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ - /* we have 4 dma channels */ #define S3C2410_DMA_CHANNELS (4) /* types */ -typedef enum { +enum s3c2410_dma_state { S3C2410_DMA_IDLE, S3C2410_DMA_RUNNING, S3C2410_DMA_PAUSED -} s3c2410_dma_state_t; +}; -/* s3c2410_dma_loadst_t +/* enum s3c2410_dma_loadst * * This represents the state of the DMA engine, wrt to the loaded / running * transfers. Since we don't have any way of knowing exactly the state of @@ -70,45 +63,40 @@ typedef enum { * currently running. */ -typedef enum { +enum s3c2410_dma_loadst { S3C2410_DMALOAD_NONE, S3C2410_DMALOAD_1LOADED, S3C2410_DMALOAD_1RUNNING, S3C2410_DMALOAD_1LOADED_1RUNNING, -} s3c2410_dma_loadst_t; +}; -typedef enum { +enum s3c2410_dma_buffresult { S3C2410_RES_OK, S3C2410_RES_ERR, S3C2410_RES_ABORT -} s3c2410_dma_buffresult_t; - - -typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t; +}; -enum s3c2410_dmasrc_e { - S3C2410_DMASRC_HW, /* source is memory */ - S3C2410_DMASRC_MEM /* source is hardware */ +enum s3c2410_dmasrc { + S3C2410_DMASRC_HW, /* source is memory */ + S3C2410_DMASRC_MEM /* source is hardware */ }; -/* enum s3c2410_chan_op_e +/* enum s3c2410_chan_op * * operation codes passed to the DMA code by the user, and also used * to inform the current channel owner of any changes to the system state */ -enum s3c2410_chan_op_e { +enum s3c2410_chan_op { S3C2410_DMAOP_START, S3C2410_DMAOP_STOP, S3C2410_DMAOP_PAUSE, S3C2410_DMAOP_RESUME, S3C2410_DMAOP_FLUSH, - S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ + S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ S3C2410_DMAOP_STARTED, /* indicate channel started */ }; -typedef enum s3c2410_chan_op_e s3c2410_chan_op_t; - /* flags */ #define S3C2410_DMAF_SLOW (1<<0) /* slow, so don't worry about @@ -117,104 +105,100 @@ typedef enum s3c2410_chan_op_e s3c2410_chan_op_t; /* dma buffer */ -typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t; - struct s3c2410_dma_client { char *name; }; -typedef struct s3c2410_dma_client s3c2410_dma_client_t; - /* s3c2410_dma_buf_s * * internally used buffer structure to describe a queued or running * buffer. */ -struct s3c2410_dma_buf_s { - s3c2410_dma_buf_t *next; - int magic; /* magic */ - int size; /* buffer size in bytes */ - dma_addr_t data; /* start of DMA data */ - dma_addr_t ptr; /* where the DMA got to [1] */ - void *id; /* client's id */ +struct s3c2410_dma_buf; +struct s3c2410_dma_buf { + struct s3c2410_dma_buf *next; + int magic; /* magic */ + int size; /* buffer size in bytes */ + dma_addr_t data; /* start of DMA data */ + dma_addr_t ptr; /* where the DMA got to [1] */ + void *id; /* client's id */ }; /* [1] is this updated for both recv/send modes? */ -typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t; +struct s3c2410_dma_chan; /* s3c2410_dma_cbfn_t * * buffer callback routine type */ -typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size, - s3c2410_dma_buffresult_t result); +typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *, + void *buf, int size, + enum s3c2410_dma_buffresult result); -typedef int (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *, - s3c2410_chan_op_t ); +typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *, + enum s3c2410_chan_op ); -struct s3c2410_dma_stats_s { - unsigned long loads; - unsigned long timeout_longest; - unsigned long timeout_shortest; - unsigned long timeout_avg; - unsigned long timeout_failed; +struct s3c2410_dma_stats { + unsigned long loads; + unsigned long timeout_longest; + unsigned long timeout_shortest; + unsigned long timeout_avg; + unsigned long timeout_failed; }; -typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t; - -/* struct s3c2410_dma_chan_s +/* struct s3c2410_dma_chan * * full state information for each DMA channel */ -struct s3c2410_dma_chan_s { +struct s3c2410_dma_chan { /* channel state flags and information */ - unsigned char number; /* number of this dma channel */ - unsigned char in_use; /* channel allocated */ - unsigned char irq_claimed; /* irq claimed for channel */ - unsigned char irq_enabled; /* irq enabled for channel */ - unsigned char xfer_unit; /* size of an transfer */ + unsigned char number; /* number of this dma channel */ + unsigned char in_use; /* channel allocated */ + unsigned char irq_claimed; /* irq claimed for channel */ + unsigned char irq_enabled; /* irq enabled for channel */ + unsigned char xfer_unit; /* size of an transfer */ /* channel state */ - s3c2410_dma_state_t state; - s3c2410_dma_loadst_t load_state; - s3c2410_dma_client_t *client; + enum s3c2410_dma_state state; + enum s3c2410_dma_loadst load_state; + struct s3c2410_dma_client *client; /* channel configuration */ - s3c2410_dmasrc_t source; - unsigned long dev_addr; - unsigned long load_timeout; - unsigned int flags; /* channel flags */ + enum s3c2410_dmasrc source; + unsigned long dev_addr; + unsigned long load_timeout; + unsigned int flags; /* channel flags */ /* channel's hardware position and configuration */ - void __iomem *regs; /* channels registers */ - void __iomem *addr_reg; /* data address register */ - unsigned int irq; /* channel irq */ - unsigned long dcon; /* default value of DCON */ + void __iomem *regs; /* channels registers */ + void __iomem *addr_reg; /* data address register */ + unsigned int irq; /* channel irq */ + unsigned long dcon; /* default value of DCON */ /* driver handles */ - s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */ - s3c2410_dma_opfn_t op_fn; /* channel operation callback */ + s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */ + s3c2410_dma_opfn_t op_fn; /* channel op callback */ /* stats gathering */ - s3c2410_dma_stats_t *stats; - s3c2410_dma_stats_t stats_store; + struct s3c2410_dma_stats *stats; + struct s3c2410_dma_stats stats_store; /* buffer list and information */ - s3c2410_dma_buf_t *curr; /* current dma buffer */ - s3c2410_dma_buf_t *next; /* next buffer to load */ - s3c2410_dma_buf_t *end; /* end of queue */ + struct s3c2410_dma_buf *curr; /* current dma buffer */ + struct s3c2410_dma_buf *next; /* next buffer to load */ + struct s3c2410_dma_buf *end; /* end of queue */ /* system device */ struct sys_device dev; }; /* the currently allocated channel information */ -extern s3c2410_dma_chan_t s3c2410_chans[]; +extern struct s3c2410_dma_chan s3c2410_chans[]; /* note, we don't really use dma_device_t at the moment */ typedef unsigned long dma_device_t; @@ -227,7 +211,7 @@ typedef unsigned long dma_device_t; */ extern int s3c2410_dma_request(dmach_t channel, - s3c2410_dma_client_t *, void *dev); + struct s3c2410_dma_client *, void *dev); /* s3c2410_dma_ctrl @@ -235,7 +219,7 @@ extern int s3c2410_dma_request(dmach_t channel, * change the state of the dma channel */ -extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op); +extern int s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op); /* s3c2410_dma_setflags * @@ -250,7 +234,7 @@ extern int s3c2410_dma_setflags(dmach_t channel, * free the dma channel (will also abort any outstanding operations) */ -extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *); +extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *); /* s3c2410_dma_enqueue * @@ -274,7 +258,7 @@ extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon); * configure the device we're talking to */ -extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source, +extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, int hwcfg, unsigned long devaddr); /* s3c2410_dma_getposition diff --git a/trunk/include/asm-arm/cacheflush.h b/trunk/include/asm-arm/cacheflush.h index fe0c744e0266..e4a2569c636c 100644 --- a/trunk/include/asm-arm/cacheflush.h +++ b/trunk/include/asm-arm/cacheflush.h @@ -247,14 +247,12 @@ extern void dmac_flush_range(unsigned long, unsigned long); */ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ - flush_dcache_page(page); \ + flush_ptrace_access(vma, page, vaddr, dst, len, 1);\ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) @@ -285,10 +283,24 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); } } + +static inline void +flush_ptrace_access(struct vm_area_struct *vma, struct page *page, + unsigned long uaddr, void *kaddr, + unsigned long len, int write) +{ + if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { + unsigned long addr = (unsigned long)kaddr; + __cpuc_coherent_kern_range(addr, addr + len); + } +} #else extern void flush_cache_mm(struct mm_struct *mm); extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); +extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, + unsigned long uaddr, void *kaddr, + unsigned long len, int write); #endif /* diff --git a/trunk/include/asm-arm/hardware/ssp.h b/trunk/include/asm-arm/hardware/ssp.h index 28aa11b769cd..3b42e181997c 100644 --- a/trunk/include/asm-arm/hardware/ssp.h +++ b/trunk/include/asm-arm/hardware/ssp.h @@ -16,8 +16,8 @@ struct ssp_state { }; int ssp_write_word(u16 data); -int ssp_read_word(void); -void ssp_flush(void); +int ssp_read_word(u16 *data); +int ssp_flush(void); void ssp_enable(void); void ssp_disable(void); void ssp_save_state(struct ssp_state *ssp); diff --git a/trunk/include/asm-arm/io.h b/trunk/include/asm-arm/io.h index b3479fc1cc8f..bf7b9dea30f1 100644 --- a/trunk/include/asm-arm/io.h +++ b/trunk/include/asm-arm/io.h @@ -291,5 +291,12 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); */ #define xlate_dev_kmem_ptr(p) p +/* + * Register ISA memory and port locations for glibc iopl/inb/outb + * emulation. + */ +extern void register_isa_ports(unsigned int mmio, unsigned int io, + unsigned int io_shift); + #endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/trunk/include/asm-arm/spinlock.h b/trunk/include/asm-arm/spinlock.h index 406ca97a8ab2..e2f1d75171df 100644 --- a/trunk/include/asm-arm/spinlock.h +++ b/trunk/include/asm-arm/spinlock.h @@ -199,7 +199,21 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw) : "cc"); } -#define __raw_read_trylock(lock) generic__raw_read_trylock(lock) +static inline int __raw_read_trylock(raw_rwlock_t *rw) +{ + unsigned long tmp tmp2 = 1; + + __asm__ __volatile__( +"1: ldrex %0, [%2]\n" +" adds %0, %0, #1\n" +" strexpl %1, %0, [%2]\n" + : "=&r" (tmp), "+r" (tmp2) + : "r" (&rw->lock) + : "cc"); + + smp_mb(); + return tmp2 == 0; +} /* read_can_lock - would read_trylock() succeed? */ #define __raw_read_can_lock(x) ((x)->lock < 0x80000000) diff --git a/trunk/include/asm-i386/alternative.h b/trunk/include/asm-i386/alternative.h index 96adbabec740..b01a7ec409ce 100644 --- a/trunk/include/asm-i386/alternative.h +++ b/trunk/include/asm-i386/alternative.h @@ -88,9 +88,6 @@ static inline void alternatives_smp_switch(int smp) {} /* * Alternative inline assembly for SMP. * - * alternative_smp() takes two versions (SMP first, UP second) and is - * for more complex stuff such as spinlocks. - * * The LOCK_PREFIX macro defined here replaces the LOCK and * LOCK_PREFIX macros used everywhere in the source tree. * @@ -110,21 +107,6 @@ static inline void alternatives_smp_switch(int smp) {} */ #ifdef CONFIG_SMP -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile ("661:\n\t" smpinstr "\n662:\n" \ - ".section .smp_altinstructions,\"a\"\n" \ - " .align 4\n" \ - " .long 661b\n" /* label */ \ - " .long 663f\n" /* new instruction */ \ - " .byte 0x68\n" /* X86_FEATURE_UP */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .smp_altinstr_replacement,\"awx\"\n" \ - "663:\n\t" upinstr "\n" /* replacement */ \ - "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ - ".previous" : args) - #define LOCK_PREFIX \ ".section .smp_locks,\"a\"\n" \ " .align 4\n" \ @@ -133,8 +115,6 @@ static inline void alternatives_smp_switch(int smp) {} "661:\n\tlock; " #else /* ! CONFIG_SMP */ -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile (upinstr : args) #define LOCK_PREFIX "" #endif diff --git a/trunk/include/asm-i386/mach-default/mach_mpspec.h b/trunk/include/asm-i386/mach-default/mach_mpspec.h index 6b5dadcf1d0e..51c9a9775932 100644 --- a/trunk/include/asm-i386/mach-default/mach_mpspec.h +++ b/trunk/include/asm-i386/mach-default/mach_mpspec.h @@ -3,6 +3,10 @@ #define MAX_IRQ_SOURCES 256 +#if CONFIG_BASE_SMALL == 0 +#define MAX_MP_BUSSES 256 +#else #define MAX_MP_BUSSES 32 +#endif #endif /* __ASM_MACH_MPSPEC_H */ diff --git a/trunk/include/asm-i386/rwlock.h b/trunk/include/asm-i386/rwlock.h index 96b0bef2ea56..87c069ccba08 100644 --- a/trunk/include/asm-i386/rwlock.h +++ b/trunk/include/asm-i386/rwlock.h @@ -21,23 +21,21 @@ #define RW_LOCK_BIAS_STR "0x01000000" #define __build_read_lock_ptr(rw, helper) \ - alternative_smp("lock; subl $1,(%0)\n\t" \ + asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" \ "jns 1f\n" \ "call " helper "\n\t" \ - "1:\n", \ - "subl $1,(%0)\n\t", \ - :"a" (rw) : "memory") + "1:\n" \ + ::"a" (rw) : "memory") #define __build_read_lock_const(rw, helper) \ - alternative_smp("lock; subl $1,%0\n\t" \ + asm volatile(LOCK_PREFIX " subl $1,%0\n\t" \ "jns 1f\n" \ "pushl %%eax\n\t" \ "leal %0,%%eax\n\t" \ "call " helper "\n\t" \ "popl %%eax\n\t" \ - "1:\n", \ - "subl $1,%0\n\t", \ - "+m" (*(volatile int *)rw) : : "memory") + "1:\n" \ + :"+m" (*(volatile int *)rw) : : "memory") #define __build_read_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ @@ -47,23 +45,21 @@ } while (0) #define __build_write_lock_ptr(rw, helper) \ - alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ "jz 1f\n" \ "call " helper "\n\t" \ - "1:\n", \ - "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t", \ - :"a" (rw) : "memory") + "1:\n" \ + ::"a" (rw) : "memory") #define __build_write_lock_const(rw, helper) \ - alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ + asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ "jz 1f\n" \ "pushl %%eax\n\t" \ "leal %0,%%eax\n\t" \ "call " helper "\n\t" \ "popl %%eax\n\t" \ - "1:\n", \ - "subl $" RW_LOCK_BIAS_STR ",%0\n\t", \ - "+m" (*(volatile int *)rw) : : "memory") + "1:\n" \ + :"+m" (*(volatile int *)rw) : : "memory") #define __build_write_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ diff --git a/trunk/include/asm-i386/spinlock.h b/trunk/include/asm-i386/spinlock.h index d816c62a7a1d..d1020363c41a 100644 --- a/trunk/include/asm-i386/spinlock.h +++ b/trunk/include/asm-i386/spinlock.h @@ -22,7 +22,7 @@ #define __raw_spin_lock_string \ "\n1:\t" \ - "lock ; decb %0\n\t" \ + LOCK_PREFIX " ; decb %0\n\t" \ "jns 3f\n" \ "2:\t" \ "rep;nop\n\t" \ @@ -38,7 +38,7 @@ */ #define __raw_spin_lock_string_flags \ "\n1:\t" \ - "lock ; decb %0\n\t" \ + LOCK_PREFIX " ; decb %0\n\t" \ "jns 5f\n" \ "2:\t" \ "testl $0x200, %1\n\t" \ @@ -57,15 +57,9 @@ "jmp 4b\n" \ "5:\n\t" -#define __raw_spin_lock_string_up \ - "\n\tdecb %0" - static inline void __raw_spin_lock(raw_spinlock_t *lock) { - alternative_smp( - __raw_spin_lock_string, - __raw_spin_lock_string_up, - "+m" (lock->slock) : : "memory"); + asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory"); } /* @@ -76,10 +70,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) #ifndef CONFIG_PROVE_LOCKING static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) { - alternative_smp( - __raw_spin_lock_string_flags, - __raw_spin_lock_string_up, - "+m" (lock->slock) : "r" (flags) : "memory"); + asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory"); } #endif diff --git a/trunk/include/asm-i386/unistd.h b/trunk/include/asm-i386/unistd.h index fc1c8ddae149..d983b74e4d9f 100644 --- a/trunk/include/asm-i386/unistd.h +++ b/trunk/include/asm-i386/unistd.h @@ -324,8 +324,6 @@ #define __NR_vmsplice 316 #define __NR_move_pages 317 -#ifdef __KERNEL__ - #define NR_syscalls 318 /* @@ -425,6 +423,8 @@ __asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \ __syscall_return(type,__res); \ } +#ifdef __KERNEL__ + #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/trunk/include/asm-i386/unwind.h b/trunk/include/asm-i386/unwind.h index 69f0f1df6722..4c1a0b968569 100644 --- a/trunk/include/asm-i386/unwind.h +++ b/trunk/include/asm-i386/unwind.h @@ -87,6 +87,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info) #else #define UNW_PC(frame) ((void)(frame), 0) +#define UNW_SP(frame) ((void)(frame), 0) static inline int arch_unw_user_mode(const void *info) { diff --git a/trunk/include/asm-ia64/sn/sn_sal.h b/trunk/include/asm-ia64/sn/sn_sal.h index bd4452bda357..ba826b3f75bb 100644 --- a/trunk/include/asm-ia64/sn/sn_sal.h +++ b/trunk/include/asm-ia64/sn/sn_sal.h @@ -706,12 +706,9 @@ static inline int sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array) { struct ia64_sal_retval ret_stuff; - unsigned long irq_flags; - local_irq_save(irq_flags); ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len, (u64)nasid_array, perms, 0, 0, 0); - local_irq_restore(irq_flags); return ret_stuff.status; } #define SN_MEMPROT_ACCESS_CLASS_0 0x14a080 @@ -1143,12 +1140,9 @@ static inline int sn_inject_error(u64 paddr, u64 *data, u64 *ecc) { struct ia64_sal_retval ret_stuff; - unsigned long irq_flags; - local_irq_save(irq_flags); ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data, (u64)ecc, 0, 0, 0, 0); - local_irq_restore(irq_flags); return ret_stuff.status; } diff --git a/trunk/include/asm-ia64/sn/xp.h b/trunk/include/asm-ia64/sn/xp.h index 9bd2f9bf329b..6f807e0193b7 100644 --- a/trunk/include/asm-ia64/sn/xp.h +++ b/trunk/include/asm-ia64/sn/xp.h @@ -60,23 +60,37 @@ * the bte_copy() once in the hope that the failure was due to a temporary * aberration (i.e., the link going down temporarily). * - * See bte_copy for definition of the input parameters. + * src - physical address of the source of the transfer. + * vdst - virtual address of the destination of the transfer. + * len - number of bytes to transfer from source to destination. + * mode - see bte_copy() for definition. + * notification - see bte_copy() for definition. * * Note: xp_bte_copy() should never be called while holding a spinlock. */ static inline bte_result_t -xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) +xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification) { bte_result_t ret; + u64 pdst = ia64_tpa(vdst); - ret = bte_copy(src, dest, len, mode, notification); + /* + * Ensure that the physically mapped memory is contiguous. + * + * We do this by ensuring that the memory is from region 7 only. + * If the need should arise to use memory from one of the other + * regions, then modify the BUG_ON() statement to ensure that the + * memory from that region is always physically contiguous. + */ + BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL); + ret = bte_copy(src, pdst, len, mode, notification); if (ret != BTE_SUCCESS) { if (!in_interrupt()) { cond_resched(); } - ret = bte_copy(src, dest, len, mode, notification); + ret = bte_copy(src, pdst, len, mode, notification); } return ret; diff --git a/trunk/include/asm-ia64/sn/xpc.h b/trunk/include/asm-ia64/sn/xpc.h index b72af597878d..35e1386f37ab 100644 --- a/trunk/include/asm-ia64/sn/xpc.h +++ b/trunk/include/asm-ia64/sn/xpc.h @@ -683,7 +683,9 @@ extern struct xpc_vars *xpc_vars; extern struct xpc_rsvd_page *xpc_rsvd_page; extern struct xpc_vars_part *xpc_vars_part; extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; -extern char xpc_remote_copy_buffer[]; +extern char *xpc_remote_copy_buffer; +extern void *xpc_remote_copy_buffer_base; +extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); extern struct xpc_rsvd_page *xpc_rsvd_page_init(void); extern void xpc_allow_IPI_ops(void); extern void xpc_restrict_IPI_ops(void); diff --git a/trunk/include/asm-powerpc/io.h b/trunk/include/asm-powerpc/io.h index a9496f34b048..36c4c34bf565 100644 --- a/trunk/include/asm-powerpc/io.h +++ b/trunk/include/asm-powerpc/io.h @@ -72,6 +72,9 @@ extern unsigned long pci_io_base; * Neither do the standard versions now, these are just here * for older code. */ +#define insb(port, buf, ns) _insb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define insw(port, buf, ns) _insw_ns((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define insl(port, buf, nl) _insl_ns((u8 __iomem *)((port)+pci_io_base), (buf), (nl)) #define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) #define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) #else @@ -137,12 +140,12 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) #define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) #define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) +#endif + #define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) #define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) #define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) -#endif - #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) diff --git a/trunk/include/asm-powerpc/ipic.h b/trunk/include/asm-powerpc/ipic.h index 0fe396a2b666..53079ec3a515 100644 --- a/trunk/include/asm-powerpc/ipic.h +++ b/trunk/include/asm-powerpc/ipic.h @@ -69,9 +69,6 @@ enum ipic_mcp_irq { IPIC_MCP_MU = 7, }; -extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, - unsigned int irq_offset, - unsigned char *senses, unsigned int senses_count); extern int ipic_set_priority(unsigned int irq, unsigned int priority); extern void ipic_set_highest_priority(unsigned int irq); extern void ipic_set_default_priority(void); @@ -79,7 +76,16 @@ extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq); extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq); extern u32 ipic_get_mcp_status(void); extern void ipic_clear_mcp_status(u32 mask); + +#ifdef CONFIG_PPC_MERGE +extern void ipic_init(struct device_node *node, unsigned int flags); +extern unsigned int ipic_get_irq(struct pt_regs *regs); +#else +extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, + unsigned int irq_offset, + unsigned char *senses, unsigned int senses_count); extern int ipic_get_irq(struct pt_regs *regs); +#endif #endif /* __ASM_IPIC_H__ */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/mpc86xx.h b/trunk/include/asm-powerpc/mpc86xx.h index f260382739fa..b85df45b1a84 100644 --- a/trunk/include/asm-powerpc/mpc86xx.h +++ b/trunk/include/asm-powerpc/mpc86xx.h @@ -23,8 +23,6 @@ #define _ISA_MEM_BASE isa_mem_base #ifdef CONFIG_PCI #define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 #endif #define CPU0_BOOT_RELEASE 0x01000000 @@ -33,7 +31,6 @@ #define MCM_PORT_CONFIG_OFFSET 0x1010 /* Offset from CCSRBAR */ -#define MPC86xx_OPENPIC_OFFSET (0x40000) #define MPC86xx_MCM_OFFSET (0x00000) #define MPC86xx_MCM_SIZE (0x02000) diff --git a/trunk/include/asm-powerpc/mpic.h b/trunk/include/asm-powerpc/mpic.h index eb241c99c457..a9f9604b9eff 100644 --- a/trunk/include/asm-powerpc/mpic.h +++ b/trunk/include/asm-powerpc/mpic.h @@ -41,6 +41,7 @@ #define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0 #define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0 #define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0 +#define MPIC_GREG_IPI_STRIDE 0x10 #define MPIC_GREG_SPURIOUS 0x000e0 #define MPIC_GREG_TIMER_FREQ 0x000f0 @@ -68,6 +69,7 @@ #define MPIC_CPU_IPI_DISPATCH_1 0x00050 #define MPIC_CPU_IPI_DISPATCH_2 0x00060 #define MPIC_CPU_IPI_DISPATCH_3 0x00070 +#define MPIC_CPU_IPI_DISPATCH_STRIDE 0x00010 #define MPIC_CPU_CURRENT_TASK_PRI 0x00080 #define MPIC_CPU_TASKPRI_MASK 0x0000000f #define MPIC_CPU_WHOAMI 0x00090 @@ -114,6 +116,103 @@ #define MPIC_VEC_TIMER_1 248 #define MPIC_VEC_TIMER_0 247 +/* + * Tsi108 implementation of MPIC has many differences from the original one + */ + +/* + * Global registers + */ + +#define TSI108_GREG_BASE 0x00000 +#define TSI108_GREG_FEATURE_0 0x00000 +#define TSI108_GREG_GLOBAL_CONF_0 0x00004 +#define TSI108_GREG_VENDOR_ID 0x0000c +#define TSI108_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */ +#define TSI108_GREG_IPI_STRIDE 0x0c +#define TSI108_GREG_SPURIOUS 0x00010 +#define TSI108_GREG_TIMER_FREQ 0x00014 + +/* + * Timer registers + */ +#define TSI108_TIMER_BASE 0x0030 +#define TSI108_TIMER_STRIDE 0x10 +#define TSI108_TIMER_CURRENT_CNT 0x00000 +#define TSI108_TIMER_BASE_CNT 0x00004 +#define TSI108_TIMER_VECTOR_PRI 0x00008 +#define TSI108_TIMER_DESTINATION 0x0000c + +/* + * Per-Processor registers + */ +#define TSI108_CPU_BASE 0x00300 +#define TSI108_CPU_STRIDE 0x00040 +#define TSI108_CPU_IPI_DISPATCH_0 0x00200 +#define TSI108_CPU_IPI_DISPATCH_STRIDE 0x00000 +#define TSI108_CPU_CURRENT_TASK_PRI 0x00000 +#define TSI108_CPU_WHOAMI 0xffffffff +#define TSI108_CPU_INTACK 0x00004 +#define TSI108_CPU_EOI 0x00008 + +/* + * Per-source registers + */ +#define TSI108_IRQ_BASE 0x00100 +#define TSI108_IRQ_STRIDE 0x00008 +#define TSI108_IRQ_VECTOR_PRI 0x00000 +#define TSI108_VECPRI_VECTOR_MASK 0x000000ff +#define TSI108_VECPRI_POLARITY_POSITIVE 0x01000000 +#define TSI108_VECPRI_POLARITY_NEGATIVE 0x00000000 +#define TSI108_VECPRI_SENSE_LEVEL 0x02000000 +#define TSI108_VECPRI_SENSE_EDGE 0x00000000 +#define TSI108_VECPRI_POLARITY_MASK 0x01000000 +#define TSI108_VECPRI_SENSE_MASK 0x02000000 +#define TSI108_IRQ_DESTINATION 0x00004 + +/* weird mpic register indices and mask bits in the HW info array */ +enum { + MPIC_IDX_GREG_BASE = 0, + MPIC_IDX_GREG_FEATURE_0, + MPIC_IDX_GREG_GLOBAL_CONF_0, + MPIC_IDX_GREG_VENDOR_ID, + MPIC_IDX_GREG_IPI_VECTOR_PRI_0, + MPIC_IDX_GREG_IPI_STRIDE, + MPIC_IDX_GREG_SPURIOUS, + MPIC_IDX_GREG_TIMER_FREQ, + + MPIC_IDX_TIMER_BASE, + MPIC_IDX_TIMER_STRIDE, + MPIC_IDX_TIMER_CURRENT_CNT, + MPIC_IDX_TIMER_BASE_CNT, + MPIC_IDX_TIMER_VECTOR_PRI, + MPIC_IDX_TIMER_DESTINATION, + + MPIC_IDX_CPU_BASE, + MPIC_IDX_CPU_STRIDE, + MPIC_IDX_CPU_IPI_DISPATCH_0, + MPIC_IDX_CPU_IPI_DISPATCH_STRIDE, + MPIC_IDX_CPU_CURRENT_TASK_PRI, + MPIC_IDX_CPU_WHOAMI, + MPIC_IDX_CPU_INTACK, + MPIC_IDX_CPU_EOI, + + MPIC_IDX_IRQ_BASE, + MPIC_IDX_IRQ_STRIDE, + MPIC_IDX_IRQ_VECTOR_PRI, + + MPIC_IDX_VECPRI_VECTOR_MASK, + MPIC_IDX_VECPRI_POLARITY_POSITIVE, + MPIC_IDX_VECPRI_POLARITY_NEGATIVE, + MPIC_IDX_VECPRI_SENSE_LEVEL, + MPIC_IDX_VECPRI_SENSE_EDGE, + MPIC_IDX_VECPRI_POLARITY_MASK, + MPIC_IDX_VECPRI_SENSE_MASK, + MPIC_IDX_IRQ_DESTINATION, + MPIC_IDX_END +}; + + #ifdef CONFIG_MPIC_BROKEN_U3 /* Fixup table entry */ struct mpic_irq_fixup @@ -171,15 +270,29 @@ struct mpic volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS]; volatile u32 __iomem *isus[MPIC_MAX_ISU]; +#ifdef CONFIG_MPIC_WEIRD + /* Pointer to HW info array */ + u32 *hw_set; +#endif + /* link */ struct mpic *next; }; +/* + * MPIC flags (passed to mpic_alloc) + * + * The top 4 bits contain an MPIC bhw id that is used to index the + * register offsets and some masks when CONFIG_MPIC_WEIRD is set. + * Note setting any ID (leaving those bits to 0) means standard MPIC + */ + /* This is the primary controller, only that one has IPIs and * has afinity control. A non-primary MPIC always uses CPU0 * registers only */ #define MPIC_PRIMARY 0x00000001 + /* Set this for a big-endian MPIC */ #define MPIC_BIG_ENDIAN 0x00000002 /* Broken U3 MPIC */ @@ -188,6 +301,18 @@ struct mpic #define MPIC_BROKEN_IPI 0x00000008 /* MPIC wants a reset */ #define MPIC_WANTS_RESET 0x00000010 +/* Spurious vector requires EOI */ +#define MPIC_SPV_EOI 0x00000020 +/* No passthrough disable */ +#define MPIC_NO_PTHROU_DIS 0x00000040 + +/* MPIC HW modification ID */ +#define MPIC_REGSET_MASK 0xf0000000 +#define MPIC_REGSET(val) (((val) & 0xf ) << 28) +#define MPIC_GET_REGSET(flags) (((flags) >> 28) & 0xf) + +#define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */ +#define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ /* Allocate the controller structure and setup the linux irq descs * for the range if interrupts passed in. No HW initialization is diff --git a/trunk/include/asm-powerpc/prom.h b/trunk/include/asm-powerpc/prom.h index b095a285c84b..d0fa1b9aed35 100644 --- a/trunk/include/asm-powerpc/prom.h +++ b/trunk/include/asm-powerpc/prom.h @@ -276,6 +276,7 @@ extern void of_irq_map_init(unsigned int flags); * of_irq_map_raw - Low level interrupt tree parsing * @parent: the device interrupt parent * @intspec: interrupt specifier ("interrupts" property of the device) + * @ointsize: size of the passed in interrupt specifier * @addr: address specifier (start of "reg" property of the device) * @out_irq: structure of_irq filled by this function * @@ -288,7 +289,8 @@ extern void of_irq_map_init(unsigned int flags); * */ -extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, +extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, + u32 ointsize, u32 *addr, struct of_irq *out_irq); diff --git a/trunk/include/asm-powerpc/time.h b/trunk/include/asm-powerpc/time.h index dcde4410348d..5785ac4737b5 100644 --- a/trunk/include/asm-powerpc/time.h +++ b/trunk/include/asm-powerpc/time.h @@ -30,10 +30,6 @@ extern unsigned long tb_ticks_per_usec; extern unsigned long tb_ticks_per_sec; extern u64 tb_to_xs; extern unsigned tb_to_us; -extern unsigned long tb_last_stamp; -extern u64 tb_last_jiffy; - -DECLARE_PER_CPU(unsigned long, last_jiffy); struct rtc_time; extern void to_tm(int tim, struct rtc_time * tm); diff --git a/trunk/include/asm-x86_64/alternative.h b/trunk/include/asm-x86_64/alternative.h index aa67bfd1b3ce..a584826cc570 100644 --- a/trunk/include/asm-x86_64/alternative.h +++ b/trunk/include/asm-x86_64/alternative.h @@ -4,6 +4,7 @@ #ifdef __KERNEL__ #include +#include struct alt_instr { u8 *instr; /* original instruction */ @@ -102,9 +103,6 @@ static inline void alternatives_smp_switch(int smp) {} /* * Alternative inline assembly for SMP. * - * alternative_smp() takes two versions (SMP first, UP second) and is - * for more complex stuff such as spinlocks. - * * The LOCK_PREFIX macro defined here replaces the LOCK and * LOCK_PREFIX macros used everywhere in the source tree. * @@ -124,21 +122,6 @@ static inline void alternatives_smp_switch(int smp) {} */ #ifdef CONFIG_SMP -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile ("661:\n\t" smpinstr "\n662:\n" \ - ".section .smp_altinstructions,\"a\"\n" \ - " .align 8\n" \ - " .quad 661b\n" /* label */ \ - " .quad 663f\n" /* new instruction */ \ - " .byte 0x66\n" /* X86_FEATURE_UP */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .smp_altinstr_replacement,\"awx\"\n" \ - "663:\n\t" upinstr "\n" /* replacement */ \ - "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ - ".previous" : args) - #define LOCK_PREFIX \ ".section .smp_locks,\"a\"\n" \ " .align 8\n" \ @@ -147,8 +130,6 @@ static inline void alternatives_smp_switch(int smp) {} "661:\n\tlock; " #else /* ! CONFIG_SMP */ -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile (upinstr : args) #define LOCK_PREFIX "" #endif diff --git a/trunk/include/asm-x86_64/processor.h b/trunk/include/asm-x86_64/processor.h index 3b3c1217fe61..de9c3147ee4c 100644 --- a/trunk/include/asm-x86_64/processor.h +++ b/trunk/include/asm-x86_64/processor.h @@ -232,8 +232,14 @@ struct tss_struct { unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; } __attribute__((packed)) ____cacheline_aligned; + extern struct cpuinfo_x86 boot_cpu_data; DECLARE_PER_CPU(struct tss_struct,init_tss); +/* Save the original ist values for checking stack pointers during debugging */ +struct orig_ist { + unsigned long ist[7]; +}; +DECLARE_PER_CPU(struct orig_ist, orig_ist); #ifdef CONFIG_X86_VSMP #define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT) diff --git a/trunk/include/asm-x86_64/spinlock.h b/trunk/include/asm-x86_64/spinlock.h index 8d3421996f94..248a79f0eaff 100644 --- a/trunk/include/asm-x86_64/spinlock.h +++ b/trunk/include/asm-x86_64/spinlock.h @@ -21,7 +21,7 @@ #define __raw_spin_lock_string \ "\n1:\t" \ - "lock ; decl %0\n\t" \ + LOCK_PREFIX " ; decl %0\n\t" \ "js 2f\n" \ LOCK_SECTION_START("") \ "2:\t" \ @@ -40,10 +40,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) { - alternative_smp( - __raw_spin_lock_string, - __raw_spin_lock_string_up, - "=m" (lock->slock) : : "memory"); + asm volatile(__raw_spin_lock_string : "=m" (lock->slock) : : "memory"); } #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) @@ -125,12 +122,12 @@ static inline int __raw_write_trylock(raw_rwlock_t *lock) static inline void __raw_read_unlock(raw_rwlock_t *rw) { - asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory"); + asm volatile(LOCK_PREFIX " ; incl %0" :"=m" (rw->lock) : : "memory"); } static inline void __raw_write_unlock(raw_rwlock_t *rw) { - asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0" + asm volatile(LOCK_PREFIX " ; addl $" RW_LOCK_BIAS_STR ",%0" : "=m" (rw->lock) : : "memory"); } diff --git a/trunk/include/asm-x86_64/unistd.h b/trunk/include/asm-x86_64/unistd.h index 94387c915e53..2d89d309a2a8 100644 --- a/trunk/include/asm-x86_64/unistd.h +++ b/trunk/include/asm-x86_64/unistd.h @@ -620,8 +620,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice) #define __NR_move_pages 279 __SYSCALL(__NR_move_pages, sys_move_pages) -#ifdef __KERNEL__ - #define __NR_syscall_max __NR_move_pages #ifndef __NO_STUBS @@ -746,6 +744,8 @@ __syscall_return(type,__res); \ #else /* __KERNEL_SYSCALLS__ */ +#ifdef __KERNEL__ + #include #include @@ -838,9 +838,9 @@ asmlinkage long sys_rt_sigaction(int sig, struct sigaction __user *oact, size_t sigsetsize); -#endif /* __ASSEMBLY__ */ +#endif -#endif /* __NO_STUBS */ +#endif /* * "Conditional" syscalls @@ -850,5 +850,6 @@ asmlinkage long sys_rt_sigaction(int sig, */ #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif /* __KERNEL__ */ +#endif + #endif diff --git a/trunk/include/asm-x86_64/unwind.h b/trunk/include/asm-x86_64/unwind.h index f3e7124effe3..1f6e9bfb569e 100644 --- a/trunk/include/asm-x86_64/unwind.h +++ b/trunk/include/asm-x86_64/unwind.h @@ -95,6 +95,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info) #else #define UNW_PC(frame) ((void)(frame), 0) +#define UNW_SP(frame) ((void)(frame), 0) static inline int arch_unw_user_mode(const void *info) { diff --git a/trunk/include/linux/delayacct.h b/trunk/include/linux/delayacct.h index 11487b6e7127..561e2a77805c 100644 --- a/trunk/include/linux/delayacct.h +++ b/trunk/include/linux/delayacct.h @@ -59,10 +59,14 @@ static inline void delayacct_tsk_init(struct task_struct *tsk) __delayacct_tsk_init(tsk); } -static inline void delayacct_tsk_exit(struct task_struct *tsk) +/* Free tsk->delays. Called from bad fork and __put_task_struct + * where there's no risk of tsk->delays being accessed elsewhere + */ +static inline void delayacct_tsk_free(struct task_struct *tsk) { if (tsk->delays) - __delayacct_tsk_exit(tsk); + kmem_cache_free(delayacct_cache, tsk->delays); + tsk->delays = NULL; } static inline void delayacct_blkio_start(void) @@ -101,7 +105,7 @@ static inline void delayacct_init(void) {} static inline void delayacct_tsk_init(struct task_struct *tsk) {} -static inline void delayacct_tsk_exit(struct task_struct *tsk) +static inline void delayacct_tsk_free(struct task_struct *tsk) {} static inline void delayacct_blkio_start(void) {} diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index 8715305f611f..0ddf16c17b93 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -46,7 +46,7 @@ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_IRQ_TRAP /* define to ack screaming irqs */ #undef ATA_NDEBUG /* define to disable quick runtime checks */ -#define ATA_ENABLE_PATA /* define to enable PATA support in some +#undef ATA_ENABLE_PATA /* define to enable PATA support in some * low-level drivers */ diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index 656b588a9f96..f45163c528e8 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -77,6 +77,7 @@ struct per_cpu_pages { struct per_cpu_pageset { struct per_cpu_pages pcp[2]; /* 0: hot. 1: cold */ #ifdef CONFIG_SMP + s8 stat_threshold; s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; #endif } ____cacheline_aligned_in_smp; diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 4eae06b08cf2..c91164ea3dec 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1292,6 +1292,7 @@ #define PCI_DEVICE_ID_VIA_8367_0 0x3099 #define PCI_DEVICE_ID_VIA_8653_0 0x3101 #define PCI_DEVICE_ID_VIA_8622 0x3102 +#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104 #define PCI_DEVICE_ID_VIA_8233C_0 0x3109 #define PCI_DEVICE_ID_VIA_8361 0x3112 #define PCI_DEVICE_ID_VIA_XM266 0x3116 @@ -1726,6 +1727,9 @@ #define PCI_VENDOR_ID_DOMEX 0x134a #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 +#define PCI_VENDOR_ID_INTASHIELD 0x135a +#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 + #define PCI_VENDOR_ID_QUATECH 0x135C #define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 #define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 6674fc1e51bf..34ed0d99b1bd 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -994,7 +994,6 @@ struct task_struct { */ struct pipe_inode_info *splice_pipe; #ifdef CONFIG_TASK_DELAY_ACCT - spinlock_t delays_lock; struct task_delay_info *delays; #endif }; diff --git a/trunk/kernel/delayacct.c b/trunk/kernel/delayacct.c index 57ca3730205d..36752f124c6a 100644 --- a/trunk/kernel/delayacct.c +++ b/trunk/kernel/delayacct.c @@ -41,24 +41,11 @@ void delayacct_init(void) void __delayacct_tsk_init(struct task_struct *tsk) { - spin_lock_init(&tsk->delays_lock); - /* No need to acquire tsk->delays_lock for allocation here unless - __delayacct_tsk_init called after tsk is attached to tasklist - */ tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); if (tsk->delays) spin_lock_init(&tsk->delays->lock); } -void __delayacct_tsk_exit(struct task_struct *tsk) -{ - struct task_delay_info *delays = tsk->delays; - spin_lock(&tsk->delays_lock); - tsk->delays = NULL; - spin_unlock(&tsk->delays_lock); - kmem_cache_free(delayacct_cache, delays); -} - /* * Start accounting for a delay statistic using * its starting timestamp (@start) @@ -118,8 +105,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) struct timespec ts; unsigned long t1,t2,t3; - spin_lock(&tsk->delays_lock); - /* Though tsk->delays accessed later, early exit avoids * unnecessary returning of other data */ @@ -161,7 +146,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) spin_unlock(&tsk->delays->lock); done: - spin_unlock(&tsk->delays_lock); return 0; } diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index dba194a8d416..d891883420f7 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -908,7 +908,6 @@ fastcall NORET_TYPE void do_exit(long code) audit_free(tsk); taskstats_exit_send(tsk, tidstats, group_dead, mycpu); taskstats_exit_free(tidstats); - delayacct_tsk_exit(tsk); exit_mm(tsk); @@ -1054,7 +1053,7 @@ static int eligible_child(pid_t pid, int options, struct task_struct *p) * Do not consider thread group leaders that are * in a non-empty thread group: */ - if (current->tgid != p->tgid && delay_group_leader(p)) + if (delay_group_leader(p)) return 2; if (security_task_wait(p)) diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index aa36c43783cc..f9b014e3e700 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -117,6 +117,7 @@ void __put_task_struct(struct task_struct *tsk) security_task_free(tsk); free_uid(tsk->user); put_group_info(tsk->group_info); + delayacct_tsk_free(tsk); if (!profile_handoff_task(tsk)) free_task(tsk); @@ -1011,7 +1012,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) - goto bad_fork_cleanup; + goto bad_fork_cleanup_delays_binfmt; INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); @@ -1277,7 +1278,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, bad_fork_cleanup_cpuset: #endif cpuset_exit(p); -bad_fork_cleanup: +bad_fork_cleanup_delays_binfmt: + delayacct_tsk_free(p); if (p->binfmt) module_put(p->binfmt->module); bad_fork_cleanup_put_domain: diff --git a/trunk/kernel/irq/handle.c b/trunk/kernel/irq/handle.c index fc4e906aedbd..48a53f68af96 100644 --- a/trunk/kernel/irq/handle.c +++ b/trunk/kernel/irq/handle.c @@ -20,6 +20,11 @@ /** * handle_bad_irq - handle spurious and unhandled irqs + * @irq: the interrupt number + * @desc: description of the interrupt + * @regs: pointer to a register structure + * + * Handles spurious and unhandled IRQ's. It also prints a debugmessage. */ void fastcall handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index e07e27e846a2..a9963ceddd65 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1176,7 +1176,15 @@ static inline unsigned interleave_nid(struct mempolicy *pol, if (vma) { unsigned long off; - off = vma->vm_pgoff; + /* + * for small pages, there is no difference between + * shift and PAGE_SHIFT, so the bit-shift is safe. + * for huge pages, since vm_pgoff is in units of small + * pages, we need to shift off the always 0 bits to get + * a useful offset. + */ + BUG_ON(shift < PAGE_SHIFT); + off = vma->vm_pgoff >> (shift - PAGE_SHIFT); off += (addr - vma->vm_start) >> shift; return offset_il_node(pol, vma, off); } else diff --git a/trunk/mm/mempool.c b/trunk/mm/mempool.c index fe6e05289cc5..ccd8cb8cd41f 100644 --- a/trunk/mm/mempool.c +++ b/trunk/mm/mempool.c @@ -238,8 +238,13 @@ void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask) init_wait(&wait); prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); smp_mb(); - if (!pool->curr_nr) - io_schedule(); + if (!pool->curr_nr) { + /* + * FIXME: this should be io_schedule(). The timeout is there + * as a workaround for some DM problems in 2.6.18. + */ + io_schedule_timeout(5*HZ); + } finish_wait(&pool->wait, &wait); goto repeat_alloc; diff --git a/trunk/mm/vmstat.c b/trunk/mm/vmstat.c index dfdf24133901..c1b5f4106b38 100644 --- a/trunk/mm/vmstat.c +++ b/trunk/mm/vmstat.c @@ -12,6 +12,7 @@ #include #include #include +#include void __get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free, struct pglist_data *pgdat) @@ -114,17 +115,72 @@ EXPORT_SYMBOL(vm_stat); #ifdef CONFIG_SMP -#define STAT_THRESHOLD 32 +static int calculate_threshold(struct zone *zone) +{ + int threshold; + int mem; /* memory in 128 MB units */ + + /* + * The threshold scales with the number of processors and the amount + * of memory per zone. More memory means that we can defer updates for + * longer, more processors could lead to more contention. + * fls() is used to have a cheap way of logarithmic scaling. + * + * Some sample thresholds: + * + * Threshold Processors (fls) Zonesize fls(mem+1) + * ------------------------------------------------------------------ + * 8 1 1 0.9-1 GB 4 + * 16 2 2 0.9-1 GB 4 + * 20 2 2 1-2 GB 5 + * 24 2 2 2-4 GB 6 + * 28 2 2 4-8 GB 7 + * 32 2 2 8-16 GB 8 + * 4 2 2 <128M 1 + * 30 4 3 2-4 GB 5 + * 48 4 3 8-16 GB 8 + * 32 8 4 1-2 GB 4 + * 32 8 4 0.9-1GB 4 + * 10 16 5 <128M 1 + * 40 16 5 900M 4 + * 70 64 7 2-4 GB 5 + * 84 64 7 4-8 GB 6 + * 108 512 9 4-8 GB 6 + * 125 1024 10 8-16 GB 8 + * 125 1024 10 16-32 GB 9 + */ + + mem = zone->present_pages >> (27 - PAGE_SHIFT); + + threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem)); + + /* + * Maximum threshold is 125 + */ + threshold = min(125, threshold); + + return threshold; +} /* - * Determine pointer to currently valid differential byte given a zone and - * the item number. - * - * Preemption must be off + * Refresh the thresholds for each zone. */ -static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item) +static void refresh_zone_stat_thresholds(void) { - return &zone_pcp(zone, smp_processor_id())->vm_stat_diff[item]; + struct zone *zone; + int cpu; + int threshold; + + for_each_zone(zone) { + + if (!zone->present_pages) + continue; + + threshold = calculate_threshold(zone); + + for_each_online_cpu(cpu) + zone_pcp(zone, cpu)->stat_threshold = threshold; + } } /* @@ -133,17 +189,16 @@ static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item) void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, int delta) { - s8 *p; + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; long x; - p = diff_pointer(zone, item); x = delta + *p; - if (unlikely(x > STAT_THRESHOLD || x < -STAT_THRESHOLD)) { + if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) { zone_page_state_add(x, zone, item); x = 0; } - *p = x; } EXPORT_SYMBOL(__mod_zone_page_state); @@ -172,10 +227,12 @@ EXPORT_SYMBOL(mod_zone_page_state); * No overflow check is necessary and therefore the differential can be * incremented or decremented in place which may allow the compilers to * generate better code. - * * The increment or decrement is known and therefore one boundary check can * be omitted. * + * NOTE: These functions are very performance sensitive. Change only + * with care. + * * Some processors have inc/dec instructions that are atomic vs an interrupt. * However, the code must first determine the differential location in a zone * based on the processor number and then inc/dec the counter. There is no @@ -185,13 +242,16 @@ EXPORT_SYMBOL(mod_zone_page_state); */ static void __inc_zone_state(struct zone *zone, enum zone_stat_item item) { - s8 *p = diff_pointer(zone, item); + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; (*p)++; - if (unlikely(*p > STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; + if (unlikely(*p > pcp->stat_threshold)) { + int overstep = pcp->stat_threshold / 2; + + zone_page_state_add(*p + overstep, zone, item); + *p = -overstep; } } @@ -204,13 +264,16 @@ EXPORT_SYMBOL(__inc_zone_page_state); void __dec_zone_page_state(struct page *page, enum zone_stat_item item) { struct zone *zone = page_zone(page); - s8 *p = diff_pointer(zone, item); + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; (*p)--; - if (unlikely(*p < -STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; + if (unlikely(*p < - pcp->stat_threshold)) { + int overstep = pcp->stat_threshold / 2; + + zone_page_state_add(*p - overstep, zone, item); + *p = overstep; } } EXPORT_SYMBOL(__dec_zone_page_state); @@ -239,19 +302,9 @@ EXPORT_SYMBOL(inc_zone_page_state); void dec_zone_page_state(struct page *page, enum zone_stat_item item) { unsigned long flags; - struct zone *zone; - s8 *p; - zone = page_zone(page); local_irq_save(flags); - p = diff_pointer(zone, item); - - (*p)--; - - if (unlikely(*p < -STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; - } + __dec_zone_page_state(page, item); local_irq_restore(flags); } EXPORT_SYMBOL(dec_zone_page_state); @@ -525,6 +578,10 @@ static int zoneinfo_show(struct seq_file *m, void *arg) pageset->pcp[j].high, pageset->pcp[j].batch); } +#ifdef CONFIG_SMP + seq_printf(m, "\n vm stats threshold: %d", + pageset->stat_threshold); +#endif } seq_printf(m, "\n all_unreclaimable: %u" @@ -613,3 +670,35 @@ struct seq_operations vmstat_op = { #endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_SMP +/* + * Use the cpu notifier to insure that the thresholds are recalculated + * when necessary. + */ +static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_CANCELED: + case CPU_DEAD: + refresh_zone_stat_thresholds(); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata vmstat_notifier = + { &vmstat_cpuup_callback, NULL, 0 }; + +int __init setup_vmstat(void) +{ + refresh_zone_stat_thresholds(); + register_cpu_notifier(&vmstat_notifier); + return 0; +} +module_init(setup_vmstat) +#endif diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 4c20f5546893..a2ede167e045 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -440,6 +440,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) iph = skb->nh.iph; if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) { + IP_INC_STATS(IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dst_mtu(&rt->u.dst))); kfree_skb(skb); diff --git a/trunk/net/ipv4/tcp_cong.c b/trunk/net/ipv4/tcp_cong.c index 5765f9d03174..7ff2e4273a7c 100644 --- a/trunk/net/ipv4/tcp_cong.c +++ b/trunk/net/ipv4/tcp_cong.c @@ -189,7 +189,7 @@ void tcp_slow_start(struct tcp_sock *tp) return; /* We MAY increase by 2 if discovered delayed ack */ - if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) { + if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) { if (tp->snd_cwnd < tp->snd_cwnd_clamp) tp->snd_cwnd++; } diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 104af5d5bcbc..111ff39a08c5 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -2505,8 +2505,13 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (before(ack, prior_snd_una)) goto old_ack; - if (sysctl_tcp_abc && icsk->icsk_ca_state < TCP_CA_CWR) - tp->bytes_acked += ack - prior_snd_una; + if (sysctl_tcp_abc) { + if (icsk->icsk_ca_state < TCP_CA_CWR) + tp->bytes_acked += ack - prior_snd_una; + else if (icsk->icsk_ca_state == TCP_CA_Loss) + /* we assume just one segment left network */ + tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache); + } if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 0c5042e7380d..c7852b38e03e 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -578,6 +578,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, ifa->flags = flags | IFA_F_TENTATIVE; ifa->cstamp = ifa->tstamp = jiffies; + ifa->rt = rt; + ifa->idev = idev; in6_dev_hold(idev); /* For caller */ @@ -603,8 +605,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, } #endif - ifa->rt = rt; - in6_ifa_hold(ifa); write_unlock(&idev->lock); out2: diff --git a/trunk/net/ipv6/exthdrs.c b/trunk/net/ipv6/exthdrs.c index 9d0ee7f0eeb5..86dac106873b 100644 --- a/trunk/net/ipv6/exthdrs.c +++ b/trunk/net/ipv6/exthdrs.c @@ -635,14 +635,17 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, struct ipv6_txoptions *opt2; int err; - if (newtype != IPV6_HOPOPTS && opt->hopopt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); - if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); - if (newtype != IPV6_RTHDR && opt->srcrt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); - if (newtype != IPV6_DSTOPTS && opt->dst1opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); + if (opt) { + if (newtype != IPV6_HOPOPTS && opt->hopopt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); + if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); + if (newtype != IPV6_RTHDR && opt->srcrt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); + if (newtype != IPV6_DSTOPTS && opt->dst1opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); + } + if (newopt && newoptlen) tot_len += CMSG_ALIGN(newoptlen); @@ -659,25 +662,25 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, opt2->tot_len = tot_len; p = (char *)(opt2 + 1); - err = ipv6_renew_option(opt->hopopt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen, newtype != IPV6_HOPOPTS, &opt2->hopopt, &p); if (err) goto out; - err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen, newtype != IPV6_RTHDRDSTOPTS, &opt2->dst0opt, &p); if (err) goto out; - err = ipv6_renew_option(opt->srcrt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen, newtype != IPV6_RTHDR, - (struct ipv6_opt_hdr **)opt2->srcrt, &p); + (struct ipv6_opt_hdr **)&opt2->srcrt, &p); if (err) goto out; - err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen, + err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen, newtype != IPV6_DSTOPTS, &opt2->dst1opt, &p); if (err) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 4b163711f3a8..d9baca062d24 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -1532,6 +1532,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) static int ip6_pkt_discard(struct sk_buff *skb) { + int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); + if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) + IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); kfree_skb(skb); diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index b85c1f9f1288..8b85036ba8e3 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -1273,8 +1273,7 @@ netlink_kernel_create(int unit, unsigned int groups, struct netlink_sock *nlk; unsigned long *listeners = NULL; - if (!nl_table) - return NULL; + BUG_ON(!nl_table); if (unit<0 || unit>=MAX_LINKS) return NULL; @@ -1745,11 +1744,8 @@ static int __init netlink_proto_init(void) netlink_skb_parms_too_large(); nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); - if (!nl_table) { -enomem: - printk(KERN_CRIT "netlink_init: Cannot allocate nl_table\n"); - return -ENOMEM; - } + if (!nl_table) + goto panic; if (num_physpages >= (128 * 1024)) max = num_physpages >> (21 - PAGE_SHIFT); @@ -1769,7 +1765,7 @@ static int __init netlink_proto_init(void) nl_pid_hash_free(nl_table[i].hash.table, 1 * sizeof(*hash->table)); kfree(nl_table); - goto enomem; + goto panic; } memset(hash->table, 0, 1 * sizeof(*hash->table)); hash->max_shift = order; @@ -1786,6 +1782,8 @@ static int __init netlink_proto_init(void) rtnetlink_init(); out: return err; +panic: + panic("netlink_init: Cannot allocate nl_table\n"); } core_initcall(netlink_proto_init); diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index fde3f55bfd4b..dab15949958e 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -1289,9 +1289,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) } } - if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) - sctp_primitive_ABORT(asoc, NULL); - else + if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { + struct sctp_chunk *chunk; + + chunk = sctp_make_abort_user(asoc, NULL, 0); + if (chunk) + sctp_primitive_ABORT(asoc, chunk); + } else sctp_primitive_SHUTDOWN(asoc, NULL); } diff --git a/trunk/net/socket.c b/trunk/net/socket.c index b4848ce0d6ac..6d261bf206fc 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -1178,7 +1178,8 @@ static int __sock_create(int family, int type, int protocol, struct socket **res */ if (!(sock = sock_alloc())) { - printk(KERN_WARNING "socket: no more sockets\n"); + if (net_ratelimit()) + printk(KERN_WARNING "socket: no more sockets\n"); err = -ENFILE; /* Not exactly a match, but its the closest posix thing */ goto out; diff --git a/trunk/sound/oss/Kconfig b/trunk/sound/oss/Kconfig index 1b7c3dfc2b41..97e38b665587 100644 --- a/trunk/sound/oss/Kconfig +++ b/trunk/sound/oss/Kconfig @@ -5,6 +5,20 @@ # # Prompt user for primary drivers. +config OSS_OBSOLETE_DRIVER + bool "Obsolete OSS drivers" + depends on SOUND_PRIME + help + This option enables support for obsolete OSS drivers that + are scheduled for removal in the near future since there + are ALSA drivers for the same hardware. + + Please contact Adrian Bunk if you had to + say Y here because your soundcard is not properly supported + by ALSA. + + If unsure, say N. + config SOUND_BT878 tristate "BT878 audio dma" depends on SOUND_PRIME && PCI @@ -23,7 +37,7 @@ config SOUND_BT878 config SOUND_EMU10K1 tristate "Creative SBLive! (EMU10K1)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER ---help--- Say Y or M if you have a PCI sound card using the EMU10K1 chipset, such as the Creative SBLive!, SB PCI512 or Emu-APS. @@ -49,7 +63,7 @@ config MIDI_EMU10K1 config SOUND_FUSION tristate "Crystal SoundFusion (CS4280/461x)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER help This module drives the Crystal SoundFusion devices (CS4280/46xx series) when wired as native sound drivers with AC97 codecs. If @@ -440,7 +454,7 @@ config SOUND_DMAP config SOUND_AD1816 tristate "AD1816(A) based cards (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOUND_OSS + depends on EXPERIMENTAL && SOUND_OSS && OSS_OBSOLETE_DRIVER help Say M here if you have a sound card based on the Analog Devices AD1816(A) chip. @@ -450,21 +464,21 @@ config SOUND_AD1816 config SOUND_AD1889 tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOUND_OSS && PCI + depends on EXPERIMENTAL && SOUND_OSS && PCI && OSS_OBSOLETE_DRIVER help Say M here if you have a sound card based on the Analog Devices AD1889 chip. config SOUND_ADLIB tristate "Adlib Cards" - depends on SOUND_OSS + depends on SOUND_OSS && OSS_OBSOLETE_DRIVER help Includes ASB 64 4D. Information on programming AdLib cards is available at . config SOUND_ACI_MIXER tristate "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)" - depends on SOUND_OSS + depends on SOUND_OSS && OSS_OBSOLETE_DRIVER ---help--- ACI (Audio Command Interface) is a protocol used to communicate with the microcontroller on some sound cards produced by miro and @@ -586,7 +600,7 @@ config SOUND_MPU401 config SOUND_NM256 tristate "NM256AV/NM256ZX audio support" - depends on SOUND_OSS + depends on SOUND_OSS && OSS_OBSOLETE_DRIVER help Say M here to include audio support for the NeoMagic 256AV/256ZX chipsets. These are the audio chipsets found in the Sony @@ -706,7 +720,7 @@ config SOUND_YM3812 config SOUND_OPL3SA2 tristate "Yamaha OPL3-SA2 and SA3 based PnP cards" - depends on SOUND_OSS + depends on SOUND_OSS && OSS_OBSOLETE_DRIVER help Say Y or M if you have a card based on one of these Yamaha sound chipsets or the "SAx", which is actually a SA3. Read diff --git a/trunk/sound/pci/ac97/ac97_codec.c b/trunk/sound/pci/ac97/ac97_codec.c index 0abf2808d59f..51e83d7a839a 100644 --- a/trunk/sound/pci/ac97/ac97_codec.c +++ b/trunk/sound/pci/ac97/ac97_codec.c @@ -573,7 +573,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = - AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0); + AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; @@ -615,7 +615,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), AC97_ENUM("Mono Output Select", std_enum[2]), -AC97_ENUM("Mic Select Capture Switch", std_enum[3]), +AC97_ENUM("Mic Select", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) };